DIRECTORY CIFS, Directory, File, FileOps, FileReader, IO, PropertyTypes, Rope, RopeFrom, RopeIO, RopeReader, System, T2FileOps USING [controlTrailerId, DataPaddedFlag, DataUnpaddedFlag]; FileReaderImpl: CEDAR PROGRAM IMPORTS Rope, RopeFrom, RopeIO, RopeReader, CIFS, Directory EXPORTS FileReader = BEGIN Open: PUBLIC PROC [fileName: Rope.ROPE, start, len: FileReader.Offset, okToMapFile: BOOLEAN] RETURNS [reply:FileReader.Reply, fh: CIFS.OpenFile, createDate: System.GreenwichMeanTime]={ file: File.Capability _ CIFS.GetFC[fh _ CIFS.Open[fileName, CIFS.read]]; [reply, createDate] _ OpenC[file, start, len, okToMapFile] }; OpenC: PUBLIC PROC [file: File.Capability, start, len: FileReader.Offset, okToMapFile: BOOLEAN] RETURNS [reply:FileReader.Reply, createDate: System.GreenwichMeanTime] = TRUSTED { Substr: PROC [start, len: FileReader.Offset] RETURNS [Rope.ROPE] = TRUSTED { RETURN [RopeFrom.File[file, start, len, TRUE, fileLen, okToMapFile]] }; dummy: STRING _ [40]; fileLen: FileReader.Offset; [createDate: createDate, byteLength: fileLen] _ Directory.GetProps[file: file, name: dummy]; reply _ DoOpen[fileLen, start, len, Substr]; }; DoOpen: PROC [totLen, start, len: FileReader.Offset, Substr: PROC [start, len: FileReader.Offset] RETURNS [Rope.ROPE]] RETURNS [reply:FileReader.Reply] = { FakeFile: PROC = { textRope: Rope.ROPE _ Substr[start, len]; reply.fileType _ Simple; RopeReader.SetPosition[reply.text, textRope]; RopeReader.SetPosition[reply.control, PhonyControl[len]] }; { -- for EXIT commentStart, end, commentLen, controlLen, propsLen, propsStart: FileReader.Offset; endSize: NAT = FileOps.endSize; endRope: Rope.ROPE; pad:CARDINAL; reply _ NEW[FileReader.ReplyRec]; start _ MAX[0, MIN[start, totLen]]; len _ MAX[0, MIN[len, totLen-start]]; end _ start+len; reply.text _ RopeReader.Create[]; reply.comment _ RopeReader.Create[]; reply.control _ RopeReader.Create[]; 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 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; RopeReader.SetPosition[reply.text, Substr[start, commentStart]] }; Tioga2 => { IF (propsStart _ ReadLen[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 -- supposed length # actual length GOTO FakeIt; reply.controlStart _ start + reply.controlStart; RopeReader.SetPosition[reply.comment, Substr[reply.controlStart+propsStart, len-propsStart-endSize]]; -- comment reader will read props and symbol table reply.version _ ReadLen[reply.comment]; reply.text _ reply.control _ NIL; reply.textLen _ reply.controlStart - pad; reply.controlStart _ reply.controlStart + FileOps.fileIdSize; reply.controlLen _ propsStart - FileOps.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 FileOps; 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..FileOps.fileIdSize) DO IF RopeReader.Get[comment] # FileOps.commentHeaderId[i] THEN RETURN[FALSE]; ENDLOOP; RETURN [TRUE] }; ReadLen: PROC [rdr: RopeReader.Ref] RETURNS [FileReader.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]] }; ReadControlTrailerId: PROC [control: RopeReader.Ref] RETURNS [FileReader.FileType, CARDINAL] = { SELECT RopeReader.Get[control] FROM FileOps.controlTrailerId[0] => { FOR i:NAT IN [1..FileOps.fileIdSize) DO IF RopeReader.Get[control] # FileOps.controlTrailerId[i] THEN RETURN[Simple, 0]; ENDLOOP; 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: FileReader.Offset] RETURNS [r: Rope.ROPE] = { OPEN FileOps; 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: FileReader.Offset] RETURNS [reply:FileReader.Reply] = { Substr: PROC [start, len: FileReader.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: FileReader.Offset] RETURNS [reply:FileReader.Reply] = { rope: Rope.ROPE _ RopeIO.GetRope[stream, len]; reply _ FromRope[rope, 0, Rope.Size[rope]] }; Start: PUBLIC PROC = { }; END. œ-- FileReaderImpl.Mesa -- written by Paxton. March 1981 Last Edited by: Maxwell, January 5, 1983 1:07 pm Last Edited by: Lamming, May 31, 1983 2:06 pm -- ***** Operations for opening file Directory.GetProperty[file: file, property: PropertyTypes.tByteLength, propertyValue: DESCRIPTOR[@fileLen, SIZE[FileReader.Offset]]]; Directory.GetProperty[file: file, property: PropertyTypes.tCreateDate, propertyValue: DESCRIPTOR[@createDate, SIZE[System.GreenwichMeanTime]]]; constructs a T1 style simple file Set up a rope reader to read in the symbol table and set up the control and data offsets. Note that propsStart is described relative to the start of the control stream RopeReader.SetPosition[reply.comment, Substr[start+propsStart, len-propsStart-endSize]]; -- comment reader will read props and symbol table reply.version _ ReadLen[reply.comment]; -- length of rope for node -- **** Read from rope instead of file -- **** Read from IO stream -- **** Miscellaneous Edited on March 3, 1983 10:18 am, by Lamming Removed interdoc code ready for T2 release Edited on March 31, 1983 3:01 pm, by Lamming Made the 'open' procedures return a structure rather than lots of values so that T1 or T2 cracking routines can choose the information they need to do their job changes to: Open, OpenC, DoOpen, FakeFile, FromRope, FromStream, DoOpen Edited on April 11, 1983 11:57 am, by Lamming changes to: DoOpen Edited on April 13, 1983 5:07 pm, by Lamming changes to: DIRECTORY, DoOpen, ReadControlTrailerId Edited on May 4, 1983 5:09 pm, by Lamming changes to: DoOpen Edited on May 26, 1983 11:29 am, by Lamming changes to: OpenC Edited on May 31, 1983 12:32 pm, by Lamming changes to: DoOpen Ê+˜JšÏc™Jš!™!J™0Jšœ-™-J™šÏk ˜ Jšžœ˜Jšœ ˜ Jšœ˜Jšœ˜Jšœ ˜ Jšžœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ˜Jšœ ˜ Jšœ˜Jšœ žœ6˜F—J˜šœž ˜Jšžœ%žœ ˜;Jšžœ ˜—Jšž˜J˜Jš$™$J˜šÏnœžœžœCžœ˜\Jšžœžœ2˜[Jšœžœ žœžœ˜HJšœ>˜>J˜—šŸœžœžœEžœ˜_JšžœBžœ˜Rš Ÿœžœ!žœžœžœ˜LJšžœ"žœ˜G—Jšœžœ˜Jšœ˜Jšœ\˜\™GJšœž œ žœ™>—šœG™GJšœž œžœ™H—Jšœ,˜,Jšœ˜J˜—š Ÿœžœ)Ÿœžœ!žœ ˜vJšžœ˜$J˜šŸœžœ˜J™!Jšœ)˜)Jšœ˜Jšœ-˜-Jšœ8˜8˜J˜——šœ ˜ JšœS˜SJšœ žœ˜Jšœžœ˜Jšœžœ˜ J˜Jšœžœ˜!Jšœžœžœ˜#Jšœžœžœ˜%J˜J˜!J˜$J˜$Jšžœžœžœ˜#JšœE˜cJšœ<˜<šžœž˜˜ Jš žœ%žœžœžœžœ˜PJš žœ)žœžœžœžœ˜TJšžœžœžœ˜1Jšœ8˜NJ˜/Jšžœ%žœžœ˜8J˜$Jšœ;˜;Jšžœ%žœžœ˜8Jšœ$˜$Jšžœ*žœžœ˜=J˜?J˜—šœ ˜ Jšœ§™§šžœ'žœžœž˜EJšžœ˜ —JšœYÏeÐce!™‹Jšœ'™'šžœ/žœžœž˜MJšžœ˜ —šžœžœ"˜GJšžœ ˜—Jšœ0˜0Jšœf ¡!˜˜Jšœ'˜'Jšœžœ˜!Jšœ)˜)Jšœ=˜=Jšœ4˜4Jšœ˜Jšœ ˜ J˜—Jšžœžœ˜—JšÐbkœ%˜@Jšœ˜—Jšœ˜J˜—šŸœžœžœžœ˜IJšžœ ˜ šžœžœžœž˜Jšžœ.žœžœžœ˜CJšžœ˜—Jšžœžœ˜J˜—šŸœžœžœžœ˜Išžœžœžœž˜'Jšžœ6žœžœžœ˜KJšžœ˜—Jšžœžœ˜J˜—šŸœžœžœžœ ˜TJš œžœžœžœž œ˜(J˜)J˜)Jšžœžœ ˜J˜—šŸœžœžœžœ˜`šžœž˜#šœž˜ šžœžœžœž˜'šžœ7ž˜=Jšžœ ˜—Jšžœ˜—Jšžœ ˜J˜—šœž˜šžœž˜#Jšœžœ ˜/Jšœžœ ˜1Jšžœžœ ˜—J˜—Jšžœžœ ˜—Jšœ˜J˜—šŸ œžœžœ˜FJšžœ ˜ 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˜šŸœžœžœ1˜FJšžœ˜$šŸœžœ!žœ˜DJšžœ#˜)—Jšœ4˜4Jšœ˜J˜—Jš™J˜šŸ œžœžœ žœ ˜CJšžœ˜$Jšœ.˜.Jšœ-˜-J˜J˜—Jš™J˜šŸœžœžœ˜J˜J˜—Jšžœ˜šž,™,J™*—šž,™,J™ Jšœ Ïr;™G—J™šž-™-Jšœ £™—šž,™,Jšœ £'™3—šž)™)Jšœ £™—šž+™+Jšœ £™—šž+™+Jšœ £™—J™—…—ò(¹