DIRECTORY Basics USING [bytesPerWord], BasicTime USING [FromNSTime], BcdDefs USING [BCD, FTIndex, FTSelf, Link, MTIndex, MTNull, MTRecord, SGIndex, SGNull, SGRecord, VersionStamp], ConvertUnsafe USING [SubString], DefaultRemoteNames USING [Get], FS USING [Error, OpenFileFromStream, Read, StreamOpen], ListerUtils USING [OpCodeArray, OpCodeArrayRep, OpCodeEntry], Literals USING [LitDescriptor, LTIndex, LTNull, LTRecord, MSTIndex, STIndex, STNull], IO USING [Close, EndOfStream, GetChar, GetInt, GetTokenRope, Put, PutChar, PutF, PutRope, SetIndex, SkipWhitespace, STREAM, UnsafeGetBlock], Rope USING [Concat, Fetch, Flatten, Length, ROPE], RuntimeError USING [UNCAUGHT], SymbolPack, Symbols USING [BitAddress, BodyRecord, BTIndex, ContextLevel, CSEIndex, CTXIndex, CTXNull, CTXRecord, ISEIndex, ISENull, lG, lL, lZ, MDIndex, Name, nullName, RootBti, SEIndex, SENull, SERecord, TransferMode, TypeClass, typeTYPE], SymbolTable USING [Base], Tree USING [Index, Link, Node, NodeName, NullIndex], VM USING [AddressForPageNumber, Allocate, Free, Interval, MakeReadOnly]; ListerUtilsImpl: PROGRAM IMPORTS BasicTime, DefaultRemoteNames, FS, IO, Rope, RuntimeError, SymbolPack, VM EXPORTS ListerUtils = BEGIN BCD: TYPE = BcdDefs.BCD; BitAddress: TYPE = Symbols.BitAddress; BTIndex: TYPE = Symbols.BTIndex; BTRecord: TYPE = Symbols.BodyRecord; bytesPerWord: NAT = Basics.bytesPerWord; CSEIndex: TYPE = Symbols.CSEIndex; typeTYPE: CSEIndex = Symbols.typeTYPE; ContextLevel: TYPE = Symbols.ContextLevel; lZ: ContextLevel = Symbols.lZ; lG: ContextLevel = Symbols.lG; lL: ContextLevel = Symbols.lL; CTXIndex: TYPE = Symbols.CTXIndex; CTXNull: CTXIndex = Symbols.CTXNull; CTXRecord: TYPE = Symbols.CTXRecord; FTIndex: TYPE = BcdDefs.FTIndex; FTSelf: FTIndex = BcdDefs.FTSelf; ISEIndex: TYPE = Symbols.ISEIndex; ISENull: ISEIndex = Symbols.ISENull; ISERecord: TYPE = SERecord.id; LTIndex: TYPE = Literals.LTIndex; LTNull: LTIndex = Literals.LTNull; LTRecord: TYPE = Literals.LTRecord; LitDescriptor: TYPE = Literals.LitDescriptor; MDIndex: TYPE = Symbols.MDIndex; MSTIndex: TYPE = Literals.MSTIndex; MSTNull: MSTIndex = LOOPHOLE[STNull]; MTIndex: TYPE = BcdDefs.MTIndex; MTNull: MTIndex = BcdDefs.MTNull; MTRecord: TYPE = BcdDefs.MTRecord; Name: TYPE = Symbols.Name; nullName: Name = Symbols.nullName; NodeName: TYPE = Tree.NodeName; RefBCD: TYPE = REF BCD; RefMTRecord: TYPE = REF MTRecord; RefSGRecord: TYPE = REF SGRecord; RootBti: BTIndex = Symbols.RootBti; ROPE: TYPE = Rope.ROPE; SEIndex: TYPE = Symbols.SEIndex; SENull: SEIndex = Symbols.SENull; SERecord: TYPE = Symbols.SERecord; SGIndex: TYPE = BcdDefs.SGIndex; SGNull: SGIndex = BcdDefs.SGNull; SGRecord: TYPE = BcdDefs.SGRecord; STIndex: TYPE = Literals.STIndex; STNull: STIndex = Literals.STNull; STREAM: TYPE = IO.STREAM; SubString: TYPE = ConvertUnsafe.SubString; SymbolTableBase: TYPE = SymbolTable.Base; TransferMode: TYPE = Symbols.TransferMode; TypeClass: TYPE = Symbols.TypeClass; VersionStamp: TYPE = BcdDefs.VersionStamp; opCodeArray: ListerUtils.OpCodeArray _ NIL; OpCodeFormatError: ERROR = CODE; GetOpCodeArray: PUBLIC PROC RETURNS [ListerUtils.OpCodeArray] = { IF opCodeArray = NIL THEN { stream: STREAM _ NIL; fileName: ROPE _ "OpCodes.txt"; opCodeArray _ NEW[ListerUtils.OpCodeArrayRep _ ALL[[NIL, 0, 0, 0]]]; stream _ FS.StreamOpen[fileName: fileName, accessOptions: $read, remoteCheck: FALSE ! FS.Error => IF error.group # bug THEN CONTINUE]; IF stream = NIL THEN { fileName _ Rope.Concat[DefaultRemoteNames.Get[].current, "Compiler>OpCodes.txt"]; stream _ FS.StreamOpen[fileName: fileName, accessOptions: $read, remoteCheck: FALSE ! FS.Error => IF error.group # bug THEN CONTINUE]; }; IF stream # NIL THEN { DO ENABLE IO.EndOfStream => EXIT; index: [0..256) _ 0; entry: ListerUtils.OpCodeEntry _ [NIL, 0, 0, 0]; [] _ IO.SkipWhitespace[stream, TRUE]; entry.name _ IO.GetTokenRope[stream].token; WHILE IO.GetChar[stream] # '( DO ENDLOOP; [] _ IO.SkipWhitespace[stream, TRUE]; index _ IO.GetInt[stream]; IF IO.GetChar[stream] # ') THEN ERROR OpCodeFormatError; entry.push _ IO.GetInt[stream]; IF IO.GetChar[stream] # ', THEN ERROR OpCodeFormatError; entry.pop _ IO.GetInt[stream]; IF IO.GetChar[stream] # ', THEN ERROR OpCodeFormatError; entry.length _ IO.GetInt[stream]; WHILE IO.GetChar[stream] # '; DO ENDLOOP; opCodeArray[index] _ entry; ENDLOOP; IO.Close[stream]; }; }; RETURN [opCodeArray]; }; ReadBcd: PUBLIC PROC [fileName: ROPE] RETURNS [bcd: RefBCD] = { stream: STREAM = FS.StreamOpen[fileName]; bcd _ NEW[BCD]; [] _ IO.UnsafeGetBlock[ stream, [base: LOOPHOLE[bcd], startIndex: 0, count: SIZE[BCD]*bytesPerWord]]; IO.Close[stream]; }; ReadMtr: PUBLIC PROC [inStream: STREAM, bcd: RefBCD, mti: MTIndex] RETURNS [mtr: RefMTRecord _ NIL] = TRUSTED { IF mti # MTNull THEN { mtr _ NEW[MTRecord]; IO.SetIndex[inStream, (bcd.mtOffset+LOOPHOLE[mti, CARDINAL])*bytesPerWord]; [] _ IO.UnsafeGetBlock[ inStream, [base: LOOPHOLE[mtr], startIndex: 0, count: SIZE[MTRecord]*bytesPerWord]]; }; }; ReadSgr: PUBLIC PROC [inStream: STREAM, bcd: RefBCD, sgi: SGIndex] RETURNS [sgr: RefSGRecord _ NIL] = TRUSTED { IF sgi # SGNull THEN { sgr _ NEW[SGRecord]; IO.SetIndex[inStream, (bcd.sgOffset+LOOPHOLE[sgi, CARDINAL])*bytesPerWord]; [] _ IO.UnsafeGetBlock[ inStream, [base: LOOPHOLE[sgr], startIndex: 0, count: SIZE[SGRecord]*bytesPerWord]]; }; }; WithSegment: PUBLIC PROC [inStream: STREAM, bcd: RefBCD, sgi: SGIndex, inner: PROC [LONG POINTER]] = { IF sgi # SGNull THEN { sgr: RefSGRecord = ReadSgr[inStream, bcd, sgi]; pages: CARDINAL = IF bcd.extended THEN sgr.pages+sgr.extraPages ELSE sgr.pages; IF pages = 0 OR sgr.file # FTSelf THEN inner[NIL] ELSE TRUSTED { interval: VM.Interval = VM.Allocate[count: pages]; ptr: LONG POINTER = VM.AddressForPageNumber[interval.page]; FS.Read[FS.OpenFileFromStream[inStream], sgr.base-1, interval.count, ptr]; VM.MakeReadOnly[interval]; -- don't want anyone messing with our tables inner[ptr ! UNWIND => VM.Free[interval]]; VM.Free[interval]; }; } ELSE inner[NIL]; }; WithPages: PUBLIC PROC [inStream: STREAM, bcd: RefBCD, start,pages: CARDINAL, inner: PROC [LONG POINTER]] = { IF pages # 0 THEN TRUSTED { interval: VM.Interval = VM.Allocate[count: pages]; ptr: LONG POINTER = VM.AddressForPageNumber[interval.page]; FS.Read[FS.OpenFileFromStream[inStream], start, interval.count, ptr]; VM.MakeReadOnly[interval]; -- don't want anyone messing with our tables inner[ptr ! UNWIND => VM.Free[interval]]; VM.Free[interval]; } ELSE inner[NIL]; }; PrintSE: PUBLIC PROC [sei: ISEIndex, nBlanks: CARDINAL, definitionsOnly: BOOL, stream: STREAM, stb: SymbolTableBase] = { sep: LONG POINTER TO ISERecord = @stb.seb[sei]; typeSei: SEIndex; Indent[stream, nBlanks]; PrintSei[sei, stream, stb]; IO.PutRope[stream, " ["]; PrintIndex[sei, stream]; IO.PutChar[stream, ']]; IF sep.public THEN IO.PutRope[stream, " [public]"]; IF sep.mark3 THEN { val: CARDINAL = LOOPHOLE[sep.idValue]; idInfo: CARDINAL = LOOPHOLE[sep.idInfo]; IO.PutRope[stream, ", type = "]; IF sep.idType = typeTYPE THEN { typeSei _ sep.idInfo; IO.PutRope[stream, "TYPE, equated to: "]; PrintType[typeSei, stream, stb]; IF stb.ctxb[sep.idCtx].level = lZ AND stb.TypeLink[sei] # SENull THEN IO.PutF[stream, ", tag code: %g", [cardinal[val]]]; } ELSE { typeSei _ sep.idType; PrintType[typeSei, stream, stb]; SELECT TRUE FROM sep.constant => IO.PutRope[stream, " [const]"]; sep.immutable => IO.PutRope[stream, " [init only]"]; ENDCASE; IF ~sep.mark4 THEN IO.PutF[stream, ", # refs: %g", [cardinal[idInfo]]] ELSE SELECT TRUE FROM sep.constant => IF ~ sep.extended THEN { IO.PutRope[stream, ", value: "]; SELECT stb.XferMode[typeSei] FROM proc, program, signal, error => PrintBcdLink[LOOPHOLE[val], stream]; ENDCASE => IF val < 1000 THEN IO.Put [stream, [cardinal[val]]] ELSE IO.PutF[stream, "%b", [cardinal[val]]]; }; (definitionsOnly AND stb.ctxb[sep.idCtx].level = lG) => IO.PutF[stream, ", index: %g", [cardinal[val]]]; ENDCASE => { addr: BitAddress = LOOPHOLE[val]; IO.PutF[ stream, ", address: %g [%g:%g]", [cardinal[addr.wd]], [cardinal[addr.bd]], [cardinal[idInfo]]]; IF sep.linkSpace THEN IO.PutChar[stream, '*]; }; }; PrintTypeInfo[typeSei, nBlanks+2, stream, stb]; IF sep.extended THEN PrintTree[stb.FindExtension[sei].tree, nBlanks+4, stream, stb]; }; }; PrintType: PUBLIC PROC [sei: SEIndex, stream: STREAM, stb: SymbolTableBase] = { tSei: SEIndex; IF sei = SENull THEN IO.PutChar[stream, '?] ELSE WITH t: stb.seb[sei] SELECT FROM cons => WITH t SELECT FROM transfer => WriteModeName[mode, stream]; ENDCASE => WriteTypeName[t.typeTag, stream]; id => FOR tSei _ sei, stb.TypeLink[tSei] UNTIL tSei = SENull DO WITH stb.seb[tSei] SELECT FROM id => { IF sei # tSei THEN IO.PutChar[stream, ' ]; PrintSei[LOOPHOLE[tSei, ISEIndex], stream, stb]; IF ~mark3 OR stb.ctxb[idCtx].level # lZ THEN EXIT; }; ENDCASE; ENDLOOP; ENDCASE; IO.PutRope[stream, " ["]; PrintIndex[sei, stream]; IO.PutChar[stream, ']]; }; PrintTypeInfo: PUBLIC PROC [sei: SEIndex, nBlanks: CARDINAL, stream: STREAM, stb: SymbolTableBase] = { IF sei # SENull THEN { sp: LONG POINTER TO SERecord = @stb.seb[sei]; WITH s: sp SELECT FROM cons => { Indent[stream, nBlanks]; IO.PutChar[stream, '[]; PrintIndex[sei, stream]; IO.PutRope[stream, "] "]; WITH s SELECT FROM transfer => WriteModeName[mode, stream]; ENDCASE => WriteTypeName[s.typeTag, stream]; WITH t: s SELECT FROM basic => NULL; enumerated => { IF t.machineDep THEN IO.PutRope[stream, " (md)"] ELSE IF t.unpainted THEN IO.PutRope[stream, " (~painted)"]; IO.PutRope[stream, ", value ctx: "]; PrintIndex[t.valueCtx, stream]; }; record => { IF t.machineDep THEN IO.PutRope[stream, " (md)"]; IF t.monitored THEN IO.PutRope[stream, " (monitored)"]; IF t.hints.variant THEN IO.PutRope[stream, " (variant)"]; OutCtx[", field", t.fieldCtx, stream]; WITH stb.ctxb[t.fieldCtx] SELECT FROM included => IF ~complete THEN IO.PutRope[stream, " [partial]"]; imported => IO.PutRope[stream, " [partial]"]; ENDCASE; WITH t SELECT FROM linked => { IO.PutRope[stream, ", link: "]; PrintType[linkType, stream, stb]}; ENDCASE; }; ref => { SELECT TRUE FROM t.counted => IO.PutRope[stream, " (counted)"]; t.var => IO.PutRope[stream, " (var)"]; ENDCASE; IF t.ordered THEN IO.PutRope[stream, " (ordered)"]; IF t.basing THEN IO.PutRope[stream, " (base)"]; IO.PutRope[stream, ", to: "]; PrintType[t.refType, stream, stb]; IF t.readOnly THEN IO.PutRope[stream, " (readonly)"]; PrintTypeInfo[t.refType, nBlanks+2, stream, stb]; }; array => { IF t.packed THEN IO.PutRope[stream, " (packed)"]; IO.PutRope[stream, ", index type: "]; PrintType[t.indexType, stream, stb]; IO.PutRope[stream, ", component type: "]; PrintType[t.componentType, stream, stb]; PrintTypeInfo[t.indexType, nBlanks+2, stream, stb]; PrintTypeInfo[t.componentType, nBlanks+2, stream, stb]; }; arraydesc => { IO.PutRope[stream, ", described type: "]; PrintType[t.describedType, stream, stb]; IF t.readOnly THEN IO.PutRope[stream, " (readonly)"]; PrintTypeInfo[t.describedType, nBlanks+2, stream, stb]; }; transfer => { IF t.safe THEN IO.PutRope[stream, " (safe)"]; OutArgType[", input", t.typeIn, stream, stb]; OutArgType[", output", t.typeOut, stream, stb]; }; definition => { IO.PutRope[stream, ", ctx: "]; PrintIndex[t.defCtx, stream]; IO.PutF[stream, ", ngfi: %g", [cardinal[t.nGfi]]]; }; union => { IF t.overlaid THEN IO.PutRope[stream, " (overlaid)"]; IF t.controlled THEN { IO.PutRope[stream, ", tag: "]; PrintSei[t.tagSei, stream, stb]}; IO.PutRope[stream, ", tag type: "]; PrintType[stb.seb[t.tagSei].idType, stream, stb]; IO.PutRope[stream, ", case ctx: "]; PrintIndex[t.caseCtx, stream]; IF t.controlled THEN PrintSE[t.tagSei, nBlanks+2, FALSE, stream, stb]; }; sequence => { IF t.packed THEN IO.PutRope[stream, " (packed)"]; IF t.controlled THEN { IO.PutRope[stream, ", tag: "]; PrintSei[t.tagSei, stream, stb]} ELSE { IO.PutRope[stream, ", index type: "]; PrintType[stb.seb[t.tagSei].idType, stream, stb]}; IO.PutRope[stream, ", component type: "]; PrintType[t.componentType, stream, stb]; IF t.controlled THEN PrintSE[t.tagSei, nBlanks+2, FALSE, stream, stb] ELSE PrintTypeInfo[stb.seb[t.tagSei].idType, nBlanks+2, stream, stb]; PrintTypeInfo[t.componentType, nBlanks+2, stream, stb]; }; relative => { IO.PutRope[stream, ", base type: "]; PrintType[t.baseType, stream, stb]; IO.PutRope[stream, ", offset type: "]; PrintType[t.offsetType, stream, stb]; PrintTypeInfo[t.baseType, nBlanks+2, stream, stb]; PrintTypeInfo[t.offsetType, nBlanks+2, stream, stb]; }; opaque => { IO.PutRope[stream, ", id: "]; PrintSei[t.id, stream, stb]; IF t.lengthKnown THEN IO.PutF[stream, ", size: %g", [cardinal[t.length]]]; }; zone => { IF t.counted THEN IO.PutRope[stream, " (counted)"]; IF t.mds THEN IO.PutRope[stream, " (mds)"]; }; subrange => { IO.PutRope[stream, " of: "]; PrintType[t.rangeType, stream, stb]; IF t.filled THEN { IO.PutF[stream, " origin: %g", [integer[t.origin]]]; IO.PutF[stream, ", range: %g", [cardinal[t.range]]]}; PrintTypeInfo[t.rangeType, nBlanks+2, stream, stb]; }; long, real => { IO.PutRope[stream, " of: "]; PrintType[t.rangeType, stream, stb]; PrintTypeInfo[t.rangeType, nBlanks+2, stream, stb]; }; ENDCASE; }; ENDCASE }; }; PrintTree: PUBLIC PROC [tree: Tree.Link, nBlanks: NAT, stream: STREAM, stb: SymbolTableBase] = { PrintSubTree: PROC [tree: Tree.Link] = { Indent[stream, nBlanks]; WITH s: tree SELECT FROM hash => PrintName[s.index, stream, stb]; symbol => { PrintSei[s.index, stream, stb]; IO.PutChar[stream, '[]; PrintIndex[s.index, stream]; IO.PutChar[stream, ']]; }; literal => PrintLiteral[s, stream, stb]; subtree => { node: Tree.Index = s.index; SELECT node FROM Tree.NullIndex => IO.PutRope[stream, ""]; Tree.Index.LAST => IO.PutRope[stream, ""]; ENDCASE => { tp: LONG POINTER TO Tree.Node _ @stb.tb[node]; IO.PutRope[stream, NodeNameTable[tp.name]]; IO.PutChar[stream, '[]; PrintIndex[node, stream]; IO.PutRope[stream, "] "]; IF tp.info # 0 THEN { IO.PutRope[stream, " info="]; PrintIndex[tp.info, stream]; }; IF tp.attr1 OR tp.attr2 OR tp.attr3 THEN { IF tp.info = 0 THEN IO.PutChar[stream, ' ]; IO.PutChar[stream, '(]; IF tp.attr1 THEN IO.PutChar[stream, '1]; IF tp.attr2 THEN IO.PutChar[stream, '2]; IF tp.attr3 THEN IO.PutChar[stream, '3]; IO.PutChar[stream, ')]; }; nBlanks _ nBlanks + 2; IF tp.name # thread THEN { EndIndex: Tree.Index = Tree.Index.LAST; EndMark: Tree.Link = [subtree[index: EndIndex]]; n: NAT = tp.nSons; IF tp.name = list AND n = 0 THEN FOR i: NAT IN [1..NAT.LAST] DO son: Tree.Link = tp.son[i]; IF son = EndMark THEN EXIT; PrintSubTree[tp.son[i]]; ENDLOOP ELSE FOR i: CARDINAL IN [1 .. n] DO PrintSubTree[tp.son[i]]; ENDLOOP; } ELSE { IO.PutRope[stream, " link="]; PrintTreeLink[tp.son[2], stream]; IO.PutRope[stream, " to "]; PrintTreeLink[tp.son[1], stream]; }; nBlanks _ nBlanks - 2}; }; ENDCASE => ERROR; }; PrintSubTree[tree]; }; PrintLiteral: PUBLIC PROC [t: Tree.Link.literal, stream: STREAM, stb: SymbolTableBase] = { WITH t.index SELECT FROM string => { msti: MSTIndex = MasterString[stb, sti]; s: LONG STRING = @stb.ltb[msti].string; IO.PutChar[stream, '"]; FOR i: CARDINAL IN [0..s.length) DO IO.PutChar[stream, s[i]] ENDLOOP; IO.PutChar[stream, '"]; IF sti # msti THEN IO.PutChar[stream, 'L]}; word => { desc: Literals.LitDescriptor = DescriptorValue[stb, lti]; v: WORD; IF desc.length # 1 THEN IO.PutChar[stream, '[]; FOR i: CARDINAL IN [0 .. desc.length) DO IF (v _ stb.ltb[desc.offset][i]) < 1000 THEN IO.Put[stream, [cardinal[v]]] ELSE IO.PutF[stream, "%b", [cardinal[v]]]; -- octal IF i+1 # desc.length THEN IO.PutChar[stream, ',]; ENDLOOP; IF desc.length # 1 THEN IO.PutChar[stream, ']]}; ENDCASE; }; PrintBcdLink: PUBLIC PROC [link: BcdDefs.Link, stream: STREAM] = { SELECT TRUE FROM link.proc => IO.PutF[stream, "proc[%g,%g]", [cardinal[link.gfi]], [cardinal[link.ep]]]; link.type => { IO.PutRope[stream, "type["]; PrintIndex[link.typeID, stream]}; ENDCASE => IO.PutF[stream, "var[%g,%g]", [cardinal[link.gfi]], [cardinal[link.var]]]; }; PrintTreeLink: PUBLIC PROC [link: Tree.Link, stream: STREAM] = { WITH t: link SELECT FROM subtree => PrintIndex[t.index, stream]; hash => {IO.PutRope[stream, "hash#"]; PrintIndex[t.index, stream]}; symbol => {IO.PutRope[stream, "symbol#"]; PrintIndex[t.index, stream]}; literal => {IO.PutRope[stream, "literal#"]; PrintIndex[t.index, stream]}; ENDCASE => ERROR; }; PrintSei: PUBLIC PROC [sei: ISEIndex, stream: STREAM, stb: SymbolTableBase] = { PrintName[stb.NameForSe[sei], stream, stb]; }; PrintName: PUBLIC PROC [name: Name, stream: STREAM, stb: SymbolTableBase] = { IF name = nullName THEN IO.PutRope[stream, "(anon)"] ELSE { ss: SubString = stb.SubStringForName[name]; FOR i: NAT IN [ss.offset..ss.offset+ss.length) DO IO.PutChar[stream, ss.base[i]]; ENDLOOP; }; }; WriteNodeName: PUBLIC PROC [n: NodeName, stream: STREAM] = { IO.PutRope[stream, NodeNameTable[n]]; }; WriteTypeName: PUBLIC PROC [n: TypeClass, stream: STREAM] = { IO.PutRope[stream, TypeNameTable[n]]; }; WriteModeName: PUBLIC PROC [n: TransferMode, stream: STREAM] = { IO.PutRope[stream, ModeNameTable[n]]; }; OutCtx: PUBLIC PROC [message: Rope.ROPE, ctx: CTXIndex, stream: STREAM] = { IO.PutRope[stream, message]; IO.PutRope[stream, " ctx: "]; IF ctx = CTXNull THEN IO.PutRope[stream, "NIL"] ELSE PrintIndex[ctx, stream]; }; OutArgType: PUBLIC PROC [message: ROPE, sei: CSEIndex, stream: STREAM, stb: SymbolTableBase] = { IF sei = SENull THEN {IO.PutRope[stream, message]; IO.PutRope[stream, ": NIL"]} ELSE WITH t: stb.seb[sei] SELECT FROM record => OutCtx[message, t.fieldCtx, stream]; any => {IO.PutRope[stream, message]; IO.PutRope[stream, ": ANY"]}; ENDCASE }; PrintVersion: PUBLIC PROC [stamp: VersionStamp, stream: STREAM, useTime: BOOL _ FALSE] = { str: PACKED ARRAY [0..12) OF [0..16) = LOOPHOLE[stamp]; FOR i: NAT IN [0..12) DO d: [0..16) = str[i]; IF d < 10 THEN IO.PutChar[stream, '0+d] ELSE IO.PutChar[stream, 'a-10+d]; ENDLOOP; IF useTime THEN { IF stamp.net # 0 OR stamp.host # 0 THEN IO.PutF[stream, " (%g, %g, ", [cardinal[stamp.net]], [cardinal[stamp.host]]] ELSE IO.PutRope[stream, " ("]; {ENABLE RuntimeError.UNCAUGHT => GO TO dreck; IO.PutF[ stream, "%g)", [time[BasicTime.FromNSTime[stamp.time]]] ]; EXITS dreck => IO.PutRope[stream, "??)"]; }; }; }; PrintStringFromTable: PUBLIC PROC [index: CARDINAL, stream: STREAM, stb: SymbolTableBase] = { str: LONG STRING = stb.ssb; len: CARDINAL = str[index]-0C; FOR i: NAT IN [1..MIN[64, len]] DO IO.PutChar[stream, str[i]]; ENDLOOP; }; PrintString: PUBLIC PROC [str: LONG STRING, stream: STREAM] = { IF str # NIL THEN FOR i: NAT IN [0..str.length) DO IO.PutChar[stream, str[i]]; ENDLOOP; }; PrintSubString: PUBLIC PROC [ss: SubString, stream: STREAM] = { FOR i: NAT IN [ss.offset..ss.offset+ss.length) DO IO.PutChar[stream, ss.base[i]]; ENDLOOP; }; PrintIndex: PUBLIC PROC [index: UNSPECIFIED, stream: STREAM] = { IO.Put[stream, [integer[LOOPHOLE[index, CARDINAL]]]]; }; Indent: PUBLIC PROC [stream: STREAM, nBlanks: NAT] = { IO.PutChar[stream, '\n]; THROUGH [0..nBlanks) DO IO.PutChar[stream, ' ]; ENDLOOP; }; DescriptorValue: PUBLIC PROC [stb: SymbolTableBase, lti: LTIndex] RETURNS [LitDescriptor] = { WITH entry: stb.ltb[lti] SELECT FROM short => { deltaShort: CARDINAL = LOOPHOLE[@(NIL[POINTER TO LTRecord.short]).value]; RETURN [[offset: LOOPHOLE[lti + deltaShort], length: 1]]; }; long => { deltaLong: CARDINAL = LOOPHOLE[@(NIL[POINTER TO LTRecord.long]).value]; RETURN [[offset: LOOPHOLE[lti + deltaLong], length: entry.length]]; }; ENDCASE => ERROR; }; MasterString: PUBLIC PROC [stb: SymbolTableBase, sti: STIndex] RETURNS [MSTIndex _ MSTNull] = { WITH s: stb.ltb[sti] SELECT FROM master => RETURN[LOOPHOLE[sti]]; copy => RETURN[s.link]; heap => RETURN[s.link]; ENDCASE; }; ShortName: PUBLIC PROC [rope: ROPE] RETURNS [ROPE] = { pos: INT _ Rope.Length[rope]; bang: INT _ pos; WHILE pos > 0 DO under: INT = pos - 1; SELECT Rope.Fetch[rope, under] FROM '! => bang _ under; '>, '/, '<, '] => RETURN [Rope.Flatten[rope, pos, bang-pos]]; ENDCASE; pos _ under; ENDLOOP; RETURN [rope]; }; NodeNameArray: TYPE = ARRAY NodeName OF ROPE; NodeNameTable: PUBLIC REF NodeNameArray = NEW[NodeNameArray _[ "list", "item", "decl", "typedecl", "basicTC", "enumeratedTC", "recordTC", "monitoredTC", "variantTC", "refTC", "pointerTC", "listTC", "arrayTC", "arraydescTC", "sequenceTC", "procTC", "processTC", "portTC", "signalTC", "errorTC", "programTC", "anyTC", "definitionTC", "unionTC", "relativeTC", "subrangeTC", "longTC", "opaqueTC", "zoneTC", "linkTC", "varTC", "implicitTC", "frameTC", "discrimTC", "paintTC", "spareTC", "unit", "diritem", "module", "body", "inline", "lambda", "block", "assign", "extract", "if", "case", "casetest", "caseswitch", "bind", "do", "forseq", "upthru", "downthru", "return", "result", "goto", "exit", "loop", "free", "resume", "reject", "continue", "retry", "catchmark", "restart", "stop", "lock", "wait", "notify", "broadcast", "unlock", "null", "label", "open", "enable", "catch", "dst", "lste", "lstf", "syscall", "checked", "lst", "spareS3", "subst", "call", "portcall", "signal", "error", "syserror", "xerror", "start", "join", "apply", "callx", "portcallx", "signalx", "errorx", "syserrorx", "startx", "fork", "joinx", "index", "dindex", "seqindex", "reloc", "construct", "union", "rowcons", "sequence", "listcons", "substx", "ifx", "casex", "bindx", "assignx", "extractx", "or", "and", "relE", "relN", "relL", "relGE", "relG", "relLE", "in", "notin", "plus", "minus", "times", "div", "mod", "dot", "cdot", "dollar", "create", "not", "uminus", "addr", "uparrow", "min", "max", "lengthen", "abs", "all", "size", "first", "last", "pred", "succ", "arraydesc", "length", "base", "loophole", "nil", "new", "void", "clit", "llit", "cast", "check", "float", "pad", "chop", "safen", "syscallx", "narrow", "istype", "openx", "mwconst", "cons", "atom", "typecode", "stringinit", "textlit", "signalinit", "procinit", "intOO", "intOC", "intCO", "intCC", "thread", "none", "exlist", "initlist", "ditem", "shorten", "self", "gcrt", "proccheck", "ord", "val", "entry", "internal", "mergecons"]]; TypeNameArray: TYPE = ARRAY TypeClass OF ROPE; TypeNameTable: REF TypeNameArray = NEW[TypeNameArray _ [ "mode", "basic", "enumerated", "record", "ref", "array", "arraydesc", "transfer", "definition", "union", "sequence", "relative", "subrange", "long", "real", "opaque", "zone", "any", "nil"]]; ModeNameArray: TYPE = ARRAY TransferMode OF ROPE; ModeNameTable: PUBLIC REF ModeNameArray = NEW[ModeNameArray _ [ "proc", "port", "signal", "error", "process", "program", "none"]]; END. "ListerUtilsImpl.mesa Copyright c 1984, 1985 by Xerox Corporation. All rights reserved. Russ Atkinson (RRA) August 20, 1985 6:05:11 pm PDT Sweet October 8, 1985 9:38:39 am PDT T Y P E S & C O N S T A N T S OpCode types & procedures Parse the opcodes file. Each entry has the form name octal(decimal)push,pop,length,aligned; where the octal number has no trailing 'B. There can be comments and blank lines in the file, and we allow multiple entries per line. Most, although not all, punctuation problems will cause ERROR OpCodeFormatError. Bcd acquisition procedures Reads the given BCD. Allows FS.Error to fall through to the caller. Reads the given module record. Get the module. Reads the given module record. Get the module. Reads the given segment, invoking the inner procedure with a pointer to it. Get the segment record. Reads the given segment, invoking the inner procedure with a pointer to it. Get the pages. Utility procedures Some of these routines were cloned from various places to allow stream: STREAM and stb: SymbolTableBase as arguments, so we don't have to use global variables. Very long lists have end markers, not explcit lengths. For all other nodes, believe the given length. This next statement is separate to deal with potential errors in time conversion. T A B L E S ÊÖ˜codešœ™Kšœ Ïmœ7™BK™2K™$—K˜šÏk ˜ Kšœžœ˜Kšœ žœ˜Kšœžœžœ]˜oKšœžœ ˜ Kšœžœ˜Kšžœžœ/˜7Kšœ žœ,˜=Kšœ žœG˜UKšžœžœlžœ˜ŒKšœžœ"žœ˜2Kšœ žœžœ˜Kšœ ˜ KšœžœØ˜åKšœ žœ˜Kšœžœ*˜4Kšžœžœ@˜H—K˜šœž˜Kšžœ žœžœ"ž˜QKšžœ žœž˜—K˜šœ™K˜Kšžœžœ žœ˜Kšœ žœ˜&Kšœ žœ˜ Kšœ žœ˜$Kšœžœ˜(šœ žœ˜"Kšœ&˜&—šœžœ˜*Kšœ˜Kšœ˜Kšœ˜—šœ žœ˜"Kšœ$˜$—Kšœ žœ˜$šœ žœ˜ Kšœ!˜!—šœ žœ˜"Kšœ$˜$—Kšœ žœ˜šœ žœ˜!Kšœ"˜"—Kšœ žœ˜#Kšœžœ˜-Kšœ žœ˜ šœ žœ˜#Kšœžœ ˜%—šœ žœ˜ Kšœ!˜!—Kšœ žœ˜"šœžœ˜Kšœ"˜"—Kšœ žœ˜Kšœžœžœžœ˜Kšœ žœžœ ˜!Kšœ žœžœ ˜!Kšœ#˜#Kšžœžœžœ˜šœ žœ˜ Kšœ!˜!—Kšœ žœ˜"šœ žœ˜ Kšœ!˜!—Kšœ žœ˜"šœ žœ˜!Kšœ"˜"—Kšžœžœžœžœ˜Kšœ žœ˜*Kšœžœ˜)Kšœžœ˜*Kšœ žœ˜$Kšœžœ˜*K˜—šœ™K™Kšœ'žœ˜+Kšœžœžœ˜ K˜šÏnœž œžœ˜Ašžœžœžœ˜Kšœžœžœ˜Kšœ žœ˜Kšœžœžœžœ ˜Dšœ žœCž˜SKš œžœ žœžœžœ˜2—šžœ žœžœ˜KšœQ˜Qšœ žœCž˜SKš œžœ žœžœžœ˜2—K˜—šžœ žœžœ˜šœ0™0Kš œ Ïbœ œ œ œ œ ™+—KšœØ™Øšž˜Kšžœžœžœ˜K˜Kšœ"žœ ˜0Kšœžœžœ˜%Kšœ žœ˜+Kšžœžœžœžœ˜)Kšœžœžœ˜%Kšœžœ˜Kšžœžœžœžœ˜8Kšœ žœ˜Kšžœžœžœžœ˜8Kšœ žœ˜Kšžœžœžœžœ˜8Kšœžœ˜!Kšžœžœžœžœ˜)Kšœ˜Kšžœ˜—Kšžœ˜K˜—Kšœ˜—Kšžœ˜K˜—K˜—šœ™K˜šŸœž œ žœžœ˜?KšœD™DKšœžœžœ˜)Kšœžœžœ˜šœžœ˜Kšœ˜Kšœžœžœžœ˜E—Kšžœ˜Kšœ˜K™—šŸœžœžœ žœžœžœžœ˜oKšœ™šžœžœ˜Kšœ™Kšœžœ ˜Kšžœ"žœžœ˜Kšœžœ˜Kšœ ˜ Kšœžœžœ˜J—K˜—Kšœ˜K™—šŸœžœžœ žœžœžœžœ˜oKšœ™šžœžœ˜Kšœ™Kšœžœ ˜Kšžœ"žœžœ˜Kšœžœ˜Kšœ ˜ Kšœžœžœ˜J—K˜—Kšœ˜K™—šŸ œžœžœ žœ$žœžœžœ˜fKšœK™Kšžœ ˜šžœ˜Kšœ™Kšœ/˜/Kš œžœžœžœžœ ˜Ošžœ žœ˜!Kšžœžœ˜šžœžœ˜Kšœ žœ žœ˜2Kšœžœžœžœ%˜;Kšžœžœ@˜JKšžœÏc,˜HKšœ žœžœ˜)Kšžœ˜K˜——K˜—šž˜Kšœžœ˜ ——Kšœ˜K™—šŸ œžœžœ žœžœ žœžœžœ˜mKšœK™Kšžœ ˜ šžœžœ˜Kšœ™Kšœ žœ žœ˜2Kšœžœžœžœ%˜;Kšžœžœ;˜EKšžœ¡,˜HKšœ žœžœ˜)Kšžœ˜K˜—šž˜Kšœžœ˜ ——Kšœ˜K™——šœ™K™KšœHžœQ™ŸK˜š Ÿœž œžœžœ žœ˜xKšœžœžœžœ˜/K˜K˜K˜Kšžœ˜Kšœ˜Kšžœ˜Kšžœ žœžœ˜3šžœ žœ˜Kšœžœžœ˜&Kšœžœžœ ˜(Kšžœ˜ šžœ˜šžœ˜K˜Kšžœ'˜)K˜ šžœ žœ˜@Kšžœžœ1˜8—Kšœ˜—šžœ˜K˜K˜ šžœžœž˜Kšœžœ˜/Kšœžœ!˜4Kšžœ˜—šžœ ˜ Kšžœžœ1˜8šž˜šžœžœž˜˜šžœžœ˜Kšžœ˜ šžœž˜!šœ˜Kšœ žœ˜$—šžœ˜ šžœ ˜ Kšžœžœ˜%Kšžœžœ%˜,———Kšœ˜——šœžœ#˜7Kšžœ.˜0—šžœ˜ Kšœžœ˜!šžœ˜Kšœ ˜ Kšœ>˜>—Kšžœžœžœ˜-Kšœ˜————Kšœ˜——Kšœ/˜/Kšžœžœ@˜TKšœ˜—Kšœ˜K˜—šŸ œž œžœ˜OK˜šžœ ˜Kšžœžœ˜šž˜šžœžœž˜ ˜šžœžœž˜K˜(Kšžœ%˜,——˜šžœ žœž˜9šžœžœž˜˜Kšžœ žœžœ˜*Kšœ žœ˜0Kšžœžœžœžœ˜2Kšœ˜—Kšžœ˜—Kšžœ˜——Kšžœ˜———Kšžœ˜Kšœ˜Kšžœ˜Kšœ˜K˜—šŸ œž œžœ žœ˜fšžœžœ˜Kšœžœžœžœ˜-šžœžœž˜˜ K˜Kšžœ˜Kšœ˜Kšžœ˜šžœžœž˜Kšœ(˜(Kšžœ%˜,—šžœžœž˜Kšœ žœ˜˜Kšžœžœžœ˜0Kšžœžœ žœžœ ˜;Kšžœ"˜$Kšœ˜Kšœ˜—˜ Kšžœžœžœ˜1Kšžœ žœžœ!˜7Kšžœžœžœ˜9K˜&šžœžœž˜%Kšœ žœ žœžœ˜?Kšœ žœ˜-Kšžœ˜—šžœžœž˜šœ ˜ Kšžœ˜Kšœ"˜"—Kšžœ˜—Kšœ˜—˜šžœžœž˜Kšœ žœ˜.Kšœ žœ˜&Kšžœ˜—Kšžœ žœžœ˜3Kšžœ žœžœ˜/Kšžœ˜Kšœ"˜"Kšžœ žœžœ ˜5Kšœ1˜1K˜—˜ Kšžœ žœžœ˜1Kšžœ#˜%Kšœ$˜$Kšžœ'˜)Kšœ(˜(Kšœ3˜3Kšœ7˜7Kšœ˜—˜Kšžœ'˜)Kšœ(˜(Kšžœ žœžœ ˜5Kšœ7˜7Kšœ˜—˜ Kšžœžœžœ˜-Kšœ-˜-Kšœ/˜/K˜—˜Kšžœ˜Kšœ˜Kšžœ0˜2Kšœ˜—˜ Kšžœ žœžœ ˜5šžœžœ˜Kšžœ˜Kšœ!˜!—Kšžœ!˜#Kšœ1˜1Kšžœ!˜#Kšœ˜Kšžœžœžœ˜FKšœ˜—˜ Kšžœ žœžœ˜1šžœ ˜šžœ˜Kšžœ˜Kšœ ˜ —šžœ˜Kšžœ#˜%Kšœ2˜2——Kšžœ'˜)Kšœ(˜(šžœ ˜Kšžœžœ˜5KšžœA˜E—Kšœ7˜7Kšœ˜—˜ Kšžœ"˜$Kšœ#˜#Kšžœ$˜&Kšœ%˜%Kšœ2˜2Kšœ4˜4Kšœ˜—˜ Kšžœ˜Kšœ˜šžœž˜Kšžœ2˜4—Kšœ˜—˜ Kšžœ žœžœ˜3Kšžœžœžœ˜+Kšœ˜—˜ Kšžœ˜Kšœ$˜$šžœ žœ˜Kšžœ2˜4Kšžœ3˜5—Kšœ3˜3Kšœ˜—˜Kšžœ˜Kšœ$˜$Kšœ3˜3Kšœ˜—Kšžœ˜—Kšœ˜—Kšž˜—Kšœ˜—K˜K˜—šŸ œž œžœ žœ˜`šŸ œžœ˜(Kšœ˜šžœ žœž˜šœ˜Kšœ ˜ —˜ Kšœ˜Kšžœ˜Kšœ˜Kšžœ˜Kšœ˜—˜ Kšœ˜—˜ K˜šžœž˜Kšœžœ˜0Kšœ žœžœ˜0šžœ˜ Kšœžœžœžœ˜.Kšžœ)˜+Kšžœ˜Kšœ˜Kšžœ˜šžœ žœ˜Kšžœ˜Kšœ˜Kšœ˜—šžœ žœ žœ žœ˜*Kšžœ žœžœ˜+Kšžœ˜Kšžœ žœžœ˜(Kšžœ žœžœ˜(Kšžœ žœžœ˜(Kšžœ˜Kšœ˜—K˜šžœ˜šžœ˜Kšœ"žœ˜'Kšœ0˜0Kšœžœ ˜šžœžœ˜šž˜Kšœ6™6š žœžœžœžœžœž˜Kšœ˜Kšžœžœžœ˜Kšœ˜Kšž˜——šž˜Kšœ.™.šžœžœžœ ž˜Kšœ˜Kšžœ˜———K˜—šžœ˜Kšœ˜Kšœ!˜!Kšœ˜Kšœ!˜!K˜——K˜——K˜—Kšžœžœ˜—K˜—Kšœ˜K˜K˜—šŸ œž œ žœ˜Zšžœ žœž˜˜ Kšœ(˜(Kšœžœžœ˜'Kšžœ˜Kš žœžœžœžœžœžœ˜EKšžœ˜Kšžœ žœžœ˜+—˜ K˜9Kšœžœ˜Kšžœžœžœ˜/šžœžœžœž˜(šžœ%˜'Kšžœžœ˜"Kšžœžœ$¡˜3—Kšžœžœžœ˜1Kšžœ˜—Kšžœžœžœ˜0—Kšžœ˜—šœ˜K˜——šŸ œž œžœ˜Bšžœžœž˜šœ ˜ KšžœH˜J—šœ˜Kšžœ<˜>—šžœ˜ KšžœH˜J——K˜K˜—šŸ œž œžœ˜@šžœ žœž˜Kšœ'˜'Kšœ žœ8˜CKšœ žœ:˜GKšœ žœ;˜IKšžœžœ˜—K˜K˜—šŸœž œžœ˜OKšœ+˜+Kšœ˜K˜—šŸ œž œžœ˜Mšžœ˜Kšžœžœ˜!šžœ˜Kšœ+˜+šžœžœžœ"ž˜1Kšžœ˜Kšžœ˜—Kšœ˜——K˜K˜—šŸ œž œžœ˜Kšžœ˜—K˜ Kšžœ˜—Kšžœ˜K˜K˜——šœ ™ K˜Kš œžœžœ žœžœ˜-KšœžœžœžœŒ˜¹Kš œžœžœ žœžœ˜.KšœžœžœÒ˜øKš œžœžœžœžœ˜1šœžœžœžœU˜‚K˜——Kšžœ˜K˜—…—Wœx”