DIRECTORY Atom USING [MakeAtom], CIFS USING [Close, OpenFile], CreateNode USING [CreateFromInfo, SpanInfo, SpanInfoRec], File USING [Capability], FileReader USING [FreeReply, Reply, FromRope, FromStream, Open, OpenC], IO USING [Handle], NameSymbolTable USING [MakeName, Name], NodeProps USING [DoSpecs, PutProp], PGSupport USING [CreatePGF, EnterLooks, EnterProp, EnterTypeName, FreePGF, PGF, RetrieveLooks, RetrieveProp, RetrieveTypeName], PutGet USING [MaxLen], Rope USING [Find, FromRefText, Lower, ROPE, Size, Substr, Translate], RopeReader USING [Backwards, BumpIndex, Get, GetString, Position, ReadOffEnd, Ref, SetIndex], RopeEdit USING [ROPE, Substr], System USING [GreenwichMeanTime], T1FileOps, TiogaLooks USING [BaseRuns, Looks, Runs], TiogaLooksOps USING [Concat, LooksBytes], TiogaLooksSupport USING [NewBase, Short], TiogaNode USING [defaultTextClassID, Offset, Node, Ref, RefBranchNode, RefTextNode], TiogaNodeOps USING [DocFromNode, FromRope, NarrowToBranchNode, NewBranchNode, NewTextNode]; GetFileImpl: CEDAR PROGRAM IMPORTS Atom, CIFS, CreateNode, FileReader, NameSymbolTable, NodeProps, PGSupport, Rope, RopeEdit, RopeReader, TiogaLooksOps, TiogaLooksSupport, TiogaNodeOps EXPORTS PutGet SHARES TiogaNode = BEGIN Byte: TYPE = [0..255]; FromFileError: PUBLIC ERROR = CODE; FromFile: PUBLIC PROC [ fileName: Rope.ROPE, start: TiogaNode.Offset _ 0, len: TiogaNode.Offset _ PutGet.MaxLen] RETURNS [node: TiogaNode.Ref] = { ForceLower: PROC [r: Rope.ROPE] RETURNS [Rope.ROPE] = { ForceCharLower: SAFE PROC [old: CHAR] RETURNS [new: CHAR] = TRUSTED { RETURN [Rope.Lower[old]] }; RETURN [Rope.Translate[base: r, translator: ForceCharLower]] }; reply: FileReader.Reply; fh: CIFS.OpenFile; createDate: System.GreenwichMeanTime; dot: INTEGER; ext: Rope.ROPE; [reply, fh, createDate] _ FileReader.Open[fileName, start, len]; node _ BuildTiogaStructure[reply]; CIFS.Close[fh]; NodeProps.PutProp[node, $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[node, createDate] }; FromFileC: PUBLIC PROC [ file: File.Capability, start: TiogaNode.Offset _ 0, len: TiogaNode.Offset _ PutGet.MaxLen] RETURNS [node: TiogaNode.Ref] = { reply: FileReader.Reply; createDate: System.GreenwichMeanTime; [reply,createDate] _ FileReader.OpenC[file,start,len]; node _ BuildTiogaStructure[reply]; AddCreateDate[node, createDate];}; AddCreateDate: PROC [node: TiogaNode.Ref, createDate: System.GreenwichMeanTime] = { NodeProps.PutProp[node, $FileCreateDate, NEW[System.GreenwichMeanTime _ createDate]] }; FromRope: PUBLIC PROC [ rope: Rope.ROPE, start: TiogaNode.Offset _ 0, len: TiogaNode.Offset _ PutGet.MaxLen] RETURNS [node: TiogaNode.Ref] = { node _ BuildTiogaStructure[FileReader.FromRope[rope,start,len]] }; FromStream: PUBLIC PROC [stream: IO.Handle, len: TiogaNode.Offset _ PutGet.MaxLen] RETURNS [node: TiogaNode.Ref] = { node _ BuildTiogaStructure[FileReader.FromStream[stream,len]] }; BuildTiogaStructure: PROCEDURE [fileInfo: FileReader.Reply] RETURNS [node: TiogaNode.Ref] = { info: CreateNode.SpanInfo; IF fileInfo.fileType#Tioga2 THEN node _ BuildT2FromT1[fileInfo.control, fileInfo.comment, fileInfo.text, fileInfo.fileType=Tioga1] ELSE IF fileInfo.flags=0C THEN -- file contains a non-branch node _ CreateNode.CreateFromInfo[ fileInfo.fileRope, fileInfo.textStart, fileInfo.textLen, fileInfo.controlStart, fileInfo.controlLen] ELSE { -- file contains a branch info _ NEW[CreateNode.SpanInfoRec]; node _ TiogaNodeOps.NewBranchNode[]; node.internalRepCreated _ FALSE; node.externalRepValid _ TRUE; info.externalRepRope _ fileInfo.fileRope; info.charsStart _ fileInfo.textStart; info.charsLen _ fileInfo.textLen; info.ctrlStart _ fileInfo.controlStart; info.ctrlLen _ fileInfo.controlLen; NodeProps.PutProp[node, $BranchInfo, info] }; FileReader.FreeReply[fileInfo] }; BuildT2FromT1: PROC [control, cmmnt, stext: RopeReader.Ref, tiogaFile: BOOL] RETURNS [rootBranch: TiogaNode.RefBranchNode] = { op: T1FileOps.Op; parentBranch, prevBranch, newBranch: TiogaNode.RefBranchNode; newText: TiogaNode.RefTextNode; terminalNode: BOOLEAN; textLength, runsLength: TiogaNode.Offset _ 0; typename: NameSymbolTable.Name; propname: ATOM; pgf: PGSupport.PGF _ PGSupport.CreatePGF[]; text: REF TEXT _ NEW[TEXT[32]]; GetAtom: PROC RETURNS [ATOM] = { GetText[]; -- get the print name RETURN [Atom.MakeAtom[Rope.FromRefText[text]]] }; GetControlRope: PROC RETURNS [Rope.ROPE] = { RETURN [GetRope[ReadLength[], control]] }; GetName: PROC RETURNS [NameSymbolTable.Name] = { GetText[]; RETURN [NameSymbolTable.MakeName[text]] }; GetRope: PROC [len: TiogaNode.Offset, rdr: RopeReader.Ref] RETURNS [Rope.ROPE] = { rope: Rope.ROPE; pos: TiogaNode.Offset; [rope,pos] _ RopeReader.Position[rdr]; RopeReader.SetIndex[rdr,pos+len]; RETURN [RopeEdit.Substr[rope,pos,len]] }; GetText: PROC = { len: NAT; IF (len _ ReadByte[]) > text.maxLength THEN text _ NEW[TEXT[len]]; text.length _ 0; text.length _ RopeReader.GetString[control, text, len] }; NextOp: PROC RETURNS [op: T1FileOps.Op] = { op _ RopeReader.Get[control ! RopeReader.ReadOffEnd => { op _ T1FileOps.endOfFile; CONTINUE } ]; }; ReadByte: PROC RETURNS [Byte] = INLINE { RETURN [LOOPHOLE[ReadChar[]]] }; ReadChar: PROC RETURNS [CHARACTER] = { RETURN [RopeReader.Get[control]] }; ReadLength: PROC RETURNS [TiogaNode.Offset] = { first, second, fourth: T1FileOps.LengthByte; third: T1FileOps.ThirdByte; card: T1FileOps.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]] }; ReadProp: PROC = { specs: Rope.ROPE _ GetControlRope[]; value: REF _ NodeProps.DoSpecs[propname, specs, 0, LAST[INT], newBranch]; IF value # NIL THEN NodeProps.PutProp[newBranch, propname, value] }; GraftOnTextNode: PROCEDURE [] RETURNS [] = { newBranch.contents _ newText _ TiogaNodeOps.NewTextNode[TiogaNode.defaultTextClassID]; -- hang stmt off brnch newText.next _ newBranch }; terminalNode _ FALSE; parentBranch _ NIL; -- means need to establish a root node prevBranch _ NIL; -- means no oldest child yet op _ NextOp[]; DO SELECT op FROM IN [T1FileOps.terminalTextNodeFirst..T1FileOps.terminalTextNodeLast] => { typename _ PGSupport.RetrieveTypeName[ LOOPHOLE[op-T1FileOps.terminalTextNodeFirst, T1FileOps.TypeIndex], pgf]; terminalNode _ TRUE }; IN [T1FileOps.startNodeFirst..T1FileOps.startNodeLast] => { typename _ PGSupport.RetrieveTypeName[ LOOPHOLE[op-T1FileOps.startNodeFirst, T1FileOps.TypeIndex], pgf] }; T1FileOps.endNode => { IF prevBranch#NIL THEN { prevBranch.last _ TRUE; prevBranch.next _ parentBranch }; prevBranch _ parentBranch; IF (parentBranch _ TiogaNodeOps.NarrowToBranchNode[parentBranch.next])=NIL THEN EXIT; op _ NextOp[]; LOOP }; T1FileOps.startNode => { typename _ GetName[]; [] _ PGSupport.EnterTypeName[typename,pgf] }; T1FileOps.terminalTextNode => { typename _ GetName[]; [] _ PGSupport.EnterTypeName[typename,pgf]; terminalNode _ TRUE }; T1FileOps.rope, T1FileOps.comment => { reader: RopeReader.Ref; IF newText=NIL THEN GraftOnTextNode[]; IF op=T1FileOps.rope THEN reader _ stext ELSE { reader _ cmmnt; newText.comment _ TRUE }; IF (textLength_ReadLength[]) > 0 THEN -- get the rope newText.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 }; T1FileOps.runs => { -- runs, if any, come before corresponding rope lookRuns: TiogaLooks.Runs; numRuns: TiogaNode.Offset; pos: TiogaNode.Offset _ 0; IF newText=NIL THEN GraftOnTextNode[]; numRuns _ ReadLength[]; -- read number of runs WHILE numRuns > 0 DO num: NAT _ TiogaLooksSupport.Short[MIN[numRuns,LAST[NAT]]]; baseRuns: TiogaLooks.BaseRuns _ TiogaLooksSupport.NewBase[num]; len: TiogaNode.Offset _ pos; numRuns _ numRuns-num; FOR i:NAT IN [0..num) DO -- read runs for this baseRuns looks: TiogaLooks.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 [T1FileOps.looksFirst .. T1FileOps.looksLast] => looks _ PGSupport.RetrieveLooks[ LOOPHOLE[op-T1FileOps.looksFirst, T1FileOps.LooksIndex],pgf]; T1FileOps.look1 => ReadLookChars[1]; T1FileOps.look2 => ReadLookChars[2]; T1FileOps.look3 => ReadLookChars[3]; T1FileOps.looks => { -- read 4 bytes of looks from control stream lb: TiogaLooksOps.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 TiogaLooksOps.Concat[lookRuns,baseRuns,len,pos-len]; ENDLOOP; runsLength _ pos; -- for use in checking rope length newText.runs _ lookRuns; op _ NextOp[]; LOOP }; T1FileOps.prop => { [] _ PGSupport.EnterProp[propname _ GetAtom[], pgf]; ReadProp; op _ NextOp[]; LOOP }; T1FileOps.propShort => { propname _ PGSupport.RetrieveProp[LOOPHOLE[ReadByte[], T1FileOps.PropIndex], pgf]; ReadProp; op _ NextOp[]; LOOP }; T1FileOps.endOfFile => { IF parentBranch=NIL THEN EXIT; -- have reached the root [] _ RopeReader.Backwards[control]; -- backup so read endOfFile again op _ T1FileOps.endNode; LOOP }; ENDCASE => ERROR FromFileError; newBranch _ TiogaNodeOps.NewBranchNode[]; IF prevBranch#NIL THEN { prevBranch.next _ newBranch; prevBranch.last _ FALSE; newBranch.next _ parentBranch; prevBranch _ newBranch } ELSE IF parentBranch#NIL THEN { parentBranch.child _ newBranch; newBranch.next _ parentBranch; prevBranch _ newBranch } ELSE { parentBranch _ newBranch; parentBranch.next _ NIL; prevBranch _ NIL }; newText _ NIL; newBranch.format _ typename; IF terminalNode THEN terminalNode _ FALSE -- reset to default case ELSE { parentBranch _ newBranch; prevBranch _ NIL }; op _ NextOp[]; ENDLOOP; IF (rootBranch _ prevBranch)=NIL THEN -- don't have a normal tree IF newBranch=NIL THEN -- null file rootBranch _ TiogaNodeOps.DocFromNode[TiogaNodeOps.FromRope[NIL]] ELSE rootBranch _ newBranch; rootBranch.last _ TRUE; NodeProps.PutProp[rootBranch, $FromTiogaFile, IF tiogaFile THEN $Yes ELSE $No]; PGSupport.FreePGF[pgf] }; END. HGetFileImpl.Mesa; Written by Paxton. January 1981 Last edited by Paxton - August 19, 1983 9:22 am Now put file wide attributes on root node Read a rope from the control stream Attaches a text node to the current branch contents field -- BODY OF BuildTiogaStructure leaf node - using earlier format branch node - using earlier format end node - pop up a level branch node - new type of format leaf node - new type of format text or comments runs of looks node properties - new sort node properties - old sort end of file If reach here, then want to start a new branch node. Ê ä˜JšÏc™Jš ™ Jš/™/J˜šÏk ˜ Jšœ žœ ˜Jšžœžœ˜!Jšœ žœ)˜;Jšœ žœ˜Jšœ žœ7˜IJšžœžœ ˜Jšœžœ˜(Jšœ žœ˜%Jšœ žœp˜Jšœ žœ ˜Jšœ žœžœ˜IJšœ žœM˜_Jšœ žœžœ ˜!Jšœ žœ˜$Jšœ ˜ Jšœ žœ˜+Jšœžœ˜*Jšœžœ˜*Jšœ žœE˜VJšœžœI˜\—J˜šœ ž ˜JšžœžœŒ˜žJšžœ˜Jšžœ žœ˜—J˜Jšœžœ ˜J˜Jšœžœžœžœ˜#J˜šÏnœžœžœ˜JšœžœE˜XJšžœ˜!š Ÿ œžœ žœžœžœ˜7šŸœžœžœžœžœžœžœ˜EJšžœ˜—Jšžœ9˜?—Jšœ˜Jšœžœ ˜Jšœ%˜%Jšœžœ˜ Jšœ žœ˜Jšœœ(˜@Jšœ"˜"Jšžœ ˜J™)šœ'˜'šžœ&žœ3ž˜bJšœžœ˜+——Jšœ"˜"J˜—šŸ œžœžœ˜JšœZ˜ZJšžœ˜!Jšœ˜Jšœ%˜%Jšœ6˜6Jšœ"˜"Jšœ"˜"J˜—šŸ œžœ@˜SJšœ)žœ+˜WJ˜—šŸœžœžœ˜Jšœ žœE˜TJšžœ˜!JšœB˜BJ˜—šŸ œžœžœ žœ/˜RJšžœ˜!Jšœ@˜@J˜—šŸœž œ˜;Jšžœ˜!Jšœ˜šžœž˜ Jšœa˜a—šžœžœžœ˜<šœ!˜!Jšœd˜d——šžœ˜ Jšœžœ˜#Jšœ$˜$Jšœžœ˜ Jšœžœ˜Jšœ)˜)Jšœ%˜%Jšœ!˜!Jšœ'˜'Jšœ#˜#Jšœ-˜-—J˜!J˜—šŸ œžœ4žœ˜LJšžœ*˜1—˜Jšœ˜Jšœ=˜=Jšœ˜Jšœžœ˜Jšœ-˜-Jšœ˜Jšœ žœ˜Jšœžœ˜+Jš œžœžœžœžœ˜J™J™šŸœžœžœžœ˜ Jšœ ˜ Jšžœ+˜1J˜—šŸœžœžœžœ˜,J™#Jšžœ$˜*J˜—šŸœžœžœ˜0Jšœ ˜ Jšžœ$˜*J˜—šŸœžœ.žœžœ˜RJšœ žœ˜Jšœ˜J˜&J˜!Jšžœ#˜)J˜—šŸœžœ˜Jšœžœ˜ Jšžœ%žœžœžœ˜BJ˜J˜9J˜—šŸœžœžœ˜,šœ˜Jšœžœž œ ˜H—J˜—š Ÿœžœžœ žœžœžœ˜IJ˜—š Ÿœžœžœž œžœ˜JJ˜—šŸ œžœžœ˜/Jšœ,˜,Jšœ˜Jšœ˜Jšœžœ ˜J˜Jšžœžœžœžœ˜.Jšœ žœ ˜J˜Jšžœžœžœžœ˜/Jšœžœ ˜J˜$J˜Jšžœžœžœžœ˜.Jšœ žœ ˜J˜Jšžœžœ ˜J˜—šŸœžœ˜Jšœ žœ˜$Jšœžœ)žœžœ˜IJšžœ žœžœ1˜D—J˜šŸœž œžœ˜,J™9šœ˜Jšœ8˜N—Jšœ˜J˜—Jš œ™J™Jšœžœ˜Jšœžœ&˜:Jšœ žœ˜0Jšœ˜šž˜šžœž˜šžœG˜IJšœ ™ šœ&˜&Jšžœ@˜H—Jšœžœ˜J˜—šžœ9˜;Jšœ"™"šœ&˜&Jšžœ;˜C—J˜—šœ˜J™šžœ žœžœ˜Jšœžœ˜Jšœ!˜!—Jšœ˜JšžœEžœžœžœ˜UJšœ˜Jšžœ˜J˜—šœ˜J™ J˜J˜-J˜—šœ˜J™J˜Jšœ+˜+Jšœžœ˜J˜—šœ&˜&J™J˜Jšžœ žœžœ˜&Jšžœžœžœ%žœ˜Yšžœžœ˜6Jšœ*˜*—šžœ ž˜Jšœ žœ˜'Jšœ˜0Jšžœžœ ˜,—Jšœ ˜9Jšœ˜Jšžœ˜J˜—šœ/˜CJ™ J˜Jšœ˜Jšœ˜Jšžœ žœžœ˜&Jšœ˜.šžœ ž˜Jš œžœžœ žœžœ˜;J˜?Jšœ˜J˜š žœžœžœ žœ˜7J˜šŸ œžœžœ˜"Jš žœžœžœ žœžœžœ˜;J˜'—šžœž˜šžœ1˜3˜ Jšžœ5˜=——Jšœ$˜$Jšœ$˜$Jšœ$˜$šœ˜Jš,˜,J˜J˜-J˜-Jšœ"žœ ˜7—Jšžœžœ˜—J˜+Jšžœ˜—šœ žœ žœžœ ž˜-J˜4—Jšžœ˜—Jšœ"˜4Jšœ˜Jšœ˜Jšžœ˜J˜—šœ˜J™J˜4J˜ Jšœ˜Jšžœ˜J˜—šœ˜J™Jšœ"žœ(˜RJ˜ Jšœ˜Jšžœ˜J˜—šœ˜Jšœ ™ Jš žœžœžœžœ˜7Jšœ$!˜EJšœ˜Jšžœ˜J˜—Jšžœžœ˜J˜—Jš5™5Jšœ)˜)šžœ žœžœ˜Jšœ˜Jšœžœ˜Jšœ˜Jšœ˜—šžœžœžœž˜Jšœ˜Jšœ˜Jšœ˜—šžœ˜Jšœ˜Jšœžœ˜Jšœ žœ˜—Jšœ žœ˜Jšœ˜Jšžœžœžœ˜BJšžœ*žœ˜4J˜Jšžœ˜J˜—šžœžœž˜Ašžœ žœžœ ˜"Jšœ<žœ˜A—Jšžœ˜—Jšœžœ˜Jšœ.žœ žœžœ˜OJ˜—J˜Jšžœ˜—…—)ð8