DIRECTORY Atom USING [MakeAtom], IO USING [atom, bool, card, char, CreateViewerStreams, PutChar, PutF, rope, STREAM], NameSymbolTable USING [MakeName, MakeNameFromRope], NodeProps USING [DoSpecs, GetProp, PutProp], PutGet, Rope USING [ROPE, Substr], RopeEdit USING [Concat, Substr], RopeReader USING [Backwards, BumpIndex, FreeRopeReader, Get, GetIndex, GetRopeReader, GetString, Position, Ref, SetIndex, SetPosition], T2FileOps USING [addLooksFirst, addLooksLast, cmt, comment, default, fmt, format, heavyDuty, IntBytes, itemSpace, lastLooksFirst, lastLooksLast, LengthByte, noClassData, noLooks, Op, prop, runs, startBI, startBranch, startBX, startClassData, startLI, startTI, ThirdByte], TiogaLooks USING [BaseRuns, Look, Looks, noLooks, Runs], TiogaLooksOps USING [Concat], TiogaLooksSupport USING [Short, NewBase], TiogaBasicClass USING [BasicClass], TiogaItemClass USING [ItemClass], TiogaNode USING [Name, Offset, Ref, RefBranchNode, RefItemNode, RefTextNode, RefBoxNode, RefBasicNode, RefListNode], TiogaNodeOps USING [FetchBasicClass, FetchItemClass, LookupBasicID, LookupItemID, NewBasicNode, NewBranchNode, NewBoxNode, NewListNode, NewTextNode]; GetT2FileImpl: CEDAR PROGRAM IMPORTS Atom, IO, NameSymbolTable, NodeProps, PutGet, Rope, RopeEdit, RopeReader, TiogaLooksOps, TiogaLooksSupport, TiogaNodeOps EXPORTS PutGet = BEGIN Debug:BOOLEAN = FALSE; -- says if to generate trace info. report:IO.STREAM; -- trace info. stream Tioga2FileFormatError: PUBLIC SIGNAL = CODE; -- raised for all format faults ClassNotAvailable: PUBLIC SIGNAL = CODE; -- raised when item class not registered NoBranchParseInfo: PUBLIC SIGNAL = CODE; -- raised when client does not supply BranchInfo CreateInternalRep: PUBLIC PROC [br:TiogaNode.RefBranchNode, wholeTree:BOOLEAN_FALSE] = { brInfo:PutGet.SpanInfo _ NARROW[NodeProps.GetProp[br, $BranchInfo]]; copy:PutGet.SpanInfo; control:RopeReader.Ref _ RopeReader.GetRopeReader[]; PutGet.GCBigInterval[]; IF wholeTree THEN { copy _ NEW[PutGet.SpanInfoRec]; copy^ _ brInfo^; }; CIR[ br:br, brInfo:IF wholeTree THEN copy ELSE brInfo, wholeTree:wholeTree, indent:0, textBuffer: NEW[TEXT[32]], control:control]; RopeReader.FreeRopeReader[control]; PutGet.GCRestoreInterval[] }; CIR: PROCEDURE [br:TiogaNode.RefBranchNode, brInfo:PutGet.SpanInfo, wholeTree:BOOLEAN, indent:CARDINAL, textBuffer:REF TEXT, control:RopeReader.Ref] = { -- branch ::= optCmt {prop} optFormat {item} lastItem {child} {childHK} startHK nchild ; Indent: PROCEDURE [] = { FOR i:CARDINAL IN [1..indent] DO IO.PutChar[report, ' ]; ENDLOOP }; NextOp: PROC RETURNS [T2FileOps.Op] = INLINE { RETURN[RopeReader.Get[control]]; }; ReadB32: PROCEDURE [] RETURNS [n:INT] = { first, second, fourth: T2FileOps.LengthByte; third: T2FileOps.ThirdByte; card: T2FileOps.IntBytes; first _ LOOPHOLE[RopeReader.Backwards[control]]; card.first _ first.data; IF ~first.others THEN -- value within 7 bits so terminate RETURN [LOOPHOLE[card]]; second _ LOOPHOLE[RopeReader.Backwards[control]]; card.second _ second.data; IF ~second.others THEN -- value within 14 bits so terminate RETURN [LOOPHOLE[card]]; third _ LOOPHOLE[RopeReader.Backwards[control]]; card.thirdBottom _ third.dataBottom; card.thirdTop _ third.dataTop; IF ~third.others THEN -- value within 21 bits so terminate RETURN [LOOPHOLE[card]]; fourth _ LOOPHOLE[RopeReader.Backwards[control]]; card.fourth _ fourth.data; RETURN [LOOPHOLE[card]] -- full 28 bit value }; ReadF32: PROCEDURE [] RETURNS [n:INT] = { first, second, fourth: T2FileOps.LengthByte; third: T2FileOps.ThirdByte; card: T2FileOps.IntBytes; first _ LOOPHOLE[RopeReader.Get[control]]; card.first _ first.data; IF ~first.others THEN -- value within 7 bits so terminate RETURN [LOOPHOLE[card]]; second _ LOOPHOLE[RopeReader.Get[control]]; card.second _ second.data; IF ~second.others THEN -- value within 14 bits so terminate RETURN [LOOPHOLE[card]]; third _ LOOPHOLE[RopeReader.Get[control]]; card.thirdBottom _ third.dataBottom; card.thirdTop _ third.dataTop; IF ~third.others THEN -- value within 21 bits so terminate RETURN [LOOPHOLE[card]]; fourth _ LOOPHOLE[RopeReader.Get[control]]; card.fourth _ fourth.data; RETURN [LOOPHOLE[card]] -- full 28 bit value }; ReadAtom: PROCEDURE [] RETURNS [ATOM] = INLINE { RETURN[Atom.MakeAtom[ReadRope[ReadF32[], control]]]; }; ReadContents: PROCEDURE [parent:TiogaNode.Ref] RETURNS [head:TiogaNode.Ref] = { -- contents ::= [ labelledBranch | item | basic ] ; previous, item:TiogaNode.Ref; DO SELECT op FROM IN [T2FileOps.startTI..T2FileOps.startLI) => item _ ReadTextItem[]; IN [T2FileOps.startLI..T2FileOps.startLI+T2FileOps.itemSpace) => -- list items item _ ReadNonTextItem[offset:op-T2FileOps.startLI, new:TiogaNodeOps.NewListNode[]]; IN [T2FileOps.startBI..T2FileOps.startBI+T2FileOps.itemSpace) => -- basic items item _ ReadNonTextItem[offset:op-T2FileOps.startBI, new:TiogaNodeOps.NewBasicNode[]]; IN [T2FileOps.startBX..T2FileOps.startBX+T2FileOps.itemSpace) => -- box items item _ ReadNonTextItem[offset:op-T2FileOps.startBX, new:TiogaNodeOps.NewBoxNode[]]; T2FileOps.startBranch => { -- orphan branch controlRope, textRope: Rope.ROPE; controlStart, textStart, controlLen, textLen: TiogaNode.Offset; br: TiogaNode.RefBranchNode _ TiogaNodeOps.NewBranchNode[]; orphanBrInfo: PutGet.SpanInfo _ NEW[PutGet.SpanInfoRec]; textLen _ ReadF32[]; -- labelled branch text length controlLen _ ReadF32[]; -- control length [controlRope, controlStart] _ RopeReader.Position[control]; [textRope, textStart] _ RopeReader.Position[text]; orphanBrInfo.externalRepRope _ RopeEdit.Concat[RopeEdit.Substr[textRope, textStart, textLen], RopeEdit.Substr[controlRope, controlStart, controlLen], textLen, controlLen]; br.internalRepCreated _ FALSE; orphanBrInfo.charsStart _ 0; orphanBrInfo.ctrlStart _ orphanBrInfo.charsLen _ textLen; orphanBrInfo.ctrlLen _ controlLen; br.externalRepValid _ ~wholeTree; -- C.F. current.externalRepValid _ ~wholeTree IF wholeTree THEN CIR[ br:br, brInfo:orphanBrInfo, wholeTree:TRUE, indent:indent+5, textBuffer:textBuffer, control:control] -- don't attache, props ELSE NodeProps.PutProp[br, $BranchInfo, orphanBrInfo]; -- attache to branch stub item _ br; RopeReader.SetPosition[control, controlRope, controlStart+controlLen]; -- skip branch RopeReader.SetPosition[text, textRope, textStart+textLen]; -- skip branch }; ENDCASE => { -- anything but an item causes termination of chain IF head=NIL THEN head _ previous _ item; IF item#NIL THEN { -- if no items at all then return NIL previous.next _ parent; previous.last _ TRUE; }; RETURN ; }; IF previous=NIL THEN head _ previous _ item ELSE { previous.next _ item; previous _ item; }; previous.last _ FALSE; -- there might be some more op _ NextOp[]; ENDLOOP }; ReadFormat: PROCEDURE [] RETURNS [n:TiogaNode.Name] = INLINE { -- format ::= symbol ; len:TiogaNode.Offset _ ReadF32[]; IF len>LAST[NAT] THEN { -- mega-symbols need special treatment format:Rope.ROPE _ ReadRope[len, control]; IF Debug THEN { Indent[]; IO.PutF[report, "Format[%g]\n", IO.rope[format]] }; RETURN [NameSymbolTable.MakeNameFromRope[format]] } ELSE { IF len > textBuffer.maxLength THEN textBuffer _ NEW[TEXT[len]]; textBuffer.length _ 0; textBuffer.length _ RopeReader.GetString[control, textBuffer, len]; n _ NameSymbolTable.MakeName[textBuffer]; }; }; ReadItemList: PROCEDURE [parent:TiogaNode.Ref] RETURNS [head:TiogaNode.Ref] = { -- {item} lastItem -- item ::= [defaultTextItem | textItem | defaultTextItemHeavyDuty | textItemHeavyDuty | listItem | boxItem] ; previous, item:TiogaNode.Ref; DO SELECT op FROM IN [T2FileOps.startTI..T2FileOps.startLI) => item _ ReadTextItem[]; -- text items IN [T2FileOps.startLI..T2FileOps.startBI) => -- list items item _ ReadNonTextItem[offset:op-T2FileOps.startLI, new:TiogaNodeOps.NewListNode[]]; IN [T2FileOps.startBX..T2FileOps.startBX+T2FileOps.itemSpace) => -- box items item _ ReadNonTextItem[offset:op-T2FileOps.startBX, new:TiogaNodeOps.NewBoxNode[]]; ENDCASE => { -- anything else causes termination of chain IF head=NIL THEN head _ previous _ item; IF item#NIL THEN { -- if no items at all then return NIL previous.next _ parent; previous.last _ TRUE; }; RETURN ; }; IF previous=NIL THEN head _ previous _ item ELSE { previous.next _ item; previous _ item; }; previous.last _ FALSE; -- there might be some more op _ NextOp[]; ENDLOOP }; ReadNonTextItem: PROCEDURE [offset:CARDINAL, new:TiogaNode.Ref] RETURNS [TiogaNode.Ref] = { OPEN T2FileOps; -- ** ACHTUNG! ACHTUNG! ACHTUNG! doHD, doCmt, doRuns, doFmt, doDefault:BOOLEAN _ FALSE; classData:Rope.ROPE _ NIL; IF offset>=heavyDuty THEN { -- it has props and/or contents offset _ offset - heavyDuty; doHD _ TRUE; }; SELECT offset FROM 0 => NULL; cmt => { doCmt _ TRUE}; fmt => { doFmt _ TRUE}; fmt+cmt => { doFmt _ doCmt _ TRUE}; default => { doDefault _ TRUE}; default+cmt => { doDefault _ doCmt _ TRUE}; default+fmt => { doDefault _ doFmt _ TRUE}; default+fmt+cmt => { doDefault _ doFmt _ doCmt _ TRUE}; ENDCASE => ERROR; -- offset out of range!!! IF Debug THEN { Indent[]; IO.PutF[report, "OTHER "]; indent _ indent + 2; }; new.comment _ doCmt; WITH new SELECT FROM bx:TiogaNode.RefBoxNode => { -- BOX NODES classInfo:TiogaItemClass.ItemClass; IF doHD THEN { IF Debug THEN IO.PutF[report, "Heavy Duty\n"]; FOR op _ NextOp[], NextOp[] WHILE op=prop DO -- read any properties ReadProp[bx]; ENDLOOP; IF Debug THEN { Indent[]; IO.PutF[report, "CONTENTS\n"]; }; bx.contents _ ReadContents[bx]; } ELSE { IF Debug THEN IO.PutF[report, "Regular\n"]; op _ NextOp[]; }; SELECT op FROM startClassData => classData _ ReadRope[ReadF32[], control]; noClassData => NULL; ENDCASE => SIGNAL Tioga2FileFormatError; bx.class _ TiogaNodeOps.LookupItemID[IF doDefault THEN $Box ELSE ReadAtom[]]; classInfo _ TiogaNodeOps.FetchItemClass[bx.class]; IF classInfo.set=NIL THEN SIGNAL ClassNotAvailable ELSE classInfo.set[bx, $Restore, classData]; -- finalise? IF Debug THEN { Indent[]; IO.PutF[report, "Class:%g Comment:%g\n", IO.atom[classInfo.flavor], IO.bool[doCmt]]; }; IF doFmt THEN bx.format _ ReadFormat[]; }; bs:TiogaNode.RefBasicNode => { -- BASIC NODES classInfo:TiogaBasicClass.BasicClass; IF doHD THEN { IF Debug THEN IO.PutF[report, "Heavy Duty\n"]; FOR op _ NextOp[], NextOp[] WHILE op=prop DO -- read any properties ReadProp[bs]; ENDLOOP; } ELSE { IF Debug THEN IO.PutF[report, "Regular\n"]; op _ NextOp[]; }; SELECT op FROM startClassData => classData _ ReadRope[ReadF32[], control]; noClassData => NULL; ENDCASE => SIGNAL Tioga2FileFormatError; bs.class _ TiogaNodeOps.LookupBasicID[IF doDefault THEN $Basic ELSE ReadAtom[]]; classInfo _ TiogaNodeOps.FetchBasicClass[bs.class]; IF classInfo.set=NIL THEN SIGNAL ClassNotAvailable ELSE classInfo.set[bs, $Restore, classData]; -- finalise? IF Debug THEN { Indent[]; IO.PutF[report, "Class:%g Comment:%g\n", IO.atom[classInfo.flavor], IO.bool[doCmt]] }; IF doFmt THEN bs.format _ ReadFormat[]; }; li:TiogaNode.RefListNode => { -- LIST NODES classInfo:TiogaItemClass.ItemClass; IF doHD THEN { IF Debug THEN IO.PutF[report, "Heavy Duty\n"]; FOR op _ NextOp[], NextOp[] WHILE op=prop DO -- read any properties ReadProp[li]; ENDLOOP; IF Debug THEN { Indent[]; IO.PutF[report, "CONTENTS\n"]; }; li.contents _ ReadContents[li]; } ELSE { IF Debug THEN IO.PutF[report, "Regular\n"]; op _ NextOp[]; }; SELECT op FROM startClassData => classData _ ReadRope[ReadF32[], control]; noClassData => NULL; ENDCASE => SIGNAL Tioga2FileFormatError; li.class _ TiogaNodeOps.LookupItemID[IF doDefault THEN $List ELSE ReadAtom[]]; classInfo _ TiogaNodeOps.FetchItemClass[li.class]; IF classInfo.set=NIL THEN SIGNAL ClassNotAvailable ELSE classInfo.set[li, $Restore, classData]; -- finalise? IF Debug THEN { Indent[]; IO.PutF[report, "Class:%g Comment:%g\n", IO.atom[classInfo.flavor], IO.bool[doCmt]] }; IF doFmt THEN li.format _ ReadFormat[]; }; ENDCASE => ERROR; -- ReadNonTextItem called with inappropriate item type IF Debug THEN indent _ indent - 2; RETURN[new] }; ReadProp: PROCEDURE [br:TiogaNode.Ref] = { -- prop ::= prop propName specs -- propName ::= symbol ; -- symbol ::= symbolLength symbolRope ; -- symbolLength ::= FORWARD32 ; -- symbolRope ::= {CHAR}; -- specs ::= specsLength specsRope ; -- specsLength ::= FORWARD32 ; -- specsRope ::= {CHAR}; atom:ATOM _ ReadAtom[]; specs:Rope.ROPE _ ReadRope[ReadF32[], control]; IF Debug THEN { Indent[]; IO.PutF[report, "Property[%g, %g]\n", IO.atom[atom], IO.rope[specs]] }; NodeProps.PutProp[br, atom, NodeProps.DoSpecs[atom, specs, br]] }; ReadRope: PROCEDURE [len:INT, rdr:RopeReader.Ref] RETURNS [Rope.ROPE] = { rope: Rope.ROPE; pos: TiogaNode.Offset; [rope, pos] _ RopeReader.Position[rdr]; -- find out where the start is RopeReader.SetIndex[rdr, pos+len]; -- step reader over it RETURN [RopeEdit.Substr[rope, pos, len]] -- return it }; ReadRuns: PROCEDURE [] RETURNS [lookRuns:TiogaLooks.Runs] = { -- runs ::= noOfRuns {run} ; -- noOfRuns ::= FORWARD32 ; -- run ::= [lookSeq| noLooks] runLength ; -- lookSeq ::= {addlooks} lastLooks -- addlooks ::= BYTE [addLooksFirst..addLooksLast] ; -- lastLooks ::= BYTE [lastLooksFirst..lastLooksLast] ; -- runLength ::= FORWARD32 ; pos: TiogaNode.Offset _ 0; numRuns: TiogaNode.Offset _ ReadF32[]; IF Debug THEN { Indent[]; IO.PutF[report, "Runs (%g) ", IO.card[numRuns]]; }; WHILE numRuns > 0 DO -- ** {run} 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 -- run ReadLooks: PROC [] = { FOR op:CHAR _ NextOp[], NextOp[] DO -- ** [lookSeq | noLooks] SELECT op FROM IN [T2FileOps.addLooksFirst..T2FileOps.addLooksLast] => { c:CHARACTER _ 'a+(op - T2FileOps.addLooksFirst); IF Debug THEN IO.PutF[report, "%g ", IO.char[c]]; looks[c] _ TRUE; }; IN [T2FileOps.lastLooksFirst..T2FileOps.lastLooksLast] => { c:CHARACTER _ 'a+(op - T2FileOps.lastLooksFirst); IF Debug THEN IO.PutF[report, "%g ", IO.char[c]]; looks[c] _ TRUE; EXIT; }; T2FileOps.noLooks => { IF Debug THEN IO.PutF[report, "NoLooks "]; EXIT; }; ENDCASE => SIGNAL Tioga2FileFormatError; ENDLOOP; }; looks: TiogaLooks.Looks _ TiogaLooks.noLooks; lookLen:TiogaNode.Offset; ReadLooks[]; lookLen _ ReadF32[]; baseRuns[i] _ [pos_pos+lookLen, looks]; IF Debug THEN IO.PutF[report, "(%g) ", IO.card[lookLen]]; ENDLOOP; lookRuns _ IF lookRuns=NIL THEN baseRuns ELSE TiogaLooksOps.Concat[lookRuns,baseRuns,len,pos-len]; ENDLOOP; IF Debug THEN IO.PutF[report, "total %g\n", IO.card[pos]]; }; ReadTextItem: PROCEDURE [] RETURNS [item:TiogaNode.RefTextNode] = { OPEN T2FileOps; -- ** ACHTUNG! ACHTUNG! ACHTUNG! ReadCRRope: PROCEDURE [rdr:RopeReader.Ref] RETURNS [rope:Rope.ROPE] = INLINE { rope _ ReadRope[ReadF32[], rdr]; RopeReader.BumpIndex[rdr, 1]; -- skip over CR IF Debug THEN { Indent[]; IO.PutF[report,"%l%g ...%l\n",IO.rope["b"], IO.rope[Rope.Substr[rope, 0, 40]], IO.rope[" "]] }; }; doHD, doCmt, doRuns, doFmt, doDefault:BOOLEAN _ FALSE; offset:CARDINAL; classInfo:TiogaItemClass.ItemClass; SELECT op FROM -- decide if heavy duty item and set offset to get within-type info IN [startTI..startTI+heavyDuty) => {offset _ op - startTI}; IN [startTI+heavyDuty..startLI) => {doHD _ TRUE; offset _ op - (startTI+heavyDuty)}; ENDCASE => ERROR; -- ReadTextItem called with non text item SELECT offset FROM 0 => NULL; cmt => { doCmt _ TRUE}; runs => { doRuns _ TRUE}; runs+cmt => { doRuns _ doCmt _ TRUE}; fmt => { doFmt _ TRUE}; fmt+cmt => { doFmt _ doCmt _ TRUE}; fmt+runs => { doFmt _ doRuns _ TRUE}; fmt+runs+cmt => { doFmt _ doRuns _ doCmt _ TRUE}; default => { doDefault _ TRUE}; default+cmt => { doDefault _ doCmt _ TRUE}; default+runs => { doDefault _ doRuns _ TRUE}; default+runs+cmt => { doDefault _ doRuns _ doCmt _ TRUE}; default+fmt => { doDefault _ doFmt _ TRUE}; default+fmt+cmt => { doDefault _ doFmt _ doCmt _ TRUE}; default+fmt+runs => { doDefault _ doFmt _ doRuns _ TRUE}; default+fmt+runs+cmt => { doDefault _ doFmt _ doRuns _ doCmt _ TRUE}; ENDCASE => ERROR; -- offset out of range!!! item _ TiogaNodeOps.NewTextNode[]; IF Debug THEN { Indent[]; IO.PutF[report, "TEXT "]; indent _ indent + 2; }; IF doHD THEN { IF Debug THEN { IO.PutF[report, "Heavy Duty\n"]; }; FOR op _ NextOp[], NextOp[] WHILE op=prop DO -- read any properties ReadProp[item]; ENDLOOP; } ELSE IF Debug THEN IO.PutF[report, "Regular\n"]; item.class _ TiogaNodeOps.LookupItemID[IF doDefault THEN $Text ELSE ReadAtom[]]; classInfo _ TiogaNodeOps.FetchItemClass[item.class]; IF classInfo=NIL THEN SIGNAL ClassNotAvailable; IF Debug THEN { Indent[]; IO.PutF[report, "Class:%g Comment:%g\n", IO.atom[classInfo.flavor], IO.bool[doCmt]] }; IF doRuns THEN item.runs _ ReadRuns[]; -- construct the runs descriptor IF doFmt THEN item.format _ ReadFormat[]; item.comment _ doCmt; item.rope _ IF doCmt THEN ReadCRRope[control] ELSE ReadCRRope[text]; IF Debug THEN indent _ indent - 2; }; -- optCmt {prop} optFormat {item} lastItem text: RopeReader.Ref; nKids: CARDINAL; prev, current: TiogaNode.RefBranchNode ; kidCtrlStart, kidTextStart: TiogaNode.Offset; op: T2FileOps.Op; IF brInfo=NIL THEN ERROR; -- client did not supply branch info. properties IF Debug THEN { Indent[]; IO.PutF[report, "%gBRANCH Data: %g %g Control: %g %g\n", IF brInfo.ctrlLen=0 THEN IO.rope["CHEAP "] ELSE IO.rope[""], IO.card[brInfo.charsStart], IO.card[brInfo.charsLen], IO.card[brInfo.ctrlStart], IO.card[brInfo.ctrlLen]]; }; text _ RopeReader.GetRopeReader[]; -- get text reader from RR cache IF Debug THEN { Indent[]; IO.PutF[report, " CONTENTS: "]; indent _ indent + 2; }; -- cheapBranch | optCmt {prop} optFormat {item} lastItem RopeReader.SetPosition[text, brInfo.externalRepRope, brInfo.charsStart]; RopeReader.SetPosition[control, brInfo.externalRepRope, brInfo.ctrlStart]; IF brInfo.ctrlLen=0 THEN { IF brInfo.charsLen=0 THEN { IF Debug THEN IO.PutF[report, "EMPTY\n"]; } ELSE { t:TiogaNode.RefTextNode _ br.contents _ TiogaNodeOps.NewTextNode[]; t.class _ TiogaNodeOps.LookupItemID[$Text]; t.next _ br; t.rope _ RopeEdit.Substr[brInfo.externalRepRope, brInfo.charsStart, brInfo.charsLen-1]; -- skip CR IF Debug THEN IO.PutF[report, "%l%g ...%l\n", IO.rope["b"], IO.rope[RopeEdit.Substr[t.rope, 0, 40]], IO.rope[" "]]; }; br.internalRepCreated _ TRUE; -- mark branch as cracked at last indent _ indent - 2; RopeReader.FreeRopeReader[text]; RETURN; }; IF Debug THEN IO.PutF[report, "\n"]; op _ NextOp[]; DO SELECT op FROM T2FileOps.comment => { br.comment _ TRUE; op _ NextOp[] }; T2FileOps.prop => { ReadProp[br]; op _ NextOp[] }; T2FileOps.format => { br.format _ ReadFormat[]; op _ NextOp[] }; ENDCASE => { br.contents _ NARROW[ReadItemList[parent:br]]; EXIT; }; ENDLOOP; kidCtrlStart _ RopeReader.GetIndex[control]; -- remember where the kids start kidTextStart _ RopeReader.GetIndex[text]; RopeReader.FreeRopeReader[text]; -- only play with the control stream hereafter -- {child} {childHK} startHK nchild ; RopeReader.SetPosition[control, brInfo.externalRepRope, brInfo.ctrlStart+brInfo.ctrlLen]; nKids _ ReadB32[]; IF Debug THEN { indent _ indent - 1; Indent[]; IO.PutF[report, "%lChildren %g%l\n", IO.rope["i"], IO.card[nKids], IO.rope[" "]] }; IF nKids>0 THEN { crntInfo:PutGet.SpanInfo; FOR i:CARDINAL IN [1..nKids] DO current _ TiogaNodeOps.NewBranchNode[]; IF prev=NIL THEN br.child _ current ELSE prev.next _ current; current.last _ (i=nKids); -- default is TRUE damnit current.externalRepValid _ ~wholeTree; current.internalRepCreated _ FALSE; -- maybe not going to crack child here IF wholeTree THEN crntInfo _ brInfo ELSE crntInfo _ NEW[PutGet.SpanInfoRec]; crntInfo.externalRepRope _ brInfo.externalRepRope; crntInfo.charsLen _ ReadB32[]; crntInfo.ctrlLen _ ReadB32[]; crntInfo.ctrlStart _ kidCtrlStart ; crntInfo.charsStart _ kidTextStart ; kidCtrlStart _ kidCtrlStart + crntInfo.ctrlLen; kidTextStart _ kidTextStart + crntInfo.charsLen; IF wholeTree THEN { ropeSave:Rope.ROPE; ropeOffset:TiogaNode.Offset; IF Debug THEN { Indent[]; IO.PutF[report, "CHILD %g:\n", IO.card[i]]; }; [ropeSave, ropeOffset] _ RopeReader.Position[control]; -- save vitals so sub-CIR can use CIR[ br:current, brInfo:crntInfo, wholeTree:TRUE, indent:indent+4, textBuffer:textBuffer, control:control]; RopeReader.SetPosition[control, ropeSave, ropeOffset]; -- restore vitals } ELSE NodeProps.PutProp[current, $BranchInfo, crntInfo]; prev _ current; ENDLOOP; current.next _ br; -- point child at parent }; br.internalRepCreated _ TRUE; -- mark branch as cracked at last indent _ indent - 1; }; NewReport: PROCEDURE [] RETURNS [] = { [, report] _ IO.CreateViewerStreams["Tioga2 file description"]; }; IF Debug THEN NewReport[]; END. þGetT2FileImpl.mesa Written by Mik Lamming - March 14, 1983 12:08 pm Last edited by Lamming - June 9, 1983 1:31 pm The primary client interface to the tree parser If the whole tree is to be cracked then there is no need to plant information blocks on each branch. Instead, a copy of the root branch info is created and passed around the tree, the information being modified to suit the branch about to be cracked. Convert a branch to internal format Print n leading blanks - only called if Debug=TRUE Get the next token from the control stream Read a 24 bit number packed as 1..4 bytes using the given character reader. Each character provides 7 data bits and a boolean indicating whether or not it is the last in the sequence. Read a 24 bit number packed as 1..4 bytes using the given character reader. Each character provides 7 data bits and a boolean indicating whether or not it is the last in the sequence. Reads a rope and makes an ATOM Read a list of items from the control and data stream until non-item N.B. op: contains an uninterpreted token on termination Build a single rope out of the orphan's control and data and plug it into a new branch structure. Next crack the branch and finally step the readers over the branch data ready to eat the next item Read a list of items from the control and data stream until lastItem offset - the sub-type index parent - the parent node new - a node of the correct type to be filled in e.g. if a comment list item with format is expected, 'offset' will be cmt+fmt and 'new' will be a RefListItem The SCANNER examines the item token and sets flags which tell the READER what to expect on the input stream ** SCANNER ** READER op contains the token for the next item op now contains the next token op contains the token for the next item op contains the token for the next item op now contains the next token Reads is a property pair and assigns it to the given node Read a rope using given reader - reader is assumed to be positioned ready to read first character ** noOfRuns sets the appropriate bits in looks add looks to looks vector add looks to looks vector Reads a text node followed by any other items that follow until EOF Reads a rope from the given reader at current position. The rope is preceded by its length. The reader is advanced beyond the terminating CR. The CR is not returned as part of the rope. op should contain the token NoClassData which serves as a property list terminator *** CREATEINTERNALREP STARTS HERE *** *** PARSE BRANCH CONTENTS DATA *** CHEAP BRANCHES - If the control length is zero then this is an empty branch. It has no properties, format or children. If the text length is non-zero then it is a default text item (DTI). The text for a DTI equals the branch text. REGULAR BRANCHES - This section deals with the general case, i.e. branches not covered by the above. This means: all branches with one or more of the following characteristics: children; format; properties; non-DTI contents. Set the control reader to read backwards and get nchild, then startHK, then {childHK} If there are no children then startHK is not present because it can be computed trivially BRANCH WITH CHILDREN - Going to create the child chain backwards. 'nextNode' points to the successor of the node that is being created now (current). Start of control (lastCtrlBytePlus1) and start of text (lastTextBytePlus1) for each child branch is computed by subtracting successive child lengths from the parent's text and control limits. Explanation of above statement: If we are going to crack the whole tree then brInfo nodes are not attached to the branch. So, even if the external rep has not been modified, there is no information attached to the branch to allow the section of the rope corresponding to this branch to be identified. if we are going to crack the whole tree then there is no need to leave any branch properties around so can re-use the one we were called with compute text and data starts and save for next iteration Create a diagnostic window and describe all files read in Debug _ TRUE; Ê#˜Jšœ™J™0Jšœ-™-J˜šÏk ˜ Jšœœ ˜Jš œœ6œœœ˜XJšœœ˜3Jšœ œ˜,J˜Jšœœœ ˜Jšœ œ˜!Jšœ œ+œ1œ˜‡Jšœ œ€˜Jšœ œ(˜8Jšœœ ˜Jšœœ˜)Jšœœ˜#Jšœœ ˜!Jšœ œe˜tJšœ œƒ˜•J˜—šœ œ˜Jšœy˜€Jšœ ˜—J˜JšœœœÏc'˜@Jšœœœž˜/Jšœ œœž˜LJšœ œœž(˜RJšœ œœž0˜ZJ˜šÏnœ œ(œœ˜XJ™/Jšœœ%˜DJšœ˜Jšœ4˜4Jšœ˜šœ œ˜J™ûJšœœ˜Jšœ˜J˜—šœ˜Jšœ˜Jšœœ œœ˜*Jšœ˜Jšœ ˜ Jšœ œœ˜Jšœ˜—Jšœ#˜#Jšœ˜Jšœ˜J˜—š Ÿœ œ@œ œ œœ˜˜J™#JšÏf-Ðbf #˜XJ™šŸœ œ˜Jšœ.™2šœœœ ˜ Jšœ˜Jš˜—J˜J˜—šŸœœœœ˜/J™*Jšœ˜ Jšœ˜J˜—šŸœ œœœ˜)J™·Jšœ,˜,Jšœ˜Jšœ˜Jšœœ ˜0J˜šœž#˜9Jšœœœ˜—Jšœ œ ˜1J˜šœž$˜;Jšœœœ˜—Jšœœ ˜0J˜$J˜šœž$˜:Jšœœ˜—Jšœ œ ˜1J˜Jšœœž˜,J˜J˜—šŸœ œœœ˜)J™·Jšœ,˜,Jšœ˜Jšœ˜Jšœœ˜*J˜šœž#˜9Jšœœœ˜—Jšœ œ˜+J˜šœž$˜;Jšœœœ˜—Jšœœ˜*J˜$J˜šœž$˜:Jšœœ˜—Jšœ œ˜+J˜Jšœœž˜,J˜J˜—š Ÿœ œœœœ˜0J™Jšœ.˜4J˜J˜—šŸ œ œœ˜OJ™DJš 3˜3J™7Jšœ˜š˜šœ˜JšœD˜Fšœ@ž ˜OJšœX˜X—šœ@ž˜PJšœV˜V—šœ@ž ˜NJšœU˜U—šœž˜+J™ÅJšœœ˜!Jšœ?˜?Jšœ;˜;Jšœ œ˜8Jšœž˜3Jšœž˜)Jšœ;˜;Jšœ2˜2Jšœ«˜«Jšœœ˜Jšœ˜Jšœ9˜9Jšœ"˜"Jšœ"ž-˜Ošœ ˜šœ˜Jšœ˜Jšœ˜Jšœ ˜Jšœ˜Jšœ˜Jšœž˜(——š˜Jšœ2ž˜K—Jšœ ˜ JšœGž˜UJšœ;ž˜IJšœ˜—šœž3˜@Jšœœœ˜(šœœœž%˜8Jšœ˜Jšœœ˜J˜—Jšœ˜J˜——Jšœ œœ˜+šœ˜Jšœ˜J˜J˜—Jšœœž˜2Jšœ˜Jš˜—J˜J˜—šŸ œ œœœ˜>Jš ˜Jšœ!˜!š œœœœž&˜>Jšœ œ˜*šœœ˜Jšœ ˜ Jšœ.˜0Jšœ˜—Jšœ+˜1Jšœ˜—šœ˜šœ˜"Jšœ œœ˜—Jšœ˜JšœC˜CJšœ)˜)J˜—J˜J˜—šŸ œ œœ˜OJšœ<Ïb™DJš  ¡˜Jš o˜oJšœ˜š˜šœ˜JšœBž ˜Qšœ/ž˜AJšœW˜W—šœ@ž ˜NJšœU˜U—šœž,˜9Jšœœœ˜(šœœœž%˜8Jšœ˜Jšœœ˜J˜—Jšœ˜J˜——Jšœ œœ˜+šœ˜Jšœ˜J˜J˜—Jšœœž˜2Jšœ˜Jš˜—J˜J˜—šŸœ œ œœ˜[J™J™™2Jšœm™mJ™—J™kJ™Jšœ ž ˜0J˜Jšœ&œœ˜6Jšœœœ˜J™J™ šœœž˜