DIRECTORY CIFS, Directory, File, T1FileOps, FileReader, IO, PropertyTypes, Rope, RopeFrom, RopeIO, RopeReader, System, T2FileOps; FileReaderImpl: CEDAR MONITOR IMPORTS Rope, RopeFrom, RopeIO, RopeReader, CIFS, Directory EXPORTS FileReader = BEGIN OPEN FileReader; Open: PUBLIC PROC [fileName: Rope.ROPE, start, len: Offset] RETURNS [reply:Reply, fh: CIFS.OpenFile, createDate: System.GreenwichMeanTime]={ file: File.Capability _ CIFS.GetFC[fh _ CIFS.Open[fileName, CIFS.read]]; [reply, createDate] _ OpenC[file, start, len] }; OpenC: PUBLIC PROC [file: File.Capability, start, len: Offset] RETURNS [reply:Reply, createDate: System.GreenwichMeanTime] = TRUSTED { Substr: PROC [start, len: Offset] RETURNS [Rope.ROPE] = TRUSTED { RETURN [RopeFrom.File[file, start, len, fileLen]] }; dummy: STRING _ [40]; fileLen: Offset; [createDate: createDate, byteLength: fileLen] _ Directory.GetProps[file: file, name: dummy]; reply _ DoOpen[fileLen, start, len, Substr] }; DoOpen: PROC [ totLen, start, len: Offset, Substr: PROC [start, len: Offset] RETURNS [Rope.ROPE]] RETURNS [reply: Reply] = { FakeFile: PROC = { textRope: Rope.ROPE _ Substr[start, len]; reply.fileType _ Simple; IF reply.text=NIL THEN reply.text _ RopeReader.Create[]; IF reply.comment=NIL THEN reply.comment _ RopeReader.Create[]; RopeReader.SetPosition[reply.text, textRope]; RopeReader.SetPosition[reply.control, PhonyControl[len]] }; { -- for EXIT commentStart, end, commentLen, controlLen, propsLen, propsStart: Offset; endSize: NAT = T1FileOps.endSize; endRope: Rope.ROPE; pad:CARDINAL; reply _ GetReply[]; start _ MAX[0, MIN[start, totLen]]; len _ MAX[0, MIN[len, totLen-start]]; end _ start+len; reply.control _ RopeReader.GetRopeReader[]; IF len <= endSize THEN GOTO FakeIt; RopeReader.SetPosition[reply.control, Substr[end-endSize, endSize]]; -- 'control' reads the trailer [reply.fileType, pad] _ ReadControlTrailerId[reply.control]; SELECT reply.fileType FROM Tioga1 => { IF (propsLen _ ReadLen[reply.control]) NOT IN [0..len-endSize) THEN GOTO FakeIt; IF (commentStart _ ReadLen[reply.control]) NOT IN [0..len-endSize) THEN GOTO FakeIt; IF ReadLen[reply.control] # len THEN GOTO FakeIt; endRope _ Substr[start+commentStart, len-commentStart]; -- comment and control reply.comment _ RopeReader.GetRopeReader[]; RopeReader.SetPosition[reply.comment, endRope]; IF ~ReadCommentHeaderId[reply.comment] THEN GOTO FakeIt; commentLen _ ReadLen[reply.comment]; RopeReader.SetPosition[reply.control, endRope, commentLen]; IF ~ReadControlHeaderId[reply.control] THEN GOTO FakeIt; controlLen _ ReadLen[reply.control]; IF commentStart+commentLen+controlLen # len THEN GOTO FakeIt; reply.text _ RopeReader.GetRopeReader[]; RopeReader.SetPosition[reply.text, Substr[start, commentStart]] }; Tioga2 => { reply.version _ RopeReader.Get[reply.control]; reply.flags _ RopeReader.Get[reply.control]; IF (propsStart _ ReadCard[reply.control]) NOT IN [0..len-endSize] THEN GOTO FakeIt; IF (reply.controlStart _ ReadLen[reply.control]) NOT IN [0..len-endSize) THEN GOTO FakeIt; IF ReadLen[reply.control] # len THEN GOTO FakeIt;-- supposed length # actual length reply.controlStart _ start + reply.controlStart; reply.text _ reply.control _ NIL; reply.textLen _ reply.controlStart - pad; reply.controlStart _ reply.controlStart + T1FileOps.fileIdSize; reply.controlLen _ propsStart - T1FileOps.fileIdSize; reply.textStart _ start; reply.fileRope _ Substr[0, len] }; ENDCASE => GOTO FakeIt; EXITS FakeIt => FakeFile[] -- build a Fake Tioga1 file structure }}; ReadControlHeaderId: PROC [control: RopeReader.Ref] RETURNS [BOOLEAN] = { OPEN T1FileOps; FOR i:NAT IN [0..fileIdSize) DO IF RopeReader.Get[control] # controlHeaderId[i] THEN RETURN[FALSE]; ENDLOOP; RETURN [TRUE] }; ReadCommentHeaderId: PROC [comment: RopeReader.Ref] RETURNS [BOOLEAN] = { FOR i:NAT IN [0..T1FileOps.fileIdSize) DO IF RopeReader.Get[comment] # T1FileOps.commentHeaderId[i] THEN RETURN[FALSE]; ENDLOOP; RETURN [TRUE] }; ReadLen: PROC [rdr: RopeReader.Ref] RETURNS [Offset] = { OPEN RopeReader; start: PACKED ARRAY [0..3] OF CHARACTER; start[0] _ Get[rdr]; start[1] _ Get[rdr]; start[2] _ Get[rdr]; start[3] _ Get[rdr]; RETURN [LOOPHOLE[start]] }; ReadCard: PROC [rdr: RopeReader.Ref] RETURNS [CARDINAL] = { OPEN RopeReader; start: PACKED ARRAY [0..1] OF CHARACTER; start[0] _ Get[rdr]; start[1] _ Get[rdr]; RETURN [LOOPHOLE[start]] }; ReadControlTrailerId: PROC [control: RopeReader.Ref] RETURNS [FileType, CARDINAL] = { SELECT RopeReader.Get[control] FROM T1FileOps.controlTrailerId[0] => { IF RopeReader.Get[control] # T1FileOps.controlTrailerId[1] THEN RETURN[Simple, 0]; RETURN [Tioga1, 0] }; T2FileOps.controlTrailerId => { SELECT RopeReader.Get[control] FROM T2FileOps.DataPaddedFlag => RETURN [Tioga2, 1]; T2FileOps.DataUnpaddedFlag => RETURN [Tioga2, 0]; ENDCASE => RETURN[Simple, 0] }; ENDCASE => RETURN[Simple, 0] }; PhonyControl: PROC [len: Offset] RETURNS [r: Rope.ROPE] = { OPEN T1FileOps; first, second, fourth: LengthByte; third: ThirdByte; lenBytes: IntBytes _ LOOPHOLE[len]; r _ RopeFrom.Character[startNode]; -- start root node r _ RopeFrom.FlatAppendByte[r, 0]; -- null type for root r _ RopeFrom.FlatAppendChar[r, terminalTextNode]; r _ RopeFrom.FlatAppendByte[r, 0]; -- null type for node r _ RopeFrom.FlatAppendChar[r, 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; r _ RopeFrom.FlatAppendByte[r, first]; IF first.others THEN { r _ RopeFrom.FlatAppendByte[r, second]; IF second.others THEN { r _ RopeFrom.FlatAppendByte[r, third]; IF third.others THEN { r _ RopeFrom.FlatAppendByte[r, fourth] }}}; r _ RopeFrom.FlatAppendChar[r, endNode]; -- end of root r _ RopeFrom.FlatAppendChar[r, endOfFile]}; FromRope: PUBLIC PROC [rope: Rope.ROPE, start, len: Offset] RETURNS [reply:Reply] = { Substr: PROC [start, len: Offset] RETURNS [Rope.ROPE] = { RETURN [Rope.Substr[rope, start, len]] }; reply _ DoOpen[Rope.Size[rope], start, len, Substr]; }; FromStream: PUBLIC PROC [stream: IO.Handle, len: Offset] RETURNS [reply:Reply] = { rope: Rope.ROPE _ RopeIO.GetRope[stream, len]; reply _ FromRope[rope, 0, Rope.Size[rope]] }; reply1, reply2, reply3: Reply; GetReply: ENTRY PROC RETURNS [reply: Reply] = { ENABLE UNWIND => NULL; IF reply3 # NIL THEN { reply _ reply3; reply3 _ NIL } ELSE IF reply2 # NIL THEN { reply _ reply2; reply2 _ NIL } ELSE IF reply1 # NIL THEN { reply _ reply1; reply1 _ NIL } ELSE reply _ NEW[ReplyRec] }; FreeReply: PUBLIC ENTRY PROC [reply: Reply] = { ENABLE UNWIND => NULL; IF reply3 = reply OR reply2 = reply OR reply1 = reply THEN ERROR; IF reply.control # NIL THEN { RopeReader.FreeRopeReader[reply.control]; reply.control _ NIL }; IF reply.comment # NIL THEN { RopeReader.FreeRopeReader[reply.comment]; reply.comment _ NIL }; IF reply.text # NIL THEN { RopeReader.FreeRopeReader[reply.text]; reply.text _ NIL }; reply.fileRope _ NIL; IF reply3 = NIL THEN reply3 _ reply ELSE IF reply2 = NIL THEN reply2 _ reply ELSE IF reply1 = NIL THEN reply1 _ reply }; END. .-- FileReaderImpl.Mesa -- written by Paxton. March 1981 Last Edited by: Maxwell, August 19, 1983 1:43 pm -- ***** Operations for opening file constructs a T1 style simple file -- length of rope for node -- **** Read from rope instead of file -- **** Read from IO stream -- **** Miscellaneous Ê©˜JšÏc™Jš!™!J™0J™šÏk ˜ Jšžœ˜Jšœ ˜ Jšœ˜Jšœ ˜ Jšœ ˜ Jšžœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœ ˜ Jšœ˜Jšœ ˜ —J˜šœž ˜Jšžœ%žœ ˜;Jšžœ ˜—Jšžœžœ ˜J˜Jš$™$J˜šÏnœžœžœžœ˜;Jšžœžœ2˜PJšœžœ žœžœ˜HJšœ1˜1J˜—šŸœžœžœ,˜>Jšžœ7žœ˜Gš Ÿœžœžœžœžœ˜AJšžœ.˜4—Jšœžœ˜Jšœ˜Jšœ\˜\Jšœ.˜.J˜—šŸœžœ˜Jšœ˜JšŸœžœžœžœ˜6Jšžœ˜J˜šŸœžœ˜J™!Jšœžœ˜)Jšœ˜Jšžœ žœžœ"˜8Jšžœžœžœ%˜>Jšœ-˜-šœ;˜;J˜——šœ ˜ JšœH˜HJšœ žœ˜!Jšœžœ˜Jšœžœ˜ J˜Jšœ˜Jšœžœžœ˜#Jšœžœžœ˜%J˜Jšœ+˜+Jšžœžœžœ˜#JšœE˜cJšœ<˜<šžœž˜˜ Jš žœ%žœžœžœžœ˜PJš žœ)žœžœžœžœ˜TJšžœžœžœ˜1Jšœ8˜NJšœ+˜+J˜/Jšžœ%žœžœ˜8J˜$Jšœ;˜;Jšžœ%žœžœ˜8Jšœ$˜$Jšžœ*žœžœ˜=Jšœ(˜(J˜B—šœ ˜ Jšœ.˜.Jšœ,˜,Jš žœ(žœžœžœžœ˜SJš žœ/žœžœžœžœ˜ZJšžœžœžœ"˜SJšœ0˜0Jšœžœ˜!Jšœ)˜)Jšœ?˜?Jšœ6˜6Jšœ˜Jšœ"˜"—Jšžœžœ˜—JšÐbkœ%˜@Jšœ˜—J˜—šŸœžœžœžœ˜IJšžœ ˜šžœžœžœž˜Jšžœ.žœžœžœ˜CJšžœ˜—Jšžœžœ˜J˜—šŸœžœžœžœ˜Išžœžœžœž˜)Jšžœ8žœžœžœ˜MJšžœ˜—Jšžœžœ˜J˜—šŸœžœžœžœ ˜IJš œžœžœžœž œ˜(J˜SJšžœžœ ˜J˜—š Ÿœžœžœžœžœ ˜LJš œžœžœžœž œ˜(J˜)Jšžœžœ ˜J˜—šŸœžœžœ žœ˜Ušžœž˜#šœ!ž˜"Jšžœ9ž œ ˜RJšžœ˜—šœž˜šžœž˜#Jšœžœ ˜/Jšœžœ ˜1Jšžœžœ˜——Jšžœžœ˜—J˜—šŸ œžœžœ žœ˜;Jšžœ ˜J˜"J˜Jšœžœ˜#J˜Jšœ#˜5Jšœ#˜8J˜1Jšœ#˜8Jšœ&˜6Jš™šžœžœ˜J˜Jšœ.žœ˜6—šžœžœžœ˜;J˜"J˜(Jšœžœ˜'—šžœžœ˜Jšœ.žœ˜5—J˜J˜&šžœžœ˜J˜'šžœžœ˜J˜&šžœžœ˜J˜+———Jšœ)˜7J˜+J˜J˜—Jš&™&J˜šŸœžœžœ&˜;Jšžœ˜šŸœžœžœ˜9Jšžœ#˜)—Jšœ4˜4Jšœ˜J˜—Jš™J˜šŸ œžœžœ žœ˜8Jšžœ˜Jšœ.˜.Jšœ-˜-J˜J˜—Jš™J˜šœ˜J˜—šŸœžœžœžœ˜/Jšž œžœ˜Jšžœ žœžœžœ˜5Jš žœžœ žœžœžœ˜:Jš žœžœ žœžœžœ˜:Jšžœ žœ ˜J˜—šŸ œž œžœžœ ˜/Jšž œžœ˜Jš žœžœžœžœžœ˜AJšžœžœžœ=žœ˜^Jšžœžœžœ=žœ˜^Jšžœžœžœ7žœ˜UJšœžœ˜Jšžœ žœžœ˜#Jšžœžœ žœžœ˜(Jšžœžœ žœžœ˜+J˜—Jšžœ˜—…—¬&ƒ