DIRECTORY FileIO USING [Open], IO USING [Close, PutRope, STREAM], IPBasic USING [PrimitiveOrSymbol, Rational], IPEncoding USING [Reader, ReaderProcs, ReadProc, Token, TokenType, Version, WriteProc, Writer, WriterProcs], Rope USING [ActionType, Concat, Equal, Map, ROPE, Substr], RopeIO USING [FromFile], RopeReader USING [Backwards, Create, Get, GetIndex, GetRope, Peek, Ref, SetIndex, SetPosition]; IPEncodingImpl: CEDAR PROGRAM IMPORTS FileIO, IO, Rope, RopeIO, RopeReader EXPORTS IPEncoding = BEGIN OPEN IPEncoding, IPBasic; ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; Node: TYPE = REF NodeRep; NodeRep: TYPE = RECORD[ next: Node, encoding: ROPE, -- name of the encoding version: Version, -- version number read: ReadProc, write: WriteProc ]; encodingList: Node _ NIL; -- head of the list of registered encodings Error: PUBLIC ERROR[message: ROPE] = CODE; closedReaderProcs: REF READONLY ReaderProcs = NEW[ReaderProcs = [ GetToken: ClosedGetToken, GetInt: ClosedGetInt, GetRational: ClosedGetRational, GetReal: ClosedGetReal, GetRope: ClosedGetRope ]]; closedWriterProcs: REF READONLY WriterProcs = NEW[WriterProcs = [ PutOp: ClosedPutOp, PutInt: ClosedPutInt, PutRational: ClosedPutRational, PutReal: ClosedPutReal, PutRope: ClosedPutRope ]]; ClosedGetToken: PROC[self: Reader, index: INT] RETURNS[Token] = { ERROR Error["closed"] }; ClosedGetInt: PROC[self: Reader, token: Token] RETURNS[INT] = { ERROR Error["closed"] }; ClosedGetRational: PROC[self: Reader, token: Token] RETURNS[Rational] = { ERROR Error["closed"] }; ClosedGetReal: PROC[self: Reader, token: Token] RETURNS[REAL] = { ERROR Error["closed"] }; ClosedGetRope: PROC[self: Reader, token: Token] RETURNS[ROPE] = { ERROR Error["closed"] }; ClosedPutOp: PROC[self: Writer, op: PrimitiveOrSymbol] = { ERROR Error["closed"] }; ClosedPutInt: PROC[self: Writer, i: INT] = { ERROR Error["closed"] }; ClosedPutRational: PROC[self: Writer, r: Rational] = { ERROR Error["closed"] }; ClosedPutReal: PROC[self: Writer, r: REAL] = { ERROR Error["closed"] }; ClosedPutRope: PROC[self: Writer, type: TokenType, text: ROPE] = { ERROR Error["closed"] }; OpenReader: PUBLIC PROC[fileName: ROPE] RETURNS[reader: Reader] = { encoding: ROPE _ NIL; version: Version _ [0,0]; ropeReader: RopeReader.Ref _ NIL; rope: ROPE _ RopeIO.FromFile[fileName]; ropeReader _ RopeReader.Create[]; ropeReader.SetPosition[rope, 0]; [encoding, version] _ ParseHeader[ropeReader]; RETURN[CreateReader[encoding, ropeReader]]; }; CreateReader: PUBLIC PROC[encoding: ROPE, ropeReader: RopeReader.Ref] RETURNS[Reader] = { node: Node = Find[encoding]; IF node=NIL THEN ERROR Error[Rope.Concat["unknown encoding: ", encoding]] ELSE { reader: Reader = node.read[ropeReader]; RETURN[reader] }; }; herald: ROPE = "Interpress/"; ParseHeader: PROC[reader: RopeReader.Ref] RETURNS[encoding: ROPE, version: Version] = { SkipIf: PROC[char: CHAR] = { IF reader.Peek[]=char THEN [] _ reader.Get[]; }; Match: PROC[rope: ROPE] RETURNS[BOOL] = { Action: Rope.ActionType = { RETURN[reader.Get[]#c] }; RETURN[NOT Rope.Map[base: rope, action: Action]]; }; SkipTo: PROC[char: CHAR] = { DO IF reader.Get[]=char THEN EXIT ENDLOOP; }; BackOver: PROC[char: CHAR] = { IF reader.Backwards[]#char THEN ERROR; }; BackNumber: PROC[end: CHAR] RETURNS[NAT] = { f: NAT _ 0; n: NAT _ 0; DO c: CHAR = reader.Backwards[]; IF c IN['0..'9] THEN { IF f=0 THEN f _ 1 ELSE IF f<1000 THEN f _ 10*f ELSE ERROR Error["version number too big"]; n _ n+(c-'0)*f; } ELSE IF c=end THEN EXIT ELSE ERROR Error["malformed version number"]; ENDLOOP; RETURN[n]; }; enc, stop: INT _ 0; GetIndex: PROC RETURNS[INT] = { RETURN[reader.GetIndex[]] }; SetIndex: PROC[index: INT] = { reader.SetIndex[index] }; SubString: PROC[start, stop: INT] RETURNS[ROPE] = { rope: ROPE = reader.GetRope[]; RETURN[Rope.Substr[rope, start, stop-start]]; }; SkipIf['\n]; -- ignore possible cr inserted by Tioga IF NOT Match[herald] THEN ERROR Error["not an Interpress master"]; enc _ GetIndex[]; -- index of first char of encoding name SkipTo[' ]; stop _ GetIndex[]; -- index of first char following header BackOver[' ]; version.minor _ BackNumber['.]; version.major _ BackNumber['/]; encoding _ SubString[enc, GetIndex[]]; SetIndex[stop]; RETURN[encoding, version]; }; CloseReader: PUBLIC PROC[self: Reader] = { self.procs _ closedReaderProcs; self.ropeReader _ NIL; self.buffer _ NIL; }; OpenWriter: PUBLIC PROC[name: ROPE, encoding: ROPE] RETURNS[Writer] = { s: STREAM = FileIO.Open[name, overwrite]; s.PutRope[herald]; s.PutRope[encoding]; s.PutRope["/2.0 "]; -- *** cheat, for now *** RETURN[CreateWriter[encoding, s]]; }; CreateWriter: PUBLIC PROC[encoding: ROPE, stream: STREAM] RETURNS[Writer] = { node: Node = Find[encoding]; IF node=NIL THEN ERROR Error[Rope.Concat["unknown encoding: ", encoding]] ELSE RETURN[node.write[stream]]; }; CloseWriter: PUBLIC PROC[self: Writer] = { self.procs _ closedWriterProcs; self.stream.Close[]; }; Find: PROC[encoding: ROPE] RETURNS[Node] = { FOR node: Node _ encodingList, node.next UNTIL node=NIL DO IF encoding.Equal[node.encoding] THEN RETURN[node]; ENDLOOP; RETURN[NIL]; }; Register: PUBLIC PROC[encoding: ROPE, version: Version, read: ReadProc, write: WriteProc] = { IF Find[encoding]=NIL THEN { node: Node = NEW[NodeRep _ [next: encodingList, encoding: encoding, version: version, read: read, write: write]]; encodingList _ node; } ELSE ERROR Error["encoding registered twice"]; }; END. ςIPEncodingImpl.mesa Last edited by: Doug Wyatt, April 21, 1983 2:28 pm Prepare to read an Interpress master with the given file name. Parse the header to verify that it is a valid master, and return a reader appropriate for its encoding. Open a reader for a specified encoding. Prepare to write an Interpress master with the given file name. Write the header and return a writer for the given encoding. Open a writer for a specified encoding; start writing wherever the stream is positioned. ΚΠ˜headšœ™šœ™Jšœ"™"—J˜šΟk ˜ Jšœœ˜Jšœœœ˜"Jšœœ˜,Jšœ œ\˜lJšœœ"œ ˜:Jšœœ ˜Jšœ œO˜_—J˜—šœœ˜Jšœ œ˜,Jšœ ˜Jšœœœ˜!J˜Jšœœœ˜Jšœœœœ˜J˜Jšœœœ ˜šœ œœ˜Jšœ ˜ Jšœ œΟc˜'Jšœž˜#Jšœ˜Jšœ˜J˜—J˜Jšœœž+˜EJ˜Jš œœœ œœ˜*J˜šœœœœ˜AJšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜—šœœœœ˜AJšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜—šΟnœœœœ ˜AJšœ˜—šŸ œœœœ˜?Jšœ˜—šŸœœœ˜IJšœ˜—šŸ œœœœ˜AJšœ˜—šŸ œœœœ˜AJšœ˜—šŸ œœ)˜:Jšœ˜—šŸ œœœ˜,Jšœ˜—šŸœœ˜6Jšœ˜—šŸ œœœ˜.Jšœ˜—šŸ œœ&œ˜BJšœ˜—J˜š Ÿ œœœ œœ˜CJšœ>™>Jšœ5™5Jšœ1™1Jšœ œœ˜J˜Jšœœ˜!Jšœœ˜'Jšœ!˜!Jšœ ˜ Jšœ.˜.Jšœ%˜+J˜—J˜šŸ œœœ œ˜EJšœ ˜Jšœ'™'J˜Jšœœœœ3˜IJšœ+œ ˜@J˜—J˜Jšœœ˜J˜šŸ œœ˜)Jšœ œ˜-šŸœœœ˜Jšœœ˜-J˜—š Ÿœœœœœ˜)Jšœœ˜5Jšœœ'˜1J˜—šŸœœœ˜Jš œœœœœ˜*J˜—šŸœœœ˜Jšœœœ˜&J˜—š Ÿ œœœœœ˜,Jšœœ˜ Jšœœ˜ šœœ˜ šœœ œ˜Jšœœ˜Jšœœœ ˜Jšœœ!˜+Jšœ˜Jšœ˜—Jšœœœ˜Jšœœ#˜-Jšœ˜—Jšœ˜ J˜—Jšœ œ˜Jš Ÿœœœœœ˜