DIRECTORY BasicTime, FileOps, FileReader, FS, Rope, RopeIO, IO, RopeReader, RefText; FileReaderImpl: CEDAR PROGRAM IMPORTS FS, Rope, RopeIO, RopeReader, RefText EXPORTS FileReader = BEGIN OPEN FileReader; InterDoc: PUBLIC SIGNAL [doc: ROPE] = CODE; -- raised by following procs Open: PUBLIC PROC [fileName: ROPE, start, len: INT] RETURNS [control, comment, text: RopeReader.Ref, tiogaFile: BOOL, fh: FS.OpenFile, createDate: BasicTime.GMT] = { fh _ FS.Open[fileName]; [control,comment,text,tiogaFile,createDate] _ OpenC[fh,start,len]; }; IsInterDoc: PROC [textRope: ROPE] RETURNS [BOOL] = { interdocHeader: ROPE = "{Interdoc/Interchange/"; RETURN [ RopeReader.EqSubstrs[textRope,interdocHeader,0,0,Rope.Size[interdocHeader]]] }; OpenC: PUBLIC PROC [file: FS.OpenFile, start, len: INT] RETURNS [ control, comment, text: RopeReader.Ref, tiogaFile: BOOL, createDate: BasicTime.GMT] = { Substr: PROC [start, len: INT] RETURNS [Rope.ROPE] = { RETURN [RopeIO.FromFileC[openFile: file, start: start, len: len]]; }; interdoc: ROPE; fileLen: INT; [bytes: fileLen, created: createDate] _ FS.GetInfo[file]; [control,comment,text,interdoc,tiogaFile] _ DoOpen[fileLen,start,len,Substr]; IF interdoc#NIL THEN SIGNAL InterDoc[interdoc]; }; DoOpen: PROC [totLen, start, len: INT, Substr: PROC [start,len: INT] RETURNS [ROPE]] RETURNS [control, comment, text: RopeReader.Ref, interdoc: ROPE, tiogaFile: BOOL] = { FakeFile: PROC = { textRope: ROPE _ Substr[start,len]; IF IsInterDoc[textRope] THEN interdoc _ textRope ELSE { tiogaFile _ FALSE; RopeReader.SetPosition[text,textRope]; RopeReader.SetPosition[control,PhonyControl[len]] }; }; { -- for EXIT commentStart,end,commentLen,controlLen,propsLen: INT; endSize: NAT = FileOps.endSize; endRope: Rope.ROPE; tiogaFile _ TRUE; start _ MAX[0,MIN[start,totLen]]; len _ MAX[0,MIN[len,totLen-start]]; end _ start+len; text _ RopeReader.Create[]; comment _ RopeReader.Create[]; control _ RopeReader.Create[]; IF len <= endSize THEN GOTO FakeIt; RopeReader.SetPosition[control,Substr[end-endSize,endSize]]; IF ~ReadControlTrailerId[control] THEN GOTO FakeIt; IF (propsLen _ ReadLen[control]) NOT IN [0..len-endSize) THEN GOTO FakeIt; IF (commentStart _ ReadLen[control]) NOT IN [0..len-endSize) THEN GOTO FakeIt; IF ReadLen[control] # len THEN GOTO FakeIt; endRope _ Substr[start+commentStart,len-commentStart]; -- comment and control RopeReader.SetPosition[comment,endRope]; IF ~ReadCommentHeaderId[comment] THEN GOTO FakeIt; commentLen _ ReadLen[comment]; RopeReader.SetPosition[control,endRope,commentLen]; IF ~ReadControlHeaderId[control] THEN GOTO FakeIt; controlLen _ ReadLen[control]; IF commentStart+commentLen+controlLen # len THEN GOTO FakeIt; RopeReader.SetPosition[text,Substr[start,commentStart]] EXITS FakeIt => FakeFile[] }}; ReadControlHeaderId: PROC [control: RopeReader.Ref] RETURNS [BOOL] = { FOR i:NAT IN [0..FileOps.fileIdSize) DO IF RopeReader.Get[control] # FileOps.controlHeaderId[i] THEN RETURN[FALSE]; ENDLOOP; RETURN [TRUE]; }; ReadCommentHeaderId: PROC [comment: RopeReader.Ref] RETURNS [BOOL] = { FOR i:NAT IN [0..FileOps.fileIdSize) DO IF RopeReader.Get[comment] # FileOps.commentHeaderId[i] THEN RETURN[FALSE]; ENDLOOP; RETURN [TRUE]; }; ReadLen: PROC [rdr: RopeReader.Ref] RETURNS [INT] = { start: PACKED ARRAY [0..3] OF CHAR; start[0] _ RopeReader.Get[rdr]; start[1] _ RopeReader.Get[rdr]; start[2] _ RopeReader.Get[rdr]; start[3] _ RopeReader.Get[rdr]; RETURN [LOOPHOLE[start]]; }; ReadControlTrailerId: PROC [control: RopeReader.Ref] RETURNS [BOOL] = { FOR i:NAT IN [0..FileOps.fileIdSize) DO IF RopeReader.Get[control] # FileOps.controlTrailerId[i] THEN RETURN[FALSE]; ENDLOOP; RETURN [TRUE]; }; PhonyControl: PROC [len: INT] RETURNS [r: ROPE] = { first, second, fourth: FileOps.LengthByte; third: FileOps.ThirdByte; lenBytes: FileOps.IntBytes _ LOOPHOLE[len]; text: REF TEXT _ NEW[TEXT[16]]; Append: PROC [c: CHAR] ~ { text _ RefText.AppendChar[text, c]; }; Append[FileOps.startNode]; -- start root node Append[VAL[0]]; -- null type for root Append[FileOps.terminalTextNode]; Append[VAL[0]]; -- null type for node Append[FileOps.rope]; -- rope for node IF lenBytes.fourth # 0 THEN { fourth.data _ lenBytes.fourth; first.others _ second.others _ third.others _ TRUE; }; IF lenBytes.thirdTop # 0 OR lenBytes.thirdBottom # 0 THEN { third.dataTop _ lenBytes.thirdTop; third.dataBottom _ lenBytes.thirdBottom; first.others _ second.others _ TRUE; }; IF lenBytes.second # 0 THEN { second.data _ lenBytes.second; first.others _ TRUE; }; first.data _ lenBytes.first; Append[VAL[first]]; IF first.others THEN { Append[VAL[second]]; IF second.others THEN { Append[VAL[third]]; IF third.others THEN { Append[VAL[fourth]] }}}; Append[FileOps.endNode]; -- end of root Append[FileOps.endOfFile]; r _ Rope.FromRefText[text]; }; FromRope: PUBLIC PROC [rope: ROPE, start, len: INT] RETURNS [control, comment, text: RopeReader.Ref, tiogaFile: BOOL] = { Substr: PROC [start,len: INT] RETURNS [ROPE] = { RETURN [Rope.Substr[rope,start,len]]; }; interdoc: ROPE; [control,comment,text,interdoc,tiogaFile] _ DoOpen[Rope.Size[rope],start,len,Substr]; IF interdoc#NIL THEN SIGNAL InterDoc[interdoc]; }; FromStream: PUBLIC PROC [stream: IO.STREAM, len: INT] RETURNS [control, comment, text: RopeReader.Ref, tiogaFile: BOOL] = { rope: ROPE _ RopeIO.GetRope[stream,len]; [control,comment,text,tiogaFile] _ FromRope[rope,0,Rope.Size[rope]]; }; END. 6FileReaderImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. written by Paxton. March 1981 Paxton. August 24, 1982 10:39 am Last Edited by: Maxwell, January 5, 1983 1:07 pm Russ Atkinson, July 26, 1983 5:41 pm Last Edited by: Birrell, August 23, 1983 1:29 pm Plass, March 29, 1985 4:54:11 pm PST Doug Wyatt, March 3, 1985 4:38:43 pm PST ***** Operations for opening file This is a silly hack to reduce the size of the return records to keep them SAFE. length of rope for node **** Read from rope instead of file **** Read from IO stream Κ˜codešœ™Kšœ Οmœ1™