summaryrefslogtreecommitdiff
path: root/Source/Core/OOLongUtil.ssc
blob: e87666f35bfcbe6af161f73cb830c2085650e526 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//-----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation.  All Rights Reserved.
//
//-----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Contracts;

namespace Boogie.Util {
  public class TeeWriter : TextWriter {
    readonly TextWriter! a;
    readonly TextWriter! b;

    public TeeWriter(TextWriter! a, TextWriter! b) {
      this.a = a;
      this.b = b;
    }

    public override System.Text.Encoding Encoding {
      get {
        return a.Encoding;
      }
    }

    public override void Close() {
      a.Close();
      b.Close();
    }
    
    public override void Flush() {
      a.Flush();
      b.Flush();
    }

    [Pure]
    public override string! ToString() {
      return "<TeeWriter: " + a.ToString() + ", " + b.ToString() + ">";
    }

    public override void Write(char ch) {
      a.Write(ch);
      b.Write(ch);
    }

    public override void Write(string s) {
      a.Write(s);
      b.Write(s);
    }
  }

  /// <summary>
  /// A LineReader is a class that allows further subclasses to just override the ReadLine() method.
  /// It simply reads from the given "reader".
  /// </summary>
  public class LineReader : TextReader {
    [Rep] readonly TextReader! reader;
    string readAhead;
    int readAheadConsumed;
    invariant readAhead == null || (0 <= readAheadConsumed && readAheadConsumed < readAhead.Length);

    public LineReader([Captured] TextReader! reader) {
      this.reader = reader;
    }
    public override void Close() {
      expose (this) {
        reader.Close();
      }
    }
    public override int Read() {
      expose (this) {
        while (readAhead == null) {
          readAhead = reader.ReadLine();
          if (readAhead == null) {
            // we're at EOF
            return -1;
          } else if (readAhead.Length > 0) {
            readAheadConsumed = 0;
            break;
          }
        }
        int res = readAhead[readAheadConsumed++];
        if (readAheadConsumed == readAhead.Length) {
          readAhead = null;
        }
        return res;
      }
    }
    public override int Read(char[]! buffer, int index, int count) {
      int n = 0;
      for (; n < count; n++) {
        int ch = Read();
        if (ch == -1) {
          break;
        }
        buffer[index + n] = (char)ch;
      }
      return n;
    }
    public override string ReadLine() {
      string res;
      if (readAhead != null) {
        expose (this) {
          res = readAhead.Substring(readAheadConsumed);
          readAhead = null;
        }
      } else {
        res = reader.ReadLine();
      }
      return res;
    }
  }

  public class IfdefReader : LineReader {
    [Rep] readonly List<string!>! defines;
    [Rep] readonly List<bool>! readState = new List<bool>();
    int ignoreCutoff = 0;  // 0 means we're not ignoring
    invariant 0 <= ignoreCutoff && ignoreCutoff <= readState.Count;
    
    public IfdefReader([Captured] TextReader! reader, [Captured] List<string!>! defines) {
      base(reader);
      this.defines = defines;
    }
    
    public override string ReadLine() {
      while (true) {
        string s = base.ReadLine();
        if (s == null) {
          return s;
        }
        string t = s.Trim();
        if (t.StartsWith("#if")) {
          string arg = t.Substring(3).TrimStart();
          bool sense = true;
          while (t.StartsWith("!")) {
            sense = !sense;
            t = t.Substring(1).TrimStart();
          }
          // push "true", since we're in a "then" branch
          readState.Add(true);
          if (ignoreCutoff == 0 && defines.Contains(arg) != sense) {
            ignoreCutoff = readState.Count;  // start ignoring
          }
        } else if (t == "#else") {
          if (readState.Count == 0 || !readState[readState.Count-1]) {
            return s;  // malformed input; return the read line as if it were not special
          }
          // change the "true" to a "false" on top of the state, since we're now going into the "else" branch
          readState[readState.Count-1] = false;
          if (ignoreCutoff == 0) {
            // the "then" branch had been included, so we'll ignore the "else" branch
            ignoreCutoff = readState.Count;
          } else if (ignoreCutoff == readState.Count) {
            // we had ignored the "then" branch, so we'll include the "else" branch
            ignoreCutoff = 0;
          }
        } else if (t == "#endif") {
          if (readState.Count == 0) {
            return s;  // malformed input; return the read line as if it were not special
          }
          if (ignoreCutoff == readState.Count) {
            // we had ignored the branch that ends here; so, now we start including again
            ignoreCutoff = 0;
          }
          // pop
          readState.RemoveAt(readState.Count-1);
        } else if (ignoreCutoff == 0) {
          return s;
        }
      }
    }
  }
}