DIRECTORY Atom, CIFS, File, FileOps, FileReader, GetFile, InterFile, IO, NameSymbolTable, NodeProps, OtherNode, PGSupport, PutGet, Rope, RopeEdit, RopeInline, RopeReader, SafeStorage, System, TextEdit, TextLooks, TextLooksSupport, TextNode; GetFileImpl: CEDAR MONITOR IMPORTS Atom, CIFS, FileReader, InterFile, NameSymbolTable, npI:NodeProps, OtherNode, PGSupport, Rope, RopeEdit, RopeReader, SafeStorage, TextLooks, TextLooksSupport, TextNode EXPORTS PutGet, GetFile SHARES TextLooks = BEGIN OPEN PutGet, GetFile, TextNode; Byte: TYPE = [0..255]; FromFileError: PUBLIC ERROR = CODE; FromFile: PUBLIC PROC [fileName: ROPE, start: Offset _ 0, len: Offset _ MaxLen, okToMapFile: BOOLEAN _ FALSE] RETURNS [root: Ref] = { control, comment, stext: RopeReader.Ref; interdoc, ext: ROPE; tiogaFile: BOOL; dot: INT; ForceLower: PROC [r: ROPE] RETURNS [ROPE] = { ForceCharLower: SAFE PROC [old: CHAR] RETURNS [new: CHAR] = TRUSTED { RETURN [Rope.Lower[old]] }; RETURN [Rope.Translate[base: r, translator: ForceCharLower]] }; fh: CIFS.OpenFile; createDate: System.GreenwichMeanTime; StartRead[]; { ENABLE UNWIND => { CIFS.Close[fh]; EndRead[] }; [control,comment,stext,tiogaFile,fh,createDate] _ FileReader.Open[fileName,start,len,okToMapFile ! FileReader.InterDoc => { interdoc _ doc; RESUME }]; root _ IF interdoc#NIL THEN InterFile.FromRope[interdoc] ELSE Finish[control,comment,stext,tiogaFile] }; CIFS.Close[fh]; npI.PutProp[root, $FileExtension, IF (dot _ Rope.Find[fileName, "."]) > 0 AND Rope.Size[ext _ Rope.Substr[fileName, dot+1]] > 0 THEN Atom.MakeAtom[ForceLower[ext]] ELSE $null]; AddCreateDate[root, createDate]; EndRead[] }; FromFileC: PUBLIC PROC [file: File.Capability, start: Offset _ 0, len: Offset _ MaxLen, okToMapFile: BOOLEAN _ FALSE] RETURNS [root: Ref] = { control, comment, stext: RopeReader.Ref; interdoc: ROPE; tiogaFile: BOOL; createDate: System.GreenwichMeanTime; StartRead[]; { ENABLE UNWIND => EndRead[]; [control,comment,stext,tiogaFile,createDate] _ FileReader.OpenC[file,start,len,okToMapFile ! FileReader.InterDoc => { interdoc _ doc; RESUME }]; root _ IF interdoc#NIL THEN InterFile.FromRope[interdoc] ELSE Finish[control,comment,stext,tiogaFile] }; AddCreateDate[root, createDate]; EndRead[] }; AddCreateDate: PROC [root: Ref, createDate: System.GreenwichMeanTime] = { npI.PutProp[root, $FileCreateDate, TextNode.pZone.NEW[System.GreenwichMeanTime _ createDate]] }; FromRope: PUBLIC PROC [rope: ROPE, start: Offset _ 0, len: Offset _ MaxLen] RETURNS [root: Ref] = { control, comment, stext: RopeReader.Ref; interdoc: ROPE; tiogaFile: BOOL; StartRead[]; { ENABLE UNWIND => EndRead[]; [control,comment,stext,tiogaFile] _ FileReader.FromRope[rope,start,len ! FileReader.InterDoc => { interdoc _ doc; RESUME }]; root _ IF interdoc#NIL THEN InterFile.FromRope[interdoc] ELSE Finish[control,comment,stext,tiogaFile] }; EndRead[] }; FromStream: PUBLIC PROC [stream: IO.Handle, len: Offset _ MaxLen] RETURNS [root: Ref] = { control, comment, stext: RopeReader.Ref; interdoc: ROPE; tiogaFile: BOOL; StartRead[]; { ENABLE UNWIND => EndRead[]; [control,comment,stext,tiogaFile] _ FileReader.FromStream[stream,len ! FileReader.InterDoc => { interdoc _ doc; RESUME }]; root _ IF interdoc#NIL THEN InterFile.FromRope[interdoc] ELSE Finish[control,comment,stext,tiogaFile] }; EndRead[] }; collectionInterval: LONG CARDINAL; bigCollectionInterval: LONG CARDINAL = 1000000; startCount: INTEGER _ 0; StartRead: ENTRY PROC = { ENABLE UNWIND => NULL; IF startCount = 0 THEN { collectionInterval _ SafeStorage.SetCollectionInterval[bigCollectionInterval] }; startCount _ startCount+1 }; EndRead: ENTRY PROC = { -- restore initial collectionInterval when all Get's done ENABLE UNWIND => NULL; IF (startCount _ startCount-1) = 0 THEN [] _ SafeStorage.SetCollectionInterval[collectionInterval] }; Finish: PROC [control, cmmnt, stext: RopeReader.Ref, tiogaFile: BOOL] RETURNS [root: Ref] = { OPEN FileOps; op: Op; parent, node, prev: Ref; textNode: RefTextNode; othrNode: RefOtherNode; terminalNode: BOOLEAN; textLength, runsLength: Offset _ 0; typename: TypeName; propname: ATOM; InsertNode: PROC [node: Ref] = { IF prev#NIL THEN prev.next _ node ELSE IF parent#NIL THEN parent.child _ node; prev _ node }; ReadByte: PROC RETURNS [Byte] = INLINE { RETURN [LOOPHOLE[ReadChar[]]] }; ReadChar: PROC RETURNS [CHARACTER] = { RETURN [RopeReader.Get[control]] }; MakeOtherNode: PROC = { InsertNode[node _ othrNode _ qZone.NEW[OtherBody]]; node.typename _ typename; node.next _ parent; parent _ node; prev _ NIL }; OtherNodeSpecs: PROC = { IF othrNode=NIL OR othrNode#node THEN ERROR FromFileError; othrNode.variety _ propname; OtherNode.DoSpecs[othrNode,GetControlRope[]] }; ReadProp: PROC = { specs: ROPE _ GetControlRope[]; value: REF _ npI.DoSpecs[propname,specs]; IF value # NIL THEN npI.PutProp[node,propname,value] }; GetRope: PROC [len: Offset, rdr: RopeReader.Ref] RETURNS [ROPE] = { rope: ROPE; pos: Offset; [rope,pos] _ RopeReader.Position[rdr]; RopeReader.SetIndex[rdr,pos+len]; RETURN [RopeEdit.Substr[rope,pos,len]] }; GetControlRope: PROC RETURNS [ROPE] = { RETURN [GetRope[ReadLength[],control]] }; GetText: PROC = { len: NAT; IF (len _ ReadByte[]) > text.maxLength THEN text _ pZone.NEW[TEXT[len]]; text.length _ 0; text.length _ RopeReader.GetString[control, text, len] }; GetAtom: PROC RETURNS [ATOM] = { GetText[]; -- get the print name RETURN [Atom.MakeAtom[Rope.FromRefText[text]]] }; GetName: PROC RETURNS [NameSymbolTable.Name] = { GetText[]; RETURN [NameSymbolTable.MakeName[text]] }; ReadLength: PROC RETURNS [Offset] = { first, second, fourth: LengthByte; third: ThirdByte; card: IntBytes; first _ LOOPHOLE[ReadByte[]]; card.first _ first.data; IF ~first.others THEN RETURN [LOOPHOLE[card]]; second _ LOOPHOLE[ReadByte[]]; card.second _ second.data; IF ~second.others THEN RETURN [LOOPHOLE[card]]; third _ LOOPHOLE[ReadByte[]]; card.thirdBottom _ third.dataBottom; card.thirdTop _ third.dataTop; IF ~third.others THEN RETURN [LOOPHOLE[card]]; fourth _ LOOPHOLE[ReadByte[]]; card.fourth _ fourth.data; RETURN [LOOPHOLE[card]] }; NextOp: PROC RETURNS [op: Op] = { OPEN RopeReader; op _ Get[control ! ReadOffEnd => { op _ endOfFile; CONTINUE }] }; pgf: PGSupport.PGF _ PGSupport.CreatePGF[]; text: REF TEXT _ pZone.NEW[TEXT[32]]; terminalNode _ FALSE; op _ NextOp[]; DO SELECT op FROM IN [terminalTextNodeFirst..terminalTextNodeLast] => { typename _ PGSupport.RetrieveTypeName[ LOOPHOLE[op-terminalTextNodeFirst, TypeIndex], pgf]; terminalNode _ TRUE }; IN [startNodeFirst..startNodeLast] => typename _ PGSupport.RetrieveTypeName[ LOOPHOLE[op-startNodeFirst, TypeIndex], pgf]; endNode => { IF prev#NIL THEN { prev.last _ TRUE; prev.next _ parent }; prev _ parent; IF (parent _ parent.next)=NIL THEN EXIT; op _ NextOp[]; LOOP }; startNode => { typename _ GetName[]; [] _ PGSupport.EnterTypeName[typename,pgf] }; terminalTextNode => { typename _ GetName[]; [] _ PGSupport.EnterTypeName[typename,pgf]; terminalNode _ TRUE }; rope, comment => { reader: RopeReader.Ref; IF op=rope THEN reader _ stext ELSE { reader _ cmmnt; textNode.comment _ TRUE }; IF textNode=NIL OR textNode#node THEN ERROR FromFileError; IF (textLength_ReadLength[]) > 0 THEN -- get the rope textNode.rope _ GetRope[textLength,reader]; SELECT runsLength FROM 0 => NULL; -- no runs for this rope textLength => runsLength _ 0; -- correct length ENDCASE => ERROR FromFileError; -- mismatch RopeReader.BumpIndex[reader,1]; -- skip CR at end of rope op _ NextOp[]; LOOP }; runs => { -- runs, if any, come before corresponding rope lookRuns: TextLooks.Runs; numRuns: Offset; pos: Offset _ 0; IF textNode=NIL OR textNode#node THEN ERROR FromFileError; numRuns _ ReadLength[]; -- read number of runs WHILE numRuns > 0 DO num: NAT _ TextLooksSupport.Short[MIN[numRuns,LAST[NAT]]]; baseRuns: TextLooks.BaseRuns _ TextLooksSupport.NewBase[num]; len: Offset _ pos; numRuns _ numRuns-num; FOR i:NAT IN [0..num) DO -- read runs for this baseRuns looks: TextLooks.Looks; ReadLookChars: PROC [num: NAT] = { FOR i:NAT IN [0..num) DO looks[ReadChar[]] _ TRUE; ENDLOOP; [] _ PGSupport.EnterLooks[looks,pgf] }; SELECT op _ NextOp[] FROM IN [looksFirst .. looksLast] => looks _ PGSupport.RetrieveLooks[ LOOPHOLE[op-looksFirst,LooksIndex],pgf]; FileOps.look1 => ReadLookChars[1]; FileOps.look2 => ReadLookChars[2]; FileOps.look3 => ReadLookChars[3]; FileOps.looks => { lb: TextLooks.LooksBytes; lb.byte0 _ ReadByte[]; lb.byte1 _ ReadByte[]; lb.byte2 _ ReadByte[]; lb.byte3 _ ReadByte[]; [] _ PGSupport.EnterLooks[looks _ LOOPHOLE[lb], pgf] }; ENDCASE => ERROR FromFileError; baseRuns[i] _ [pos_pos+ReadLength[],looks]; ENDLOOP; lookRuns _ IF lookRuns=NIL THEN baseRuns ELSE TextLooks.Concat[lookRuns,baseRuns,len,pos-len]; ENDLOOP; runsLength _ pos; -- for use in checking rope length textNode.runs _ lookRuns; op _ NextOp[]; LOOP }; prop => { [] _ PGSupport.EnterProp[propname _ GetAtom[], pgf]; ReadProp; op _ NextOp[]; LOOP }; propShort => { propname _ PGSupport.RetrieveProp[LOOPHOLE[ReadByte[],PropIndex], pgf]; ReadProp; op _ NextOp[]; LOOP }; otherNode => { typename _ GetName[]; [] _ PGSupport.EnterTypeName[typename, pgf]; MakeOtherNode; op _ NextOp[]; LOOP }; otherNodeShort => { typename _ PGSupport.RetrieveTypeName[ LOOPHOLE[ReadByte[],TypeIndex], pgf]; MakeOtherNode; op _ NextOp[]; LOOP }; otherNodeSpecs => { [] _ PGSupport.EnterProp[propname _ GetAtom[], pgf]; OtherNodeSpecs; op _ NextOp[]; LOOP }; otherNodeSpecsShort => { propname _ PGSupport.RetrieveProp [LOOPHOLE[ReadByte[],PropIndex], pgf]; OtherNodeSpecs; op _ NextOp[]; LOOP }; endOfFile => { IF parent=NIL THEN EXIT; -- have reached the root [] _ RopeReader.Backwards[control]; -- backup so read endOfFile again op _ endNode; LOOP }; ENDCASE => ERROR FromFileError; InsertNode[node _ textNode _ qZone.NEW[TextBody]]; node.typename _ typename; IF terminalNode THEN terminalNode _ FALSE ELSE { node.next _ parent; parent _ node; prev _ NIL }; op _ NextOp[]; ENDLOOP; IF (root _ prev)=NIL THEN -- don't have a normal tree IF node=NIL THEN root _ qZone.NEW[TextBody] -- null file ELSE root _ node; -- single node in file root.last _ TRUE; npI.PutProp[root, $FromTiogaFile, IF tiogaFile THEN $Yes ELSE $No]; PGSupport.FreePGF[pgf] }; StartGetFile: PUBLIC PROC = { }; END. -- GetFileImpl.Mesa -- written by Paxton. January 1981 -- last written by Paxton. December 1, 1982 9:44 am SafeStorage.ReclaimCollectibleObjects[]; -- MAIN PROGRAM -- read 4 bytes of looks from control stream -- if reach here, then want to start a new text node Ê å˜JšÏc™Jš#™#Jš3™3J˜JšÏk ˜ J˜Jšžœ˜J˜J˜J˜ J˜J˜ Jšžœ˜J˜J˜ J˜ J˜ J˜J˜J˜ J˜ J˜ J˜ J˜J˜ J˜ J˜J˜ J˜šœ ž ˜Jšžœžœ˜¯Jšžœ˜Jšžœ ˜—Jšžœžœ˜%J˜Jšœžœ ˜J˜Jšœžœžœžœ˜#J˜šÏnœžœžœ žœ*˜OJšœ žœžœ˜Jšžœ˜J˜(Jšœžœ˜Jšœ žœ˜Jšœžœ˜ š Ÿ œžœžœžœžœ˜-šŸœžœžœžœžœžœžœ˜EJšžœ˜—Jšžœ9˜?—Jšœžœ ˜Jšœ%˜%J˜ Jšœžœžœžœ˜1šœ1˜1šœ0˜0Jšœ)žœ˜3——šœžœ žœžœ˜8Jšžœ+˜/—Jšžœ ˜šœ!˜!šžœ&ž˜+šœ2ž˜6Jšœžœ˜+———Jšœ ˜ J˜ J˜—šŸ œžœžœA˜WJšœ žœžœ˜Jšžœ˜J˜(Jšœ žœ˜Jšœ žœ˜Jšœ%˜%J˜ Jšœžœžœ˜šœ\˜\Jšœ)žœ˜3—šœžœ žœžœ˜8Jšžœ+˜/—Jšœ ˜ J˜ —J˜šŸ œžœ6˜Išœ"˜"Jšœžœ+˜=—J˜—š Ÿœžœžœžœ+žœ˜cJ˜(Jšœ žœ˜Jšœ žœ˜J˜ Jšœžœžœ˜šœH˜HJšœ)žœ˜3—šœžœ žœžœ˜8Jšžœ+˜/—J˜ J˜—š Ÿ œžœžœ žœžœ˜YJ˜(Jšœ žœ˜Jšœ žœ˜J˜ Jšœžœžœ˜šœF˜FJšœ)žœ˜3—šœžœ žœžœ˜8Jšžœ+˜/—J˜ J˜—Jšœžœžœ˜"Jšœžœžœ ˜/Jšœ žœ˜J˜šŸ œžœžœ˜Jšžœžœžœ˜šžœžœ˜Jš(™(J˜P—J˜J˜J˜—šŸœžœžœ9˜QJšžœžœžœ˜šžœ!ž˜'J˜=J˜——šŸœžœ4žœžœ˜]Jšžœ ˜ J˜J˜J˜J˜Jšœžœ˜J˜#J˜Jšœ žœ˜J˜šŸ œžœ˜ Jšžœžœžœ˜!Jšžœžœžœžœ˜,J˜J˜—šŸœžœžœ žœ˜(Jšžœžœ˜ J˜—šŸœžœžœž œ˜&Jšžœ˜#J˜—šŸ œžœ˜Jšœ#žœ ˜3J˜Jšœ*žœ˜0J˜—šŸœžœ˜Jš žœ žœžœžœžœ˜:Jšœ˜J˜/J˜—šŸœžœ˜Jšœžœ˜Jšœžœ˜)Jšžœ žœžœ$˜7J˜—šŸœžœ$žœžœ˜CJšœžœ˜ J˜ J˜&J˜!Jšžœ#˜)J˜—šŸœžœžœžœ˜'Jšžœ#˜)J˜—šŸœžœ˜Jšœžœ˜ Jšžœ%žœžœžœ˜HJ˜J˜9J˜—šŸœžœžœžœ˜ Jšœ ˜ Jšžœ+˜1J˜—šŸœžœžœ˜0Jšœ žœ$˜5J˜—šŸ œžœžœ ˜%J˜"J˜J˜Jšœžœ ˜J˜Jšžœžœžœžœ˜.Jšœ žœ ˜J˜Jšžœžœžœžœ˜/Jšœžœ ˜J˜$J˜Jšžœžœžœžœ˜.Jšœ žœ ˜J˜Jšžœžœ ˜J˜—šŸœžœžœ˜"Jšžœ ˜Jšœ3žœ˜AJ˜——Jš™˜Jšœžœ˜+Jš œžœžœ žœžœ˜%J˜Jšœžœ˜J˜šž˜šžœž˜šžœ3˜5˜&Jšžœ,˜4—Jšœžœ˜—šžœ#˜%˜&Jšžœ%˜-——˜ Jšžœžœžœžœ˜:J˜Jšžœžœžœžœ˜(Jšœžœ˜—˜J˜J˜-—˜J˜J˜+Jšœžœ˜—˜J˜Jšžœ žœžœ&žœ˜PJš žœ žœžœžœžœ˜:šžœžœ˜6J˜+—šžœ ž˜Jšœžœ˜#Jšœ˜/Jšžœžœ ˜+—Jšœ ˜9Jšœžœ˜—šœ /˜9J˜J˜J˜Jš žœ žœžœžœžœ˜:Jšœ˜.šžœ ž˜Jš œžœžœ žœžœ˜:J˜=J˜J˜š žœžœžœ žœ˜7J˜šŸ œžœžœ˜"Jš žœžœžœ žœžœžœ˜;J˜'—šžœž˜šžœ˜˜ Jšžœ ˜(——J˜"J˜"J˜"˜Jš,™,J˜J˜-J˜-Jšœ"žœ ˜7—Jšžœžœ˜—J˜+Jšžœ˜—šœ žœ žœžœ ž˜-J˜0—Jšžœ˜—Jšœ"˜4J˜Jšœžœ˜—˜ J˜4J˜ Jšœžœ˜—˜Jšœ"žœ˜GJ˜ Jšœžœ˜—˜J˜J˜,J˜Jšœžœ˜—˜˜&Jšžœ˜%—J˜Jšœžœ˜—˜J˜4J˜Jšœžœ˜—˜˜!Jšœžœ˜&—J˜Jšœžœ˜—˜Jš žœžœžœžœ˜1Jšœ$!˜EJšœžœ˜—Jšžœžœ˜—Jš4™4Jšœ#žœ ˜2J˜Jšžœžœž˜)Jšžœ-žœ˜7J˜Jšžœ˜—šžœžœžœ˜5Jš žœžœžœžœ ˜8Jšžœ˜(—Jšœ žœ˜Jšœ"žœ žœžœ˜CJ˜J˜—šŸ œžœžœ˜J˜J˜—Jšžœ˜J˜—…—(4ù