<<>> <> <> <> <> <> <> <> <> DIRECTORY ConvertUnsafe USING [SubString], IO, MobListerUtils USING [PrintName, PrintSei], OSMiscOps USING [bytesPerUnit], Rope USING [ROPE], SortedSymbolLister USING [], StructuredStreams USING [Begin, Bp, Create, End], SymbolOps USING [DecodeCard, DecodeType, FindExtension, FirstCtxSe, LinkMode, NextSe, NormalType, RecField, SubStringForName, ToType, TypeLink, UnderType, XferMode], Symbols USING [Base, BitAddress, BodyRecord, BTIndex, codeANY, codeCHAR, CSEIndex, CSENull, CTXIndex, CTXNull, ExtensionType, FirstStandardCtx, HTIndex, HTNull, ISEIndex, ISENull, LastStandardCtx, lZ, RecordSEIndex, SEIndex, SENull, SERecord, TransferMode, typeANY, typeTYPE], SymbolSegment USING [Base, STHeader], SymbolTable USING [SymbolTableBaseRep], SymbolTablePrivate USING [SymbolTableBase, SymbolTableBaseRep], Tree USING [Base, Index, Link, Node, Null, Scan], TreeOps USING [GetTag], UnparserBuffer USING [Handle, Init, NewInittedHandle]; SortedSymbolListerImpl: PROGRAM IMPORTS IO, MobListerUtils, StructuredStreams, UnparserBuffer, SymbolOps, TreeOps EXPORTS SortedSymbolLister, SymbolTable = BEGIN OPEN Symbols; bitsPerByte: CARD = 8; bitsPerUnit: CARD = OSMiscOps.bytesPerUnit*bitsPerByte; STREAM: TYPE = IO.STREAM; SymbolTableBase: TYPE = REF SymbolTableBaseRep; SymbolTableBaseRep: PUBLIC TYPE = SymbolTablePrivate.SymbolTableBaseRep; ROPE: TYPE = Rope.ROPE; Control: TYPE = {begin, end, brk, tbrk}; DoControl: PROC[st: IO.STREAM, cc: Control] = { SELECT cc FROM $begin => StructuredStreams.Begin[st]; $end => StructuredStreams.End[st]; $brk => StructuredStreams.Bp[st, width, 2]; $tbrk => StructuredStreams.Bp[st, united, 2]; ENDCASE => ERROR; }; alwaysMD: BOOL ¬ FALSE; VfTag: TYPE = {signed, unsigned, char, enum, array, transfer, ref, real, other}; ValFormat: TYPE = RECORD[ bias: INTEGER¬0, var: SELECT tag: VfTag FROM signed => [], --an INTEGER or subrange with base < 0 unsigned => [], -- a CARDINAL, WORD, UNSPECIFIED, or subrange w/ base >= 0 char => [], --a character enum => [esei: EnumeratedSEIndex], --an enumerated type array => [componentType: SEIndex], transfer => [mode: TransferMode], --a PROC, SIGNAL, ERROR, PROGRAM, or PORT ref => [], --a pointer real => [], other => [], --anything else (whether single word or multi-word) ENDCASE ]; PrintInterface: PUBLIC PROC[st: STREAM, stb: SymbolTableBase] = { sei: ISEIndex; stHandle: LONG POINTER TO SymbolSegment.STHeader = stb.stHandle; st.PutRope[" -- Item # -- Item Name\n"]; FOR sei ¬ SymbolOps.FirstCtxSe[stb, stHandle.outerCtx], SymbolOps.NextSe[stb, sei] UNTIL sei = ISENull DO SELECT SymbolOps.LinkMode[stb, sei] FROM val => { PutValue[st, stb, sei]; st.PutRope[ModePrintName[SymbolOps.XferMode[stb, stb.seb[sei].idType]]]; st.PutRope["\n"]; }; ref => { PutValue[st, stb, sei]; st.PutRope["EXPORTED Variable"]; st.PutRope["\n"]; }; manifest => NULL; -- constant ENDCASE; ENDLOOP; }; PutValue: PROCEDURE [st: STREAM, stb: SymbolTableBase, sei: Symbols.ISEIndex] = { idValue: CARD ¬ SymbolOps.DecodeCard[stb.seb[sei].idValue]; st.PutRope[" -- "]; IF stb.seb[sei].extended THEN st.PutRope["(INLINE?) "]; PutUnsigned[st, idValue]; st.PutRope[" -- "]; MobListerUtils.PrintSei[sei: sei, stream: st, stb: stb]; st.PutRope[": "]; }; ModePrintName: ARRAY Symbols.TransferMode OF Rope.ROPE = ["PROCEDURE", "PORT", "SIGNAL", "ERROR", "PROCESS", "PROGRAM", "OTHER", "NONE"]; AddSymbols: PUBLIC PROC[rList: LIST OF REF ANY , stb: SymbolTableBase] RETURNS[LIST OF REF ANY] = { ros: IO.STREAM ¬ IO.ROS[]; upb: UnparserBuffer.Handle; strc: IO.STREAM; modname: ROPE; mySei, sei: ISEIndex; stHandle: LONG POINTER TO SymbolSegment.STHeader = stb.stHandle; ros.PutRope[": --"]; -- set up modname FOR sei ¬ SymbolOps.FirstCtxSe[stb, stHandle.directoryCtx], SymbolOps.NextSe[stb, sei] UNTIL sei = ISENull DO mySei ¬ sei; ENDLOOP; MobListerUtils.PrintSei[mySei, ros, stb]; ros.PutRope["--"]; modname ¬ ros.RopeFromROS[FALSE]; upb ¬ UnparserBuffer.NewInittedHandle[[output: [stream[ros]]]]; strc ¬ StructuredStreams.Create[upb]; FOR sei ¬ SymbolOps.FirstCtxSe[stb, stHandle.outerCtx], SymbolOps.NextSe[stb, sei] UNTIL sei = ISENull DO ros.Reset[]; upb.Init[]; DoControl[strc, $begin]; PrintSym[strc, stb, sei, modname, TRUE]; strc.PutChar[';]; DoControl[strc, $end]; rList ¬ CONS[ros.RopeFromROS[FALSE], rList]; ENDLOOP; RETURN[rList]}; FirstChar: PROC[stb: SymbolTableBase, hti: HTIndex] RETURNS[CHAR] = { ss: ConvertUnsafe.SubString; IF hti = HTNull THEN RETURN['\000]; ss ¬ SymbolOps.SubStringForName[stb, hti]; RETURN[IF ss.length = 0 THEN '\000 ELSE ss.base[ss.offset]]}; PrintSym: PROC[ st: IO.STREAM, stb: SymbolTableBase, sei: ISEIndex, colonstring: ROPE, defaultPublic: BOOL] = { PrintSei: PROC[val: ISEIndex] = { MobListerUtils.PrintSei[sei: val, stream: st, stb: stb]}; PutRope: PROC[val: ROPE] = { st.PutRope[val]}; typeSei: SEIndex; vf: ValFormat; hti: HTIndex; <> hti ¬ stb.seb[sei].hash; IF FirstChar[stb, hti] = '& THEN RETURN; DoControl[st, $begin]; IF hti # HTNull THEN {PrintSei[sei]; PutRope[colonstring]}; IF stb.seb[sei].public # defaultPublic THEN { defaultPublic ¬ stb.seb[sei].public; PutRope[IF defaultPublic THEN "PUBLIC " ELSE "PRIVATE "]}; IF stb.seb[sei].idType = typeTYPE THEN { typeSei ¬ SymbolOps.DecodeType[stb.seb[sei].idInfo]; PutRope["TYPE"]; WITH t~~stb.seb[typeSei] SELECT FROM cons => WITH t SELECT FROM opaque => NULL; ENDCASE => PutRope[" = "]; ENDCASE => PutRope[" = "]; DoControl[st, $brk]; vf ¬ PrintType[st, stb, typeSei, NoSub, defaultPublic]; DoControl[st, $brk]; PrintDefaultValue[st, stb, sei, vf]} ELSE { typeSei ¬ stb.seb[sei].idType; IF stb.seb[sei].immutable AND NOT stb.seb[sei].constant AND (SELECT SymbolOps.XferMode[stb, typeSei] FROM none, process => TRUE, ENDCASE => FALSE) <> THEN PutRope["READONLY "]; vf ¬ PrintType[st, stb, typeSei, NoSub, defaultPublic]; IF stb.seb[sei].constant AND vf.tag <= enum THEN { PutRope[" = "]; DoControl[st, $brk]; IF stb.seb[sei].extended THEN PrintTreeLink[st, stb, SymbolOps.FindExtension[stb, sei].tree, vf] ELSE PrintTypedVal[st, stb, SymbolOps.DecodeCard[stb.seb[sei].idValue], vf]} }; DoControl[st, $end]}; PrintTypedVal: PROC[st: IO.STREAM, stb: SymbolTableBase, val: LONG UNSPECIFIED, vf: ValFormat] = { PutCharConst: PROC[val: CARDINAL] = {st.PutF1["%bC", [cardinal[val]]]}; loophole: BOOL ¬ FALSE; val ¬ val + vf.bias; WITH vf SELECT FROM signed => PutSigned[st, LOOPHOLE[val, INT]]; unsigned => PutUnsigned[st, LOOPHOLE[val, CARD]]; char => PutCharConst[val]; enum => PutEnum[st, stb, val, esei]; transfer, ref => IF val = 0 THEN st.PutRope["NIL"] ELSE loophole ¬ TRUE; ENDCASE => loophole ¬ TRUE; IF loophole THEN { st.PutRope["LOOPHOLE ["]; PutUnsigned[st, LOOPHOLE[val, CARD]]; st.Put1[[character[']]]]}; }; GetBitSpec: PROC[stb: SymbolTableBase, isei: ISEIndex] RETURNS[ROPE] = { a: Symbols.BitAddress; s: CARDINAL; ros: IO.STREAM ¬ IO.ROS[]; [offset: a, size: s] ¬ SymbolOps.RecField[stb, isei]; ros.PutF1[" (%d", [cardinal[a.bd/bitsPerUnit]]]; IF s # 0 THEN ros.PutF[":%d..%d", [cardinal[a.bd MOD bitsPerUnit]], [cardinal[(a.bd+s-1) MOD bitsPerUnit]]]; ros.PutRope["): "]; RETURN[ros.RopeFromROS[]]}; PrintFieldCtx: PROC[st: IO.STREAM, stb: SymbolTableBase, ctx: CTXIndex, md: BOOL, defaultPublic: BOOL] = { PutChar: PROC[val: CHAR] = { st.Put1[[character[val]]]}; PutRope: PROC[val: ROPE] = { st.PutRope[val]}; isei: ISEIndex ¬ SymbolOps.FirstCtxSe[stb, ctx]; bitspec: ROPE ¬ ": "; first: BOOL ¬ TRUE; IF isei # ISENull AND stb.seb[isei].idCtx # ctx THEN isei ¬ SymbolOps.NextSe[stb, isei]; IF isei = ISENull THEN { PutRope["NULL"]; RETURN }; PutChar['[]; FOR isei ¬ isei, SymbolOps.NextSe[stb, isei] UNTIL isei = ISENull DO IF first THEN first ¬ FALSE ELSE PutRope[", "]; DoControl[st, $brk]; IF md THEN bitspec ¬ GetBitSpec[stb, isei]; DoControl[st, $begin]; PrintSym[st, stb, isei, bitspec, defaultPublic]; PrintDefaultValue[st, stb, isei, GetValFormat[stb, stb.seb[isei].idType]]; DoControl[st, $end]; ENDLOOP; PutChar[']]}; PrintValue: PROC[st: IO.STREAM, value: LONG UNSPECIFIED] = { lc: LONG CARDINAL ¬ LOOPHOLE[value]; PutUnsigned[st, lc]}; NoSub: PROC[ptr: BOOL] = { }; EnumeratedSEIndex: TYPE = Symbols.Base RELATIVE LONG POINTER TO SERecord.cons.enumerated; PutEnum: PROC[st: IO.STREAM, stb: SymbolTableBase, val: LONG UNSPECIFIED, esei: EnumeratedSEIndex] = { sei: ISEIndex; FOR sei ¬ SymbolOps.FirstCtxSe[stb, stb.seb[esei].valueCtx], SymbolOps.NextSe[stb, sei] WHILE sei # ISENull DO IF SymbolOps.DecodeCard[stb.seb[sei].idValue] = val THEN {MobListerUtils.PrintSei[sei, st, stb]; RETURN}; ENDLOOP; st.PutRope["LOOPHOLE ["]; PrintValue[st, val]; st.Put1[[character[']]]]}; GetValFormat: PROC[stb: SymbolTableBase, tsei: SEIndex] RETURNS[vf: ValFormat] = { WITH t~~stb.seb[tsei] SELECT FROM id => RETURN[GetValFormat[stb, SymbolOps.UnderType[stb, tsei]]]; cons => WITH t SELECT FROM basic => SELECT code FROM codeANY => vf ¬ [,unsigned[]]; codeCHAR => vf ¬ [,char[]]; ENDCASE; enumerated => vf ¬ [,enum [LOOPHOLE [tsei]]]; array => vf ¬ [,array [componentType]]; transfer => vf ¬ [,transfer[mode]]; relative => vf ¬ GetValFormat[stb, offsetType]; subrange => { vf ¬ GetValFormat[stb, rangeType]; IF vf.tag = signed AND origin >= 0 THEN vf ¬ [,unsigned[]]; vf.bias ¬ origin}; real => vf ¬ [,real[]]; ref => vf ¬ [,ref[]]; ENDCASE => vf ¬ [,other[]]; ENDCASE => vf ¬ [,other[]]; }; octalThreshold: NAT ¬ 1024; PutSigned: PROC[st: IO.STREAM, val: INT] = { IF val > octalThreshold THEN st.PutF1["%bB", [integer[val]]] ELSE st.PutF1["%d", [integer[val]]]}; PutUnsigned: PROC[st: IO.STREAM, val: LONG CARDINAL] = { IF val > octalThreshold THEN st.PutF1["%bB", [cardinal[val]]] ELSE st.PutF1["%d", [cardinal[val]]]}; PrintType: PROC[ st: IO.STREAM, stb: SymbolTableBase, tsei: SEIndex, dosub: PROC[ptr: BOOL], defaultPublic: BOOL] RETURNS[vf: ValFormat] = { PutChar: PROC[val: CHAR] = { st.Put1[[character[val]]]}; PutRope: PROC[val: ROPE] = { st.PutRope[val]}; PrintSei: PROC[val: ISEIndex] = { MobListerUtils.PrintSei[sei: val, stream: st, stb: stb]}; PrintHti: PROC[val: HTIndex] = { MobListerUtils.PrintName[name: val, stream: st, stb: stb]}; vf ¬ GetValFormat[stb, tsei]; WITH t~~stb.seb[tsei] SELECT FROM id => { printBase: BOOL ¬ TRUE; multiSubrange: BOOL ¬ FALSE; bsei: SEIndex ¬ tsei; csei: CSEIndex; <> tseiNext: SEIndex; { l1: SEIndex = SymbolOps.DecodeType[t.idInfo]; IF stb.seb[l1].seTag = id THEN GO TO noAdj; UNTIL (tseiNext ¬ SymbolOps.TypeLink[stb, tsei]) = SENull DO WITH stb.seb[tsei] SELECT FROM id => { PrintSei[LOOPHOLE[tsei]]; PutChar[' ]; }; ENDCASE; tsei ¬ tseiNext; ENDLOOP; EXITS noAdj => NULL; }; <> IF t.idCtx NOT IN [Symbols.FirstStandardCtx..Symbols.LastStandardCtx] THEN WITH c~~stb.ctxb [t.idCtx] SELECT FROM included => { hti: HTIndex = stb.mdb [c.module].moduleId; PrintHti [hti]; --interface name PutChar ['.]}; -- dot qualification < PutCurrentModuleDot[];>> ENDCASE; <> DO csei ¬ SymbolOps.UnderType[stb, bsei]; WITH stb.seb[csei] SELECT FROM basic => { <