<> <> <> <> DIRECTORY IO, PropertyLists, Rope; TokenIO: CEDAR DEFINITIONS = BEGIN <> <<>> <> <> <> <> Stopped: ERROR; <<-- Raised if any process calls Stop >> EncodingError: SIGNAL; <<-- All read procedures SIGNAL EncodingError if read token is not as expected; >> <<-- for emergeny error bypassing or debugging, the state may be changed in >> <<-- the debugger and the computation continued; however, normal computation >> <<-- considers EncodingError to be an ERROR, not a SIGNAL. >> <<-->> <<-- The read routines do not have changed the state of the input stream.>> <<>> Handle: TYPE = REF HandleRec; HandleRec: TYPE = --READONLY-- RECORD [ stop: REF BOOL _, --never NIL; stop^ is not considered READONLY <<--private implementor fields which need to be fast>> s: PRIVATE IO.STREAM _ NIL, --reserved for the implementor funny: PRIVATE BOOL _ FALSE, --reserved for the implementor imp: PRIVATE REF ImpRec _ NIL, --reserved for the implementor <<--client fields>> stream: IO.STREAM _ NIL, --for clients, but not automatically initialized clientKey: REF _ NIL, --for clients; represents a key put on properties clientData: REF _ NIL, --for clients; represents context oldVersion: BOOL _ FALSE, --for client: client may switch it to true only properties: REF PropertyLists.PropList _ NIL --don't PutProp from forked processes ]; --[certain features for speed of ChipNDale only] Mark: TYPE = REF; ImpRec: TYPE; Write: PROC [h: Handle, t: Token]; WritePush: PROC [h: Handle, a: ATOM]; WritePush2: PROC [h: Handle, a: ATOM]; WritePop: PROC [h: Handle]; WriteAtom: PROC [h: Handle, a: ATOM]; WriteRope: PROC [h: Handle, r: Rope.ROPE]; WriteInt: PROC [h: Handle, i: INT]; WriteReal: PROC [h: Handle, r: REAL]; WriteStream: PROC [h: Handle] RETURNS [s: IO.STREAM]; <<-- Next writes can be in stream mode>> <<-- Usage of any other write procs finishes stream mode and switches back to token mode >> <<-- Returns always same stream h.stream for same handle ! >> <<-- Do not close, do not use random access>> MarkAndWriteInt: PROC [h: Handle, value: INT_-1] RETURNS [Mark]; <<-- WriteInt and remembers position for later updates>> UpdateMark: PROC [h: Handle, mark: Mark, value: INT]; <<-- Updates value of integer written before>> TType: TYPE = {push, push2, pop, atom, rope, int, real, streamed, endOfStream, error}; Token: TYPE = RECORD [ SELECT type: TType FROM push => [value: ATOM], push2 => [value: ATOM], pop => [value: ATOM], atom => [value: ATOM], rope => [value: Rope.ROPE], int => [value: INT], real => [value: REAL], streamed => [value: REF], endOfStream => [], error => [value: REF], ENDCASE ]; Read: PROC [h: Handle] RETURNS [Token]; ReadAgain: PROC [h: Handle, t: Token]; <<--Causes next call of Read to get t>> <<--Do not use in stream mode except before any real input from stream>> ReadInt: PROC [h: Handle] RETURNS [INT]; ReadAtom: PROC [h: Handle] RETURNS [ATOM]; ReadRope: PROC [h: Handle] RETURNS [Rope.ROPE]; ReadReal: PROC [h: Handle] RETURNS [REAL]; ReadPush: PROC [h: Handle] RETURNS [ATOM]; ReadPush2: PROC [h: Handle] RETURNS [ATOM]; ReadPop: PROC [h: Handle]; ReadStream: PROC [h: Handle] RETURNS [s: IO.STREAM]; <<--Next reads can use stream>> <<--Returns always the same read stream h.stream for the same handle>> <<--Do not close, do not use random access>> <<--It is not possible to read from stream anything which was not written in stream mode>> <<>> Skip: PROC [h: Handle]; <<--if the next token is a pop: no-op>> <<--if the next token is not a pop>> <<-- skips forward on the stream until the next pop is read>> <<-- pairs of push and pop: calls the catcher; >> <<-- pairs of push2 and pop are skipped. >> <<--In stream mode: skips started stream >> <<--Attaching TokenIO to STREAMS>> <<-- while TokenIO is attached to a stream no other operations on this stream must occur >> <<-- otherwise, TokenIO might not be able to read back the clobbered stream. >> CreateReader: PROC [stream: IO.STREAM, stop: REF BOOL_NIL, catcher: PROC [Handle]_NIL] RETURNS [Handle]; <<--EncodingError if stream was not written and closed with TokenIO>> <<--stop: set stop^ to TRUE to stop the reading>> <<--catcher: called implicitely by Skip>> <<>> CreateWriter: PROC [stream: IO.STREAM, stop: REF BOOL_NIL] RETURNS [Handle]; <<--EncodingError if stream does not provide random access>> <<--stop: set stop^ to TRUE to stop the writing>> <<>> Close: PROC [h: Handle, closeStream: BOOL_TRUE]; <<--Closes TokenIO stream >> <<--closeStream: implicit call of IO.Close >> <<--Calling Close is not necessary if writing is supposed to fail >> END.