<<>> <> <> <> <> <> <> <> <> <> <> <> <<>> <> DIRECTORY Ascii USING [CR, SP, TAB, LF, BS, ControlA, ControlX, FF, NUL, ESC, DEL, BEL], Atom USING [PropList], Basics USING [FWORD, HWORD, UnsafeBlock], BasicTime USING [GMT, Now, Unpacked], Rope USING [ROPE, UncheckedFlat]; IO: CEDAR DEFINITIONS IMPORTS BasicTime = BEGIN ROPE: TYPE = Rope.ROPE; UnsafeBlock: TYPE = Basics.UnsafeBlock; <> <<>> STREAM: TYPE = REF STREAMRecord; <> <> <<>> StreamVariety: TYPE = {input, output, inputOutput}; <> <> <> EndOfStream: ERROR [stream: STREAM]; Error: ERROR [ec: ErrorCode, stream: STREAM, details: LIST OF REF ¬ NIL, msg: ROPE ¬ NIL]; ErrorCode: TYPE = MACHINE DEPENDENT { Null, <> NotImplementedForThisStream, <> StreamClosed, <> Failure, <> IllegalBackup, <> BufferOverflow, <> BadIndex, <> SyntaxError, <> Overflow, <> PFInvalidCode, <> PFInvalidPFProcs, <> PFCantBindConversionProc, <> PFFormatSyntaxError, <> PFTypeMismatch, <> PFUnprintableValue, < int conversion)>> (BYTE.LAST) }; AtomFromErrorCode: PROC [ErrorCode] RETURNS [ATOM]; ErrorCodeFromAtom: PROC [ATOM] RETURNS [ErrorCode]; Rubout: ERROR [stream: STREAM]; -- Formerly EditedStream.Rubout; <> <<>> Timeout: SIGNAL [which: REF, codes: LIST OF ATOM, msg: ROPE]; <> <> GetInfo: PROC [stream: STREAM] RETURNS [variety: StreamVariety, class: ATOM]; <> GetChar: PROC [self: STREAM] RETURNS [CHAR]; <> <<>> InlineGetChar: PROC [self: STREAM] RETURNS [CHAR] ~ INLINE { i: NAT ~ self.bufferIndex; IF i < self.bufferInputLength THEN { self.bufferIndex ¬ i+1; RETURN[QFetch[self.buffer, i]] } ELSE RETURN[self.streamProcs.getChar[self]]; }; <<>> GetBlock: PROC [self: STREAM, block: REF TEXT, startIndex: NAT ¬ 0, count: NAT ¬ NAT.LAST] RETURNS [nBytesRead: NAT]; < block.maxLength)>> <> <<>> UnsafeGetBlock: UNSAFE PROC [self: STREAM, block: UnsafeBlock] RETURNS [nBytesRead: INT]; <> <> <<>> EndOf: PROC [self: STREAM] RETURNS [BOOL]; <> <<>> InlineEndOf: PROC [self: STREAM] RETURNS [BOOL] ~ INLINE { RETURN[(self.bufferIndex >= self.bufferInputLength) AND self.streamProcs.endOf[self]]; }; <<>> CharsAvail: PROC [self: STREAM, wait: BOOL ¬ FALSE] RETURNS [INT]; <> <<>> Backup: PROC [self: STREAM, char: CHAR]; <> <> <<>> PeekChar: PROC [self: STREAM] RETURNS [CHAR]; <> InlinePeekChar: PROC [self: STREAM] RETURNS [CHAR] ~ INLINE { i: NAT ~ self.bufferIndex; IF i < self.bufferInputLength THEN RETURN[QFetch[self.buffer, i]] ELSE RETURN[PeekChar[self]]; }; <> PutChar: PROC [self: STREAM, char: CHAR]; <> InlinePutChar: PROC [self: STREAM, char: CHAR] ~ INLINE { i: NAT ~ self.bufferIndex; IF i < self.bufferOutputLength THEN { self.bufferIndex ¬ i+1; self.buffer[i] ¬ char } ELSE self.streamProcs.putChar[self, char]; }; PutBlock: PROC [self: STREAM, block: REF READONLY TEXT, startIndex: NAT ¬ 0, count: NAT ¬ NAT.LAST]; < block.maxLength, then set count ¬ block.length-startIndex. Then perform PutChar for each byte in block[startIndex .. startIndex+count).>> <<>> UnsafePutBlock: PROC [self: STREAM, block: UnsafeBlock]; <> <> <<>> Flush: PROC [self: STREAM]; <> <<>> EraseChar: PROC [self: STREAM, char: CHAR]; <> <> Reset: PROC [self: STREAM]; <> <<>> Close: PROC [self: STREAM, abort: BOOL ¬ FALSE]; <> <> GetIndex: PROC [self: STREAM] RETURNS [index: INT]; SetIndex: PROC [self: STREAM, index: INT]; GetLength: PROC [self: STREAM] RETURNS [length: INT]; SetLength: PROC [self: STREAM, length: INT]; <> <> RIS: PROC [rope: ROPE, oldStream: STREAM ¬ NIL] RETURNS [stream: STREAM]; <> ROS: PROC [oldStream: STREAM ¬ NIL] RETURNS [stream: STREAM]; <> RopeFromROS: PROC [self: STREAM, close: BOOL ¬ TRUE] RETURNS [ROPE]; <> <> TIS: PROC [text: REF READONLY TEXT, oldStream: STREAM ¬ NIL] RETURNS [stream: STREAM]; <> <<>> TOS: PROC [text: REF TEXT ¬ NIL, oldStream: STREAM ¬ NIL] RETURNS [stream: STREAM]; <> <<>> TextFromTOS: PROC [self: STREAM] RETURNS [REF TEXT]; <> <> noWhereStream: STREAM; <> <<>> noInputStream: STREAM; <> <<>> <> atom: PROC [v: ATOM] RETURNS [Value] = INLINE {RETURN[[atom[v]]]}; bool: PROC [v: BOOL] RETURNS [Value] = INLINE {RETURN[[boolean[v]]]}; card: PROC [v: CARD] RETURNS [Value] = INLINE {RETURN[[cardinal[v]]]}; char: PROC [v: CHAR] RETURNS [Value] = INLINE {RETURN[[character[v]]]}; dcard: PROC [v: DCARD] RETURNS [Value]; dint: PROC [v: DINT] RETURNS [Value]; dreal: PROC [v: DREAL] RETURNS [Value]; int: PROC [v: INT] RETURNS [Value] = INLINE {RETURN[[integer[v]]]}; real: PROC [v: REAL] RETURNS [Value] = INLINE {RETURN[[real[v]]]}; refAny: PROC [v: REF READONLY ANY] RETURNS [Value] = INLINE {RETURN[[refAny[v]]]}; rope: PROC [v: ROPE] RETURNS [Value] = INLINE {RETURN[[rope[v]]]}; text: PROC [v: REF READONLY TEXT] RETURNS [Value] = INLINE {RETURN[[text[v]]]}; time: PROC [v: BasicTime.GMT ¬ BasicTime.Now[]] RETURNS [Value] = INLINE {RETURN[[time[v]]]}; <> <<>> Put: PROC [stream: STREAM, v1, v2: Value, v3: Value ¬ [null[]]]; Put1: PROC [stream: STREAM, value: Value]; PutR: PROC [v1, v2: Value, v3: Value ¬ [null[]]] RETURNS [ROPE]; PutR1: PROC [value: Value] RETURNS [ROPE]; PutL: PROC [stream: STREAM, list: LIST OF Value]; PutLR: PROC [list: LIST OF Value] RETURNS [ROPE]; <> <> PutF: PROC [stream: STREAM, format: ROPE ¬ NIL, v1, v2: Value, v3: Value ¬ [null[]]]; PutF1: PROC [stream: STREAM, format: ROPE ¬ NIL, value: Value]; PutFR: PROC [format: ROPE ¬ NIL, v1, v2: Value, v3: Value ¬ [null[]]] RETURNS [ROPE]; PutFR1: PROC [format: ROPE ¬ NIL, value: Value] RETURNS [ROPE]; PutFL: PROC [stream: STREAM, format: ROPE ¬ NIL, list: LIST OF Value]; PutFLR: PROC [format: ROPE ¬ NIL, list: LIST OF Value] RETURNS [ROPE]; <> <> <<"This is an integer in a 5 position field: | 17|">> <> <<"This is an integer in a 5 position field: |00017|">> <> <<"This is an integer in a 5 position field: |17 |">> <> <<"This is a floating point number: | 1.23|">> <> <<%b: Print number in octal, with trailing 'B.>> <<%x: Print number in hex, with trailing 'H.>> <<%e: Analogous to FORTRAN E format. Example: "%10.2e".>> <<%f: Analogous to FORTRAN F format. Example: "%-8.3f" (left-justified).>> <<%r: Print the number as a time interval in seconds, with format HH:MM:SS.>> <<%l: For Viewer streams, change looks for subsequent output.>> <<%q: Print the literal representation of the rope, i.e., with escape sequences.>> <> <> <> TokenKind: TYPE = MACHINE DEPENDENT { tokenERROR, -- token.error describes the scanning error tokenID, -- an identifier or reserved word tokenDECIMAL, -- a whole number literal expressed in decimal tokenOCTAL, -- a whole number literal expressed in octal tokenHEX, -- a whole number literal expressed in hexidecimal tokenREAL, -- a REAL literal tokenROPE, -- a ROPE, REF TEXT, or STRING literal tokenCHAR, -- a CHAR literal tokenATOM, -- an ATOM literal tokenSINGLE, -- a single-character token tokenDOUBLE, -- a double-character token tokenCOMMENT, -- a comment tokenEOF, -- the end-of-file marker (BYTE.LAST) -- room for extensions }; AtomFromTokenKind: PROC [TokenKind] RETURNS [ATOM]; TokenKindFromAtom: PROC [ATOM] RETURNS [TokenKind]; TokenError: TYPE = MACHINE DEPENDENT { none, -- no error extendedChar, -- error following backslash in char or string literal numericLiteral, charLiteral, stringLiteral, atomLiteral, -- error in parsing indicated type singleChar, -- first non-whitespace char is not legal as first char of token (BYTE.LAST) -- room for extensions }; AtomFromTokenError: PROC [TokenError] RETURNS [ATOM]; TokenErrorFromAtom: PROC [ATOM] RETURNS [TokenError]; GetCedarToken: PROC [stream: STREAM, buffer: REF TEXT, flushComments: BOOL ¬ TRUE] RETURNS [tokenKind: TokenKind, token: REF TEXT, charsSkipped: INT, error: TokenError]; <> <> GetCedarTokenRope: PROC [stream: STREAM, flushComments: BOOL ¬ TRUE] RETURNS [tokenKind: TokenKind, token: ROPE, charsSkipped: INT]; <> <> <> GetInt: PROC [stream: STREAM] RETURNS [INT]; GetCard: PROC [stream: STREAM] RETURNS [CARD]; GetReal: PROC [stream: STREAM] RETURNS [REAL]; GetDReal: PROC [stream: STREAM] RETURNS [DREAL]; GetBool: PROC [stream: STREAM] RETURNS [BOOL]; GetAtom: PROC [stream: STREAM] RETURNS [ATOM]; GetRopeLiteral: PROC [stream: STREAM] RETURNS [ROPE]; GetCharLiteral: PROC [stream: STREAM] RETURNS [CHAR]; GetID: PROC [stream: STREAM] RETURNS [ROPE]; <> GetTime: PROC [stream: STREAM] RETURNS [BasicTime.GMT]; GetUnpackedTime: PROC [stream: STREAM] RETURNS [BasicTime.Unpacked]; <> GetRefAny: PROC [stream: STREAM] RETURNS [REF ANY]; <> <<'( starts a list (LIST OF REF ANY), ') terminates a list,>> <<'+, '- are unary operators that may precede a numeric literal,>> <<', is ignored between elements of a list,>> <<'^ is always ignored.>> GetRefAnyLine: PROC [stream: STREAM] RETURNS [LIST OF REF ANY]; <> <<>> <> SkipWhitespace: PROC [stream: STREAM, flushComments: BOOL ¬ TRUE] RETURNS [charsSkipped: INT]; <> <<>> GetToken: PROC [stream: STREAM, breakProc: BreakProc ¬ TokenProc, buffer: REF TEXT] RETURNS [token: REF TEXT, charsSkipped: INT]; <> <> CharClass: TYPE = {break, sepr, other}; BreakProc: TYPE = PROC [char: CHAR] RETURNS [CharClass]; TokenProc: BreakProc; <> < sepr,>> <<'[, '], '(, '), '{, '}, '", '+, '-, '*, '/, '@, '¬ => break,>> < other]};>> <> IDProc: BreakProc; <> < sepr,>> < other]};>> <> <<>> GetTokenRope: PROC [stream: STREAM, breakProc: BreakProc ¬ TokenProc] RETURNS [token: ROPE, charsSkipped: INT]; <> <> <<>> GetLine: PROC [stream: STREAM, buffer: REF TEXT] RETURNS [line: REF TEXT]; <> <> <<>> GetLineRope: PROC [stream: STREAM] RETURNS [line: ROPE]; <> <> <> GetRope: PROC [self: STREAM, len: INT ¬ INT.LAST, demand: BOOL ¬ FALSE] RETURNS [ROPE]; <> <> <<>> PutRope: PROC [self: STREAM, r: ROPE, start: INT ¬ 0, len: INT ¬ INT.LAST]; <> <> <> GetText: PROC [self: STREAM, len: NAT, buffer: REF TEXT ¬ NIL] RETURNS [REF TEXT]; <> PutText: PROC [self: STREAM, t: REF READONLY TEXT]; <> GetByte: PROC [self: STREAM] RETURNS [BYTE] ~ INLINE { RETURN [ORD[GetChar[self]]] }; InlineGetByte: PROC [self: STREAM] RETURNS [BYTE] ~ INLINE { RETURN [ORD[InlineGetChar[self]]] }; PutByte: PROC [self: STREAM, byte: BYTE] ~ INLINE { PutChar[self, VAL[byte]] }; InlinePutByte: PROC [self: STREAM, byte: BYTE] ~ INLINE { InlinePutChar[self, VAL[byte]] }; GetHWord: PROC [self: STREAM] RETURNS [hword: Basics.HWORD]; PutHWord: PROC [self: STREAM, hword: Basics.HWORD]; GetFWord: PROC [self: STREAM] RETURNS [fword: Basics.FWORD]; PutFWord: PROC [self: STREAM, fword: Basics.FWORD]; <> BS: CHAR = Ascii.BS; -- '\b TAB: CHAR = Ascii.TAB; -- '\t LF: CHAR = Ascii.LF; -- '\l FF: CHAR = Ascii.FF; -- '\f CR: CHAR = Ascii.CR; -- '\r NUL: CHAR = Ascii.NUL; ControlA: CHAR = Ascii.ControlA; BEL: CHAR = Ascii.BEL; ControlX: CHAR = Ascii.ControlX; ESC: CHAR = Ascii.ESC; SP: CHAR = Ascii.SP; DEL: CHAR = Ascii.DEL; <> <> <<>> GetCharProc: TYPE ~ PROC [self: STREAM] RETURNS [CHAR]; GetBlockProc: TYPE ~ PROC [self: STREAM, block: REF TEXT, startIndex: NAT, count: NAT] RETURNS [nBytesRead: NAT]; UnsafeGetBlockProc: TYPE ~ UNSAFE PROC [self: STREAM, block: UnsafeBlock] RETURNS [nBytesRead: INT]; EndOfProc: TYPE ~ PROC [self: STREAM] RETURNS [BOOL]; CharsAvailProc: TYPE ~ PROC [self: STREAM, wait: BOOL] RETURNS [INT]; BackupProc: TYPE ~ PROC [self: STREAM, char: CHAR]; PutCharProc: TYPE ~ PROC [self: STREAM, char: CHAR]; PutBlockProc: TYPE ~ PROC [self: STREAM, block: REF READONLY TEXT, startIndex: NAT, count: NAT]; UnsafePutBlockProc: TYPE ~ PROC [self: STREAM, block: UnsafeBlock]; FlushProc: TYPE ~ PROC [self: STREAM]; ResetProc: TYPE ~ PROC [self: STREAM]; CloseProc: TYPE ~ PROC [self: STREAM, abort: BOOL]; GetIndexProc: TYPE ~ PROC [self: STREAM] RETURNS [INT]; SetIndexProc: TYPE ~ PROC [self: STREAM, index: INT]; GetLengthProc: TYPE ~ PROC [self: STREAM] RETURNS [INT]; SetLengthProc: TYPE ~ PROC [self: STREAM, length: INT]; EraseCharProc: TYPE ~ PROC [self: STREAM, char: CHAR]; CreateStreamProcs: PROC [ variety: StreamVariety, class: ATOM, getChar: GetCharProc ¬ NIL, getBlock: GetBlockProc ¬ NIL, unsafeGetBlock: UnsafeGetBlockProc ¬ NIL, endOf: EndOfProc ¬ NIL, charsAvail: CharsAvailProc ¬ NIL, backup: BackupProc ¬ NIL, putChar: PutCharProc ¬ NIL, putBlock: PutBlockProc ¬ NIL, unsafePutBlock: UnsafePutBlockProc ¬ NIL, flush: FlushProc ¬ NIL, reset: ResetProc ¬ NIL, close: CloseProc ¬ NIL, getIndex: GetIndexProc ¬ NIL, setIndex: SetIndexProc ¬ NIL, getLength: GetLengthProc ¬ NIL, setLength: SetLengthProc ¬ NIL, eraseChar: EraseCharProc ¬ NIL ] RETURNS [REF StreamProcs]; CreateStream: PROC [streamProcs: REF StreamProcs, streamData: REF ANY, backingStream: STREAM ¬ NIL] RETURNS [stream: STREAM]; <> STREAMRecord: TYPE = RECORD [ streamProcs: REF StreamProcs, -- the stream procedures streamData: REF ANY ¬ NIL, -- instance data, type is specific to the stream class propList: Atom.PropList ¬ NIL, -- instance data, type is independent of the stream class backingStream: STREAM ¬ NIL, -- distinguished instance data, used to "layer" streams <> buffer: REF TEXT ¬ NIL, bufferInputLength: NAT ¬ 0, bufferOutputLength: NAT ¬ 0, bufferIndex: NAT ¬ 0 ]; StreamProcs: TYPE = PRIVATE RECORD [ getChar: GetCharProc, getBlock: GetBlockProc, unsafeGetBlock: UnsafeGetBlockProc, endOf: EndOfProc, charsAvail: CharsAvailProc, backup: BackupProc, putChar: PutCharProc, putBlock: PutBlockProc, unsafePutBlock: UnsafePutBlockProc, flush: FlushProc, reset: ResetProc, close: CloseProc, getIndex: GetIndexProc, setIndex: SetIndexProc, getLength: GetLengthProc, setLength: SetLengthProc, eraseChar: EraseCharProc, propList: Atom.PropList, variety: StreamVariety, class: ATOM ]; Value: TYPE = RECORD [ SELECT type: ValueType FROM null => NULL, atom => [value: ATOM], boolean => [value: BOOL], character => [value: CHAR], cardinal => [value: CARD], integer => [value: INT], dint => [value: REF DINT], -- indirection keeps size of IO.Value small dcard => [value: REF DCARD], real => [value: REAL], dreal => [value: REF DREAL], refAny => [value: REF READONLY ANY], rope => [value: ROPE], text => [value: REF READONLY TEXT], time => [value: BasicTime.GMT], ENDCASE ]; ValueType: TYPE = {null, atom, boolean, character, cardinal, integer, dint, dcard, real, dreal, refAny, rope, text, time}; QFetch: PRIVATE PROC [buffer: REF READONLY TEXT, i: NAT] RETURNS [CHAR] ~ INLINE { <> TRUSTED { RETURN [LOOPHOLE[buffer, Rope.UncheckedFlat][i]] }; }; <<>> <<>> END.