DIRECTORY Basics, BasicTime, CardTab, ConvertUnsafe, CountedVM, IO, ListerSysOps, Literals USING [Base, LitDescriptor, LTIndex, LTNull, LTRecord, MSTIndex, STIndex, STNull, STRecord], MobDefs USING [Base, FTIndex, FTSelf, Link, Mob, MobBase, MTIndex, MTNull, MTRecord, SGIndex, SGNull, SGRecord, VersionStamp], MobListerUtils USING [], MobMapper USING [AlterMob, BadMobContents], Rope, SymbolOps USING [DecodeCard, DecodeType, NameForSe, SubStringForName, TypeLink, XferMode], Symbols USING [Base, BitAddress, BodyRecord, BTIndex, ContextLevel, CSEIndex, CTXIndex, CTXNull, CTXRecord, ISEIndex, ISENull, lG, lL, lZ, MDIndex, Name, nullName, RootBti, SEIndex, SENull, SERecord, TransferMode, TypeClass, typeTYPE, UNSPEC], SymTab, SymbolTable USING [SymbolTableBaseRep], SymbolTablePrivate USING [SymbolTableBase, SymbolTableBaseRep], Table USING [IndexRep], Tree USING [Base, Index, Link, LinkTag, Node, NodeName, nullIndex], TreeOps USING [GetTag, ToCard], VM; MobListerUtilsImpl: PROGRAM IMPORTS Basics, CardTab, ConvertUnsafe, CountedVM, IO, ListerSysOps, MobMapper, Rope, SymTab, SymbolOps, TreeOps, VM EXPORTS MobListerUtils, SymbolTable = BEGIN Mob: TYPE = MobDefs.Mob; BitAddress: TYPE = Symbols.BitAddress; BTIndex: TYPE = Symbols.BTIndex; BTRecord: TYPE = Symbols.BodyRecord; 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 = MobDefs.FTIndex; FTSelf: FTIndex = MobDefs.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 = MobDefs.MTIndex; MTNull: MTIndex = MobDefs.MTNull; MTRecord: TYPE = MobDefs.MTRecord; Name: TYPE = Symbols.Name; nullName: Name = Symbols.nullName; NodeName: TYPE = Tree.NodeName; RefMob: TYPE = REF Mob; 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 = MobDefs.SGIndex; SGNull: SGIndex = MobDefs.SGNull; SGRecord: TYPE = MobDefs.SGRecord; STIndex: TYPE = Literals.STIndex; STNull: STIndex = Literals.STNull; STREAM: TYPE = IO.STREAM; SubString: TYPE = ConvertUnsafe.SubString; SymbolTableBase: TYPE = REF SymbolTableBaseRep; SymbolTableBaseRep: PUBLIC TYPE = SymbolTablePrivate.SymbolTableBaseRep; TransferMode: TYPE = Symbols.TransferMode; TypeClass: TYPE = Symbols.TypeClass; VersionStamp: TYPE = MobDefs.VersionStamp; 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]; stream.PutRope[" ["]; PrintLongIndex[sei, stream]; stream.PutChar[']]; IF sep.public THEN stream.PutRope[" [public]"]; IF sep.mark3 THEN { val: CARD = SymbolOps.DecodeCard[sep.idValue]; idInfo: CARD = SymbolOps.DecodeCard[sep.idInfo]; stream.PutRope[", type = "]; IF sep.idType = typeTYPE THEN { typeSei ¬ SymbolOps.DecodeType[sep.idInfo]; stream.PutRope["TYPE, equated to: "]; PrintType[typeSei, stream, stb]; IF stb.ctxb[sep.idCtx].level = lZ AND SymbolOps.TypeLink[stb, sei] # SENull THEN stream.PutF1[", tag code: %g", [cardinal[val]]]; } ELSE { typeSei ¬ sep.idType; PrintType[typeSei, stream, stb]; SELECT TRUE FROM sep.constant => stream.PutRope[" [const]"]; sep.immutable => stream.PutRope[" [init only]"]; ENDCASE; SELECT TRUE FROM ~sep.mark4 => stream.PutF1[", # refs: %g", [cardinal[idInfo]]]; sep.constant => IF ~ sep.extended THEN { stream.PutRope[", value: "]; SELECT SymbolOps.XferMode[stb, typeSei] FROM proc, program, signal, error => PrintMobLink[LOOPHOLE[val], stream]; ENDCASE => IF val < 1000 THEN stream.Put1[[cardinal[val]]] ELSE stream.PutF1["%b", [cardinal[val]]]; }; (definitionsOnly AND stb.ctxb[sep.idCtx].level = lG) => stream.PutF1[", index: %g", [cardinal[val]]]; ENDCASE => { addr: BitAddress = LOOPHOLE[val]; bitsPerByte: INT = 8; stream.PutF[ ", address: %g [%g:%g]", [cardinal[addr.bd/bitsPerByte]], [cardinal[addr.bd MOD bitsPerByte]], [cardinal[idInfo]]]; IF sep.linkSpace THEN stream.PutChar['*]; }; }; PrintTypeInfo[typeSei, nBlanks+2, stream, stb]; IF sep.extended THEN stream.PutRope["(extended)"]; }; IF sep.flags.valid THEN { stream.PutRope[" flags:"]; IF sep.flags.used THEN stream.PutRope[" used"]; IF sep.flags.addressed THEN stream.PutRope[" addressed"]; IF sep.flags.assigned THEN stream.PutRope[" assigned"]; IF sep.flags.upLevel THEN stream.PutRope[" upLevel"]; }; IF sep.special # normal THEN { stream.PutRope[" special:"]; SELECT sep.special FROM globalLink => stream.PutRope[" globalLink"]; staticLink => stream.PutRope[" staticLink"]; frameExtension => stream.PutRope[" frameExtension"]; memoryLink => stream.PutRope[" memoryLink"]; returnLink => stream.PutRope[" returnLink"]; ENDCASE => NULL; }; }; PrintType: PUBLIC PROC [sei: SEIndex, stream: STREAM, stb: SymbolTableBase] = { IF sei = SENull THEN stream.PutChar['?] 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: SEIndex ¬ sei, SymbolOps.TypeLink[stb, tSei] UNTIL tSei = SENull DO WITH stb.seb[tSei] SELECT FROM id => { IF sei # tSei THEN stream.PutChar[' ]; PrintSei[LOOPHOLE[tSei, ISEIndex], stream, stb]; IF ~mark3 OR stb.ctxb[idCtx].level # lZ THEN EXIT; }; ENDCASE; ENDLOOP; ENDCASE; stream.PutRope[" ["]; PrintLongIndex[sei, stream]; stream.PutChar[']]; }; 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]; stream.PutChar['[]; PrintLongIndex[LOOPHOLE[sei], stream]; stream.PutRope["] "]; 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 stream.PutRope[" (md)"] ELSE IF t.painted THEN stream.PutRope[" (painted)"]; stream.PutRope[", value ctx: "]; PrintLongIndex[t.valueCtx, stream]; }; record => { IF t.machineDep THEN stream.PutRope[" (md)"]; IF t.monitored THEN stream.PutRope[" (monitored)"]; IF t.hints.variant THEN stream.PutRope[" (variant)"]; OutCtx[", field", t.fieldCtx, stream]; WITH stb.ctxb[t.fieldCtx] SELECT FROM included => IF ~complete THEN stream.PutRope[" [partial]"]; imported => stream.PutRope[" [partial]"]; ENDCASE; WITH t SELECT FROM linked => { stream.PutRope[", link: "]; PrintType[linkType, stream, stb]}; ENDCASE; }; ref => { SELECT TRUE FROM t.counted => stream.PutRope[" (counted)"]; t.var => stream.PutRope[" (var)"]; ENDCASE; IF t.ordered THEN stream.PutRope[" (ordered)"]; IF t.basing THEN stream.PutRope[" (base)"]; stream.PutRope[", to: "]; PrintType[t.refType, stream, stb]; IF t.readOnly THEN stream.PutRope[" (readonly)"]; PrintTypeInfo[t.refType, nBlanks+2, stream, stb]; }; array => { IF t.packed THEN stream.PutRope[" (packed)"]; stream.PutRope[", index type: "]; PrintType[t.indexType, stream, stb]; stream.PutRope[", component type: "]; PrintType[t.componentType, stream, stb]; PrintTypeInfo[t.indexType, nBlanks+2, stream, stb]; PrintTypeInfo[t.componentType, nBlanks+2, stream, stb]; }; arraydesc => { stream.PutRope[", described type: "]; PrintType[t.describedType, stream, stb]; IF t.readOnly THEN stream.PutRope[" (readonly)"]; PrintTypeInfo[t.describedType, nBlanks+2, stream, stb]; }; transfer => { IF t.safe THEN stream.PutRope[" (safe)"]; OutArgType[", input", t.typeIn, stream, stb]; OutArgType[", output", t.typeOut, stream, stb]; }; definition => { stream.PutRope[", ctx: "]; PrintLongIndex[t.defCtx, stream]; }; union => { IF t.overlaid THEN stream.PutRope[" (overlaid)"]; IF t.controlled THEN { stream.PutRope[", tag: "]; PrintSei[t.tagSei, stream, stb]}; stream.PutRope[", tag type: "]; PrintType[stb.seb[t.tagSei].idType, stream, stb]; stream.PutRope[", case ctx: "]; PrintLongIndex[t.caseCtx, stream]; IF t.controlled THEN PrintSE[t.tagSei, nBlanks+2, FALSE, stream, stb]; }; sequence => { IF t.packed THEN stream.PutRope[" (packed)"]; IF t.controlled THEN { stream.PutRope[", tag: "]; PrintSei[t.tagSei, stream, stb]} ELSE { stream.PutRope[", index type: "]; PrintType[stb.seb[t.tagSei].idType, stream, stb]}; stream.PutRope[", 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 => { stream.PutRope[", base type: "]; PrintType[t.baseType, stream, stb]; stream.PutRope[", offset type: "]; PrintType[t.offsetType, stream, stb]; PrintTypeInfo[t.baseType, nBlanks+2, stream, stb]; PrintTypeInfo[t.offsetType, nBlanks+2, stream, stb]; }; opaque => { stream.PutRope[", id: "]; PrintSei[t.id, stream, stb]; IF t.lengthKnown THEN stream.PutF1[", size: %g", [cardinal[t.length]]]; }; zone => { IF t.counted THEN stream.PutRope[" (counted)"]; IF t.mds THEN stream.PutRope[" (mds)"]; }; subrange => { stream.PutRope[" of: "]; PrintType[t.rangeType, stream, stb]; IF t.filled THEN { stream.PutF1[" origin: %g", [integer[t.origin]]]; stream.PutF1[", range: %g", [cardinal[t.range]]]}; PrintTypeInfo[t.rangeType, nBlanks+2, stream, stb]; }; real => { stream.PutF1[" length: %g", [integer[t.length]]]; }; ENDCASE; }; ENDCASE }; }; PrintTree: PUBLIC PROC [tree: Tree.Link, nBlanks: NAT, stream: STREAM, stb: SymbolTableBase] = { PrintSubTree: PROC [tree: Tree.Link] RETURNS [ok: BOOL ¬ TRUE] = { tag: Tree.LinkTag ~ TreeOps.GetTag[tree]; Indent[stream, nBlanks]; WITH s~~tree SELECT tag FROM hash => PrintName[s.index, stream, stb]; symbol => { PrintSei[s.index, stream, stb]; stream.PutChar['[]; PrintLongIndex[s.index, stream]; stream.PutChar[']]}; literal => PrintLiteral[s.index, stream, stb]; string => stream.PutRope["\"STRING\""]; subtree => { node: Tree.Index = s.index; SELECT node FROM Tree.nullIndex => stream.PutRope[""]; Tree.Index.LAST => stream.PutRope[""]; ENDCASE => { tp: LONG POINTER TO Tree.Node ¬ @stb.tb[node]; stream.PutRope[ConvertUnsafe.ToRope[NodeNameTable[tp.name]]]; stream.PutChar['[]; PrintLongIndex[node, stream]; stream.PutRope["] "]; IF TreeOps.ToCard[tp.info] # 0 THEN { stream.PutRope[" info="]; PrintLongIndex[LOOPHOLE[tp.info], stream]}; IF tp.attr1 OR tp.attr2 OR tp.attr3 THEN { IF TreeOps.ToCard[tp.info] = 0 THEN stream.PutChar[' ]; stream.PutChar['(]; IF tp.attr1 THEN stream.PutChar['1]; IF tp.attr2 THEN stream.PutChar['2]; IF tp.attr3 THEN stream.PutChar['3]; stream.PutChar[')]}; 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; IF NOT PrintSubTree[tp.son[i]] THEN EXIT; ENDLOOP ELSE FOR i: CARDINAL IN [1 .. n] DO [] ¬ PrintSubTree[tp.son[i]]; ENDLOOP; } ELSE { stream.PutRope[" link="]; PrintTreeLink[tp.son[2], stream]; stream.PutRope[" to "]; PrintTreeLink[tp.son[1], stream]}; nBlanks ¬ nBlanks - 2}; }; ENDCASE => { stream.PutF1["(broken Tree.Link, %08xH)", [cardinal[LOOPHOLE[tree]]] ]; ok ¬ FALSE}; }; [] ¬ PrintSubTree[tree]; }; PrintLiteral: PUBLIC PROC [lti: Literals.LTIndex, stream: STREAM, stb: SymbolTableBase] = { IF lti=Literals.LTNull THEN stream.PutRope["(null literal)"] ELSE { desc: Literals.LitDescriptor = DescriptorValue[stb, lti]; v: CARD; IF desc.words # 1 THEN stream.PutChar['[]; FOR i: CARDINAL IN [0 .. desc.words) DO v ¬ SymbolOps.DecodeCard[stb.ltb[desc.offset][i]]; IF v < 1000 THEN stream.Put1[[cardinal[v]]] ELSE stream.PutF1["%b", [cardinal[v]]]; -- octal IF i+1 # desc.words THEN stream.PutChar[',]; ENDLOOP; IF desc.words # 1 THEN stream.PutChar[']]}; RETURN}; PrintStringLiteral: PUBLIC PROC [sti: Literals.STIndex, stream: STREAM, stb: SymbolTableBase] = { msti: MSTIndex = MasterString[stb, sti]; s: LONG POINTER TO Literals.STRecord.master = @stb.ltb[msti]; stream.PutChar['"]; FOR i: CARDINAL IN [0..s.length) DO stream.PutChar[s.string[i]] ENDLOOP; stream.PutChar['"]; IF sti # msti THEN stream.PutChar['L]; }; PrintMobLink: PUBLIC PROC [link: MobDefs.Link, stream: STREAM] = { SELECT link.tag FROM proc => stream.PutF["proc[%g,%g]", [cardinal[link.modIndex]], [cardinal[link.offset]]]; type => { stream.PutRope["type["]; PrintIndex[link.offset, stream]}; ENDCASE => stream.PutF["var[%g,%g]", [cardinal[link.modIndex]], [cardinal[link.offset]]]; }; PrintTreeLink: PUBLIC PROC [link: Tree.Link, stream: STREAM] = { WITH t~~link SELECT TreeOps.GetTag[link] FROM subtree => PrintLongIndex[t.index, stream]; hash => {stream.PutRope["hash#"]; PrintLongIndex[t.index, stream]}; symbol => {stream.PutRope["symbol#"]; PrintLongIndex[t.index, stream]}; literal => {stream.PutRope["literal#"]; PrintLongIndex[t.index, stream]}; ENDCASE => ERROR; }; PrintSei: PUBLIC PROC [sei: ISEIndex, stream: STREAM, stb: SymbolTableBase] = { PrintName[SymbolOps.NameForSe[stb, sei], stream, stb]; }; PrintName: PUBLIC PROC [name: Name, stream: STREAM, stb: SymbolTableBase] = { IF name = nullName THEN stream.PutRope["(anon)"] ELSE { ss: SubString = SymbolOps.SubStringForName[stb, name]; FOR i: NAT IN [ss.offset..ss.offset+ss.length) DO stream.PutChar[ss.base[i]]; ENDLOOP; }; }; WriteNodeName: PUBLIC PROC [n: NodeName, stream: STREAM] = { stream.PutRope[ConvertUnsafe.ToRope[NodeNameTable[n]]]; }; WriteTypeName: PUBLIC PROC [n: TypeClass, stream: STREAM] = { stream.PutRope[ConvertUnsafe.ToRope[TypeNameTable[n]]]; }; WriteModeName: PUBLIC PROC [n: TransferMode, stream: STREAM] = { stream.PutRope[ConvertUnsafe.ToRope[ModeNameTable[n]]]; }; OutCtx: PUBLIC PROC [message: Rope.ROPE, ctx: CTXIndex, stream: STREAM] = { stream.PutRope[message]; stream.PutRope[" ctx: "]; IF ctx = CTXNull THEN stream.PutRope["NIL"] ELSE PrintLongIndex[ctx, stream]; }; OutArgType: PUBLIC PROC [message: ROPE, sei: CSEIndex, stream: STREAM, stb: SymbolTableBase] = { IF sei = SENull THEN {stream.PutRope[message]; stream.PutRope[": NIL"]} ELSE WITH t~~stb.seb[sei] SELECT FROM record => OutCtx[message, t.fieldCtx, stream]; any => {stream.PutRope[message]; stream.PutRope[": ANY"]}; ENDCASE }; PrintVersion: PUBLIC PROC [stamp: VersionStamp, stream: STREAM, useTime: BOOL ¬ FALSE] = { stream.PutF["%08x%08x", [cardinal[stamp[0]]], [cardinal[stamp[1]]] ]; <> < GO TO dreck; stream.PutF["%g)", [time[BasicTime.FromNSTime[stamp.time]]]]; EXITS dreck => stream.PutRope["??)"]; }; };>> }; 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 stream.PutChar[str[i]]; ENDLOOP; }; PrintString: PUBLIC PROC [str: LONG STRING, stream: STREAM] = { IF str # NIL THEN FOR i: NAT IN [0..str.length) DO stream.PutChar[str[i]]; ENDLOOP; }; PrintSubString: PUBLIC PROC [ss: SubString, stream: STREAM] = { FOR i: NAT IN [ss.offset..ss.offset+ss.length) DO stream.PutChar[ss.base[i]] ENDLOOP; }; PrintIndex: PUBLIC PROC [index: UNSPECIFIED, stream: STREAM] = { stream.Put1[[cardinal[LOOPHOLE[index, CARDINAL]]]]; }; PrintLongIndex: PUBLIC PROC [index: Symbols.Base RELATIVE LONG POINTER, stream: STREAM] = { tagged: Table.IndexRep ¬ LOOPHOLE[index]; IO.PutF1[stream, "%g:", [cardinal[tagged.tag]] ]; tagged.tag ¬ 0; IO.PutF1[stream, "%g", [cardinal[LOOPHOLE[tagged, CARD]]] ]; }; Indent: PUBLIC PROC [stream: STREAM, nBlanks: NAT] = { stream.PutChar['\n]; THROUGH [0..nBlanks) DO stream.PutChar[' ]; ENDLOOP; }; DescriptorValue: PUBLIC PROC [stb: SymbolTableBase, lti: LTIndex] RETURNS [LitDescriptor] = { bitsPerWord: CARD = 16; WITH entry~~stb.ltb[lti] SELECT FROM short => { deltaShort: CARDINAL = LTRecord.short.SIZE - Symbols.UNSPEC.SIZE; RETURN [[ bits: bitsPerWord, class: unsigned, words: 1, offset: LOOPHOLE[lti + deltaShort]]]}; long => { deltaLong: CARDINAL = SIZE[LTRecord.long[0]]; RETURN [[ bits: entry.bits, class: unsigned, words: entry.bits/bitsPerWord, offset: LOOPHOLE[lti + deltaLong]]]}; 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[]; bang: INT ¬ pos; WHILE pos > 0 DO under: INT = pos - 1; SELECT rope.Fetch[under] FROM '! => bang ¬ under; '>, '/, '<, '] => RETURN [rope.Flatten[pos, bang-pos]]; ENDCASE; pos ¬ under; ENDLOOP; RETURN [rope]; }; NodeNameTable: ARRAY NodeName OF LONG STRING = [ "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", "optionTC", "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", "power", "dot", "cdot", "dollar", "create", "not", "uminus", "addr", "uparrow", "min", "max", "ord", "val", "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", "lengthen", "shorten", "self", "gcrt", "proccheck", "entry", "internal", "invalid"]; TypeNameTable: ARRAY TypeClass OF LONG STRING = [ "mode", "basic", "signed", "unsigned", "real", "enumerated", "record", "ref", "array", "arraydesc", "transfer", "definition", "union", "sequence", "relative", "subrange", "opaque", "zone", "any", "nil"]; ModeNameTable: ARRAY TransferMode OF LONG STRING = [ "proc", "port", "signal", "error", "process", "program", "other", "none"]; MobErr: PUBLIC ERROR [err: ROPE] = CODE; MobFile: TYPE = REF MobFileRecord; MobFileRecord: TYPE = RECORD [ name: Rope.ROPE, h: CountedVM.Handle, mob: MobDefs.MobBase, bytes: CARD ]; bytesPerWord: CARD = BYTES[WORD]; bytesPerVMWord: CARD = BYTES[WORD]; bytesPerWord32: CARD = BYTES[CARD32]; ReadMob: PUBLIC PROC [name: ROPE] RETURNS [mob: MobDefs.MobBase] = { mobFile: MobFile ¬ NIL; err: ROPE ¬ NIL; stream: STREAM; time: BasicTime.GMT; mobFile ¬ FindMobFile[name]; IF mobFile # NIL THEN RETURN[mobFile.mob]; [stream, err, time] ¬ ListerSysOps.Open[name, read]; IF err # NIL THEN ERROR MobErr[err: err]; IF stream # NIL THEN { bytes: INT ¬ IO.GetLength[stream]; allocatedBytes: CARD ¬ VM.WordsForPages[VM.PagesForBytes[bytes]] * bytesPerVMWord; allocatedWord32s: CARD ¬ allocatedBytes / bytesPerWord32; h: CountedVM.Handle; mob: MobDefs.MobBase; limit: CARD; IF bytes = 0 THEN ERROR MobErr[err: Rope.Concat["0 length stream for file: ", name]]; h ¬ CountedVM.SimpleAllocate[allocatedBytes/bytesPerWord]; TRUSTED { Basics.FillWords[dst: h.pointer, count: allocatedWord32s, value: CARD.LAST]; IO.SetIndex[stream, 0]; [] ¬ IO.UnsafeGetBlock[ self: stream, block: [base: h.pointer, startIndex: 0, count: bytes]]; [] ¬ ListerSysOps.Close[stream, TRUE]; mob ¬ LOOPHOLE[h.pointer]; }; limit ¬ bytes / BYTES[UNIT]; IF MobMapper.AlterMob[mob, LOOPHOLE[mob], limit ! MobMapper.BadMobContents => GO TO Oops] = badVersion THEN ERROR MobErr[err: Rope.Concat["MobMapper.AlterMob failed for ", name]]; mobFile ¬ NEW[MobFileRecord ¬ [ name: name, h: h, mob: mob, bytes: bytes ]]; AddMobFile[mobFile]; EXITS Oops => ERROR MobErr[err: Rope.Concat["MobMapper.BadMobContents raised for ", name]]; }; RETURN[mobFile.mob]; }; FreeMob: PUBLIC PROC [mob: MobDefs.MobBase] = { mobFile: MobFile ¬ NIL; val: CardTab.Val; [, val] ¬ CardTab.Fetch[x: table.cardTabTable, key: LOOPHOLE[mob]]; IF val = NIL THEN RETURN; mobFile ¬ NARROW[val]; [] ¬ CardTab.Delete[x: table.cardTabTable, key: LOOPHOLE[mob]]; [] ¬ SymTab.Delete[x: table.symTabTable, key: mobFile.name]; mobFile.name ¬ NIL; mobFile.mob ¬ NIL; CountedVM.Free[mobFile.h]; mobFile.h ¬ NIL; }; TablePair: TYPE = REF TablePairRep; TablePairRep: TYPE = RECORD [ cardTabTable: CardTab.Ref, symTabTable: SymTab.Ref ]; table: TablePair = NEW[TablePairRep ¬ [cardTabTable: CardTab.Create[], symTabTable: SymTab.Create[]]]; FindMobFile: PROC [name: ROPE] RETURNS [MobFile] = { WITH SymTab.Fetch[x: table.symTabTable, key: name].val SELECT FROM mobFile: MobFile => RETURN [mobFile]; ENDCASE => RETURN [NIL]; }; AddMobFile: PROC [mobFile: MobFile] = { [] ¬ CardTab.Insert[x: table.cardTabTable, key: LOOPHOLE[mobFile.mob], val: mobFile]; [] ¬ SymTab.Insert[x: table.symTabTable, key: mobFile.name, val: mobFile]; }; InitMobTab: PUBLIC PROC = { CardTab.Erase[table.cardTabTable]; SymTab.Erase[table.symTabTable]; }; END. â MobListerUtilsImpl.mesa Copyright Ó 1984, 1985, 1986, 1987, 1989, 1990, 1991 by Xerox Corporation. All rights reserved. Russ Atkinson (RRA) November 21, 1989 11:32:06 pm PST Sweet October 8, 1985 9:38:39 am PDT Satterthwaite March 11, 1986 8:56:47 am PST Doug Wyatt, January 22, 1987 0:22:39 am PST Andy Litman April 4, 1988 9:08:34 pm PDT JKF May 25, 1990 10:29:11 am PDT Last tweaked by Mike Spreitzer on July 13, 1992 10:01 am PDT Willie-s, September 26, 1991 2:17 pm PDT Michael Plass, November 26, 1991 4:32 pm PST T Y P E S & C O N S T A N T S 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. Crashes for some extensions at the moment -- AHL PrintTree[SymbolOps.FindExtension[stb, sei].tree, nBlanks+4, stream, stb]; Figure out why this crashes for MACHINE CODE = { "..." } -- AHL PrintStringLiteral[s.index, stream, stb]; Very long lists have end markers, not explcit lengths. For all other nodes, believe the given length. deltaShort: CARDINAL = LOOPHOLE[@(NIL[POINTER TO LTRecord.short]).value]; deltaLong: CARDINAL = LOOPHOLE[@(NIL[POINTER TO LTRecord.long]).value]; T A B L E S from ListerSysOps: Ê{•NewlineDelimiter –(cedarcode) style™codešœ™Kšœ ÏeœU™`KšœÏkœ#™5KšÏy!Ðky™$KšŸ( ™+Kšœ(ž™+KšŸ% ™(Kšžœ™ K™˜UKšœ:˜:šžœ˜ KšœAžœžœ˜LKšžœ˜KšœžœV˜]Kšœ žœ˜&Kšœžœ ˜K˜—Kšœžœžœ˜šžœžœDžœ˜lKšžœB˜G—šœ žœ˜Kšœ ˜ K˜Kšœ ˜ K˜ K˜—Kšœ˜šž˜KšœžœH˜U—K˜—Kšžœ˜˜K˜K˜——š¡œžœžœ˜/K˜K˜Kšœ4žœ˜CKšžœžœžœžœ˜Kšœ žœ˜Kšœ?˜?Kšœ<˜