-- 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
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
-- ***** Operations for opening file
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];
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]]];
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 = {
constructs a T1 style simple file
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 => {
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
IF (propsStart ← ReadLen[reply.control]) NOT IN [0..len-endSize] THEN
GOTO FakeIt;
RopeReader.SetPosition[reply.comment, Substr[start+propsStart, len-propsStart-endSize]]; -- comment reader will read props and symbol table
reply.version ← ReadLen[reply.comment];
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
-- length of 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]};
-- **** Read from rope instead of file
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];
};
-- **** Read from IO stream
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]] };
-- **** Miscellaneous
Start: PUBLIC PROC = {
};
END.
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