MobDebug.mesa
Copyright Ó 1985, 1989, 1991, 1992 by Xerox Corporation. All rights reserved.
Satterthwaite on February 27, 1986 11:43:26 am PST
Lewis on 19-Jan-81 17:28:21
Maxwell, August 4, 1983 11:57 am
Paul Rovner, September 22, 1983 10:09 pm
Russ Atkinson (RRA) March 7, 1985 0:25:20 am PST
Andy Litman May 5, 1988 3:20:48 pm PDT
JKF July 22, 1989 3:52:46 pm PDT
DIRECTORY
Alloc USING [AddNotify, DropNotify, Notifier, Top],
MobBindDefs USING [RelocHandle, RelocType],
MobComData USING [data],
MobControlDefs USING [],
MobDefs USING [Base, Namee, CTIndex, CTNull, CTRecord, cttype, cxtype, EVIndex, EVRecord, EVNull, evtype, EXPIndex, EXPRecord, exptype, fptype, FTIndex, FTNull, FTRecord, FTSelf, fttype, IMPIndex, IMPNull, IMPRecord, imptype, LFIndex, lftype, Link, MTIndex, MTNull, MTRecord, mttype, NameRecord, NTIndex, NTRecord, nttype, RFIndex, rftype, SGIndex, sgtype, SPIndex, SPRecord, sptype, sstype, sttype, TFIndex, tftype, treetype, TMIndex, TMRecord, tmtype, TYPIndex, TYPRecord, typtype, VersionStamp, LinkFrag, NullVersion],
ConvertUnsafe USING [SubString, SubStringToRope, ToRope],
MobHashOps USING [SubStringForHash],
IO USING [card, int, Put, Put1, PutChar, PutF, PutRope, rope, time],
Rope USING [ROPE],
MobSymbols USING [CXIndex, CXRecord, HTIndex, HTNull, STIndex, stNull],
SmallCards USING [Card16],
Table USING [Base],
MobTree USING [Index, Link, NodeName, Scan, nullIndex],
MobTreeOps USING [ScanSons];
MobDebug: PROGRAM
IMPORTS Alloc, ConvertUnsafe, MobHashOps, IO, MobTreeOps, MobComData
EXPORTS MobControlDefs = {
OPEN MobDefs;
tb, cxb, stb, mtb, lfb, rfb, tfb: Table.Base;
etb, evb, itb, ctb, sgb, ftb, typb, tmb, ntb, spb, fpb: Table.Base;
ssb: LONG STRING;
DebugNotify: Alloc.Notifier ~ {
tb ¬ base[treetype]; stb ¬ base[sttype]; cxb ¬ base[cxtype];
ctb ¬ base[cttype]; mtb ¬ base[mttype];
lfb ¬ base[lftype]; rfb ¬ base[rftype]; tfb ¬ base[tftype];
etb ¬ base[exptype]; evb ¬ base[evtype]; itb ¬ base[imptype];
sgb ¬ base[sgtype]; ftb ¬ base[fttype];
typb ¬ base[typtype]; tmb ¬ base[tmtype];
ntb ¬ base[nttype]; ssb ¬ base[sstype];
spb ¬ base[sptype]; fpb ¬ base[fptype]};
SubString: TYPE ~ ConvertUnsafe.SubString;
Utility Writes
WriteChar: PROC[c: CHAR] ~ INLINE {
(MobComData.data.errorStream).PutChar[c]};
WriteRope: PROC[r: Rope.ROPE] ~ {
(MobComData.data.errorStream).PutRope[r]};
WriteString: PROC[s: LONG STRING] ~ --INLINE-- {
(MobComData.data.errorStream).PutRope[ConvertUnsafe.ToRope[s]]};
WriteSubString: PROC[ss: SubString] ~ INLINE {
(MobComData.data.errorStream).PutRope[ConvertUnsafe.SubStringToRope[ss]]};
WriteName: PUBLIC PROC[name: NameRecord] ~ {
ssd: ConvertUnsafe.SubString ~ [base~ssb, offset~name+1, length~ssb.text[name].ORD];
WriteSubString[ssd]};
WriteTime: PUBLIC PROC[t: LONG CARDINAL] ~ {
(MobComData.data.errorStream).Put1[IO.time[LOOPHOLE[t]]]};
WriteCR: PROC ~ INLINE {WriteChar['\012]};
Indent: PROC[n: CARDINAL] ~ {
WriteCR[];
THROUGH [1..n/8] DO WriteChar['\t] ENDLOOP;
THROUGH [1..n MOD 8] DO WriteChar[' ] ENDLOOP};
annotated printing
WriteDecimal: PROC[id: Rope.ROPE, n: INT] ~ {
(MobComData.data.errorStream).Put[IO.rope[id], IO.int[n]]};
WriteOctal: PROC[id: Rope.ROPE, n: UNSPECIFIED] ~ {
IF id # NIL THEN (MobComData.data.errorStream).PutRope[id];
(MobComData.data.errorStream).PutF["%g%b", IO.rope[id], IO.card[LOOPHOLE[n, CARDINAL]]]};
WriteLongOctal: PROC[id: Rope.ROPE, n: LONG UNSPECIFIED] ~ {
IF id # NIL THEN (MobComData.data.errorStream).PutRope[id];
(MobComData.data.errorStream).PutF["%g%b", IO.rope[id], IO.card[LOOPHOLE[n, CARD]]]};
WriteIndex: PROC[id: Rope.ROPE, index: Base RELATIVE LONG POINTER] ~ {
IF id # NIL THEN (MobComData.data.errorStream).PutRope[id];
PrintIndex[index]};
Parse tree printing
WriteNodeName: PROC[n: MobTree.NodeName] ~ {
WriteString[
SELECT n FROM
list => "list",
item => "item",
source => "source",
config => "config",
module => "module",
assign => "assign",
plus => "plus",
then => "then",
dot => "dot",
slash => "slash",
none => "null",
ENDCASE => "ERROR"
];
};
PrintSubMobTree: PROC[t: MobTree.Link, nBlanks: CARDINAL] ~ {
Printer: MobTree.Scan ~ {
Indent[nBlanks];
WITH s~~t SELECT FROM
hash => PrintHti[s.index];
symbol => {PrintHti[stb[s.index].hti]; PrintIndex[s.index]};
subtree => {
node: MobTree.Index ~ s.index;
IF node = MobTree.nullIndex THEN WriteString["<empty>"]
ELSE {
WriteNodeName[tb[node].name]; PrintIndex[node];
SELECT tb[node].name FROM
$config => IF tb[node].attrs[$exportsALL] THEN WriteString[" (EXPORTS ALL)"];
$module =>
IF tb[node].attrs[$explicitLinkLoc] THEN
WriteString[IF tb[node].attrs[$codeLinks] THEN " (Code Links)" ELSE " (Frame Links)"];
$item => IF tb[node].attrs[$codeLinks] THEN WriteString[" (Code Links)"];
ENDCASE;
WriteDecimal[" [", tb[node].info]; WriteChar[']];
nBlanks ¬ nBlanks + 2;
MobTreeOps.ScanSons[s, Printer];
nBlanks ¬ nBlanks - 2}};
ENDCASE};
Printer[t]};
PrintTree: PUBLIC PROC[t: MobTree.Link] ~ {
(MobComData.data.table).AddNotify[DebugNotify];
PrintSubMobTree[t, 0]; WriteCR[]; WriteCR[];
(MobComData.data.table).DropNotify[DebugNotify]};
PrintHti: PROC[hti: MobSymbols.HTIndex] ~ {
s: SubString;
IF hti = MobSymbols.HTNull THEN WriteString["(anonymous)"]
ELSE {s ¬ MobHashOps.SubStringForHash[hti]; WriteSubString[s]}};
Context and semantic entry printing
PrintSemanticEntries: PUBLIC PROC ~ {
cxLimit: MobSymbols.CXIndex ~ (MobComData.data.table).Top[cxtype];
FOR cxi: MobSymbols.CXIndex ¬ MobSymbols.CXIndex.FIRST, cxi+MobSymbols.CXRecord.SIZE UNTIL cxi = cxLimit DO
PrintContext[cxi]; WriteCR[]
ENDLOOP
};
PrintContext: PROC[cxi: MobSymbols.CXIndex] ~ {
(MobComData.data.table).AddNotify[DebugNotify];
WriteIndex["Context: ", cxi];
FOR sti: MobSymbols.STIndex ¬ cxb[cxi].link, stb[sti].link UNTIL sti = MobSymbols.stNull DO
Indent[2];
PrintHti[stb[sti].hti]; PrintIndex[sti];
IF stb[sti].filename THEN WriteString[", filename"];
IF stb[sti].assigned THEN WriteString[", assigned"];
IF stb[sti].imported THEN {
WriteString[", imported"]; IF stb[sti].impi # IMPNull THEN PrintIndex[stb[sti].impi]};
IF stb[sti].exported THEN WriteString[", exported"];
WITH s~~stb[sti] SELECT FROM
external => {
WriteString[", external["];
WITH m~~s.map SELECT FROM
config => WriteIndex["config", m.cti];
module => WriteIndex["module", m.mti];
interface => WriteIndex["interface", m.expi];
ENDCASE;
WITH p~~s SELECT FROM
file => WriteIndex[", file", p.fti];
instance => WriteIndex[", instance", p.sti];
ENDCASE;
WriteChar[']]};
local => {
WriteIndex[", local", s.info];
WITH m~~s.map SELECT FROM
config => WriteIndex["config", m.cti];
ENDCASE;
WriteIndex[", context", s.context]};
unknown => WriteString[", unknown[]"];
ENDCASE;
ENDLOOP;
(MobComData.data.table).DropNotify[DebugNotify];
WriteCR[]};
Mob table printing
PrintMob: PUBLIC PROC ~ {
PrintConfigs[];
PrintImports[];
PrintExports[];
PrintExpVars[];
PrintTypes[];
PrintTypeMap[];
PrintModules[];
PrintFiles[]};
PrintConfigs: PUBLIC PROC ~ {
cti: CTIndex ¬ CTIndex.FIRST;
ctLimit: CTIndex ~ (MobComData.data.table).Top[cttype];
(MobComData.data.table).AddNotify[DebugNotify];
WriteCR[];
WriteString["Configurations:"];
UNTIL cti = ctLimit DO
PrintConfig[cti];
cti ¬ cti + (CTRecord.SIZE+ctb[cti].nControls*Namee.SIZE);
ENDLOOP;
WriteCR[];
(MobComData.data.table).DropNotify[DebugNotify]};
PrintConfig: PUBLIC PROC[cti: CTIndex] ~ {
(MobComData.data.table).AddNotify[DebugNotify];
Indent[2];
WriteName[ctb[cti].name]; PrintIndex[cti];
IF ctb[cti].namedInstance THEN {
WriteString[", instance: "]; WriteNameFromTable[[0,0,config[cti]]]};
WriteString[", file: "];
PrintFileName[ctb[cti].file]; PrintIndex[ctb[cti].file];
IF ctb[cti].config # CTNull THEN {
WriteString[", parent: "]; WriteName[ctb[ctb[cti].config].name]; PrintIndex[ctb[cti].config]};
IF ctb[cti].nControls # 0 THEN {
WriteString[", controls: ["];
FOR i: CARD16 IN [0..ctb[cti].nControls) DO
WITH c~~ctb[cti].controls[i] SELECT FROM
module => WriteName[mtb[c.mti].name];
config => {WriteName[ctb[c.cti].name]; WriteChar['*]};
ENDCASE => ERROR;
WriteString[IF i # ctb[cti].nControls-1 THEN ", " ELSE "]"];
ENDLOOP};
(MobComData.data.table).DropNotify[DebugNotify]};
PrintImports: PUBLIC PROC ~ {
iti: IMPIndex ¬ IMPIndex.FIRST;
impLimit: IMPIndex ~ (MobComData.data.table).Top[imptype];
WriteCR[];
WriteString["Imports:"];
UNTIL iti = impLimit DO PrintImport[iti]; iti ¬ iti + IMPRecord.SIZE ENDLOOP;
WriteCR[]};
PrintImport: PUBLIC PROC[iti: IMPIndex] ~ {
(MobComData.data.table).AddNotify[DebugNotify];
Indent[2];
WriteName[itb[iti].name]; PrintIndex[iti];
SELECT itb[iti].port FROM
$module => WriteString[" (module)"];
ENDCASE;
IF itb[iti].namedInstance THEN {
WriteString[", instance: "]; WriteNameFromTable[[0,0,import[iti]]]};
WriteString[", version: "]; PrintFileVersion[itb[iti].file]; PrintIndex[itb[iti].file];
WriteDecimal[", modIndex: ", itb[iti].modIndex];
(MobComData.data.table).DropNotify[DebugNotify]};
PrintExports: PUBLIC PROC ~ {
eti: EXPIndex ¬ EXPIndex.FIRST;
expLimit: EXPIndex ~ (MobComData.data.table).Top[exptype];
WriteCR[];
WriteString["Exports:"];
UNTIL eti = expLimit DO
PrintExport[eti];
eti ¬ eti + SIZE[EXPRecord[etb[eti].nLinks]]
ENDLOOP;
WriteCR[]};
PrintExport: PUBLIC PROC[eti: EXPIndex] ~ {
(MobComData.data.table).AddNotify[DebugNotify];
Indent[2];
WriteName[etb[eti].name]; PrintIndex[eti];
IF etb[eti].port = $module THEN WriteString[" [module]"];
IF etb[eti].namedInstance THEN {
WriteString[", instance: "]; WriteNameFromTable[[0,0,export[eti]]]};
WriteString[", file: "]; PrintFileVersion[etb[eti].file]; PrintIndex[etb[eti].file];
WriteDecimal[", nLinks: ", etb[eti].nLinks];
WriteString[", links:"];
FOR i: CARDINAL IN [0..etb[eti].nLinks) DO
IF i MOD 8 = 0 THEN Indent[4] ELSE WriteChar[' ];
WriteDecimal["to:", etb[eti].links[i].to]; WriteChar[' ];
PrintControlLink[etb[eti].links[i].from];
IF i+1 # etb[eti].nLinks THEN WriteChar[',];
ENDLOOP;
(MobComData.data.table).DropNotify[DebugNotify]};
PrintExpVars: PUBLIC PROC ~ {
evi: EVIndex ¬ EVIndex.FIRST;
evLimit: EVIndex ~ (MobComData.data.table).Top[evtype];
WriteCR[];
WriteString["Exported variables:"];
UNTIL evi = evLimit DO
PrintExpVar[evi];
evi ¬ evi + evb[evi].length*CARD.SIZE + EVRecord.SIZE;
--evi ¬ evi + evb[evi].length+EVRecord.SIZE
ENDLOOP;
WriteCR[]};
PrintExpVar: PUBLIC PROC[evi: EVIndex] ~ {
(MobComData.data.table).AddNotify[DebugNotify];
Indent[2];
PrintIndex[evi];
WriteDecimal[", length: ", evb[evi].length];
WriteString[", offsets:"];
WriteCR[];
FOR i: CARDINAL IN [1..evb[evi].length] DO
IF i MOD 8 = 1 THEN Indent[4] ELSE WriteChar[' ];
WriteLongOctal[NIL, evb[evi].offsets[i]];
IF i # evb[evi].length THEN WriteChar[',];
ENDLOOP;
(MobComData.data.table).DropNotify[DebugNotify]};
PrintTypes: PUBLIC PROC ~ {
typi: TYPIndex ¬ TYPIndex.FIRST;
typLimit: TYPIndex ~ (MobComData.data.table).Top[typtype];
WriteCR[];
WriteString["Exported types:"];
UNTIL typi = typLimit DO PrintType[typi]; typi ¬ typi + TYPRecord.SIZE ENDLOOP;
WriteCR[]};
PrintType: PUBLIC PROC[typi: TYPIndex] ~ {
(MobComData.data.table).AddNotify[DebugNotify];
Indent[2];
PrintIndex[typi];
WriteDecimal[", id: ", typb[typi].id];
WriteString[", from: "]; PrintVersion[typb[typi].version];
(MobComData.data.table).DropNotify[DebugNotify]};
PrintTypeMap: PUBLIC PROC ~ {
tmi: TMIndex ¬ TMIndex.FIRST;
tmLimit: TMIndex ~ (MobComData.data.table).Top[tmtype];
WriteCR[];
WriteString["Type map:"];
UNTIL tmi = tmLimit DO PrintMapEntry[tmi]; tmi ¬ tmi + TMRecord.SIZE ENDLOOP;
WriteCR[]};
PrintMapEntry: PUBLIC PROC[tmi: TMIndex] ~ {
(MobComData.data.table).AddNotify[DebugNotify];
Indent[2];
PrintIndex[tmi];
WriteDecimal[", entry: ", tmb[tmi].offset];
WriteString[", in: "]; PrintVersion[tmb[tmi].version];
WriteIndex[", mapped to: ", tmb[tmi].map];
(MobComData.data.table).DropNotify[DebugNotify]};
PrintSpaces: PUBLIC PROC ~ {
spi: SPIndex ¬ SPIndex.FIRST;
spLimit: SPIndex ~ (MobComData.data.table).Top[sptype];
WriteCR[];
WriteString["Spaces:"];
UNTIL spi = spLimit DO PrintSpace[spi]; spi ¬ spi + spb[spi].length+SPRecord.SIZE ENDLOOP;
WriteCR[]};
PrintSpace: PUBLIC PROC[spi: SPIndex] ~ {
(MobComData.data.table).AddNotify[DebugNotify];
Indent[2];
PrintIndex[spi];
WriteIndex[", segment: ", spb[spi].seg];
WriteDecimal[", length: ", spb[spi].length];
FOR i: CARDINAL IN [0..spb[spi].length) DO
Indent[4];
IF spb[spi].spaces[i].resident THEN WriteString[", resident"];
WriteOctal[", offset: ", spb[spi].spaces[i].offset];
WriteDecimal[", units: ", spb[spi].spaces[i].pages];
WriteCR[];
ENDLOOP;
(MobComData.data.table).DropNotify[DebugNotify]};
PrintModules: PUBLIC PROC ~ {
mti: MTIndex ¬ MTIndex.FIRST;
mtLimit: MTIndex ~ (MobComData.data.table).Top[mttype];
WriteCR[];
WriteString["Modules:"];
UNTIL mti = mtLimit DO
PrintModule[mti];
mti ¬ mti + MTRecord.SIZE;
ENDLOOP;
WriteCR[]};
PrintModule: PUBLIC PROC[mti: MTIndex] ~ {
(MobComData.data.table).AddNotify[DebugNotify];
Indent[2];
WriteName[mtb[mti].name]; PrintIndex[mti];
IF mtb[mti].namedInstance THEN {
WriteString["instance: "]; WriteNameFromTable[[0,0,module[mti]]]};
WriteString[", file: "]; PrintFileName[mtb[mti].file];
WriteChar[' ]; PrintFileVersion[mtb[mti].file]; PrintIndex[mtb[mti].file];
IF mtb[mti].config # CTNull THEN {
WriteString[", config: "];
WriteName[ctb[mtb[mti].config].name];
PrintIndex[mtb[mti].config]};
Indent[4];
WriteDecimal["framesize: ", mtb[mti].framesize];
WriteDecimal[", modIndex: ", mtb[mti].modIndex];
WriteString[", links: "];
WriteString[SELECT mtb[mti].linkLoc FROM
$framePrefix => "framePrefix",
$codePrefix => "codePrefix",
$inFrame => "inFrame",
ENDCASE => "dontcare"];
Indent[4];
WriteString["code: "]; PrintSegment[mtb[mti].code.sgi];
WriteLongOctal[", offset: ", mtb[mti].code.offset];
WriteLongOctal[", length: ", mtb[mti].code.length];
IF mtb[mti].code.linkspace THEN WriteString[", space available for links"];
Indent[4];
WriteString["symbols: "]; PrintSegment[mtb[mti].sseg];
IF mtb[mti].variables # EVNull THEN {Indent[4]; WriteIndex["variables: ", mtb[mti].variables]};
BEGIN
lfh: LONG POINTER TO LinkFrag = @lfb[mtb[mti].links];
FOR i: SmallCards.Card16 IN [0..lfh.length) DO
IF i MOD 8 = 0 THEN Indent[6] ELSE WriteChar[' ];
PrintControlLink[lfh[i]];
IF i+1 # lfh.length THEN WriteChar[',];
ENDLOOP;
END;
(MobComData.data.table).DropNotify[DebugNotify]};
PrintLinkFrag: PROC[lfi: LFIndex] ~ {
Indent[4];
WriteDecimal["number of links (indirect): ", lfb[lfi].length];
WriteString[", control links:"];
FOR i: CARDINAL IN [0..lfb[lfi].length) DO
IF i MOD 8 = 0 THEN Indent[6] ELSE WriteChar[' ];
PrintControlLink[lfb[lfi].frag[i]];
IF i+1 # lfb[lfi].length THEN WriteChar[',];
ENDLOOP};
PrintRefLitFrag: PROC[rfi: RFIndex] ~ {
Indent[4]; WriteDecimal["number of atoms: ", rfb[rfi].length];
WriteString[", atom and REF literal links:"];
FOR i: CARDINAL IN [0..rfb[rfi].length) DO
IF i MOD 8 = 0 THEN Indent[6] ELSE WriteChar[' ];
WriteDecimal[NIL, rfb[rfi].frag[i]];
IF i+1 # rfb[rfi].length THEN WriteChar[',];
ENDLOOP};
PrintTypeFrag: PROC[tfi: TFIndex] ~ {
Indent[4];
WriteDecimal["number of types: ", tfb[tfi].length];
WriteString[", type codes:"];
FOR i: CARDINAL IN [0..tfb[tfi].length) DO
IF i MOD 8 = 0 THEN Indent[6] ELSE WriteChar[' ];
WriteDecimal[NIL, tfb[tfi].frag[i]];
IF i+1 # tfb[tfi].length THEN WriteChar[',];
ENDLOOP};
PrintSegment: PUBLIC PROC[sgi: SGIndex] ~ {
PrintFileName[sgb[sgi].file];
WriteDecimal[" [base: ", sgb[sgi].base.units];
WriteDecimal[", units: ", sgb[sgi].units.units];
IF sgb[sgi].extraUnits.units # 0 THEN WriteDecimal["+", sgb[sgi].extraUnits.units];
WriteChar[']]};
PrintFiles: PUBLIC PROC ~ {
fti: FTIndex ¬ FTIndex.FIRST;
ftLimit: FTIndex ~ (MobComData.data.table).Top[fttype];
WriteCR[];
WriteString["Files:"];
UNTIL fti = ftLimit DO PrintFile[fti]; fti ¬ fti + FTRecord.SIZE ENDLOOP;
WriteCR[]};
PrintFile: PUBLIC PROC[fti: FTIndex] ~ {
(MobComData.data.table).AddNotify[DebugNotify];
Indent[2];
WriteName[ftb[fti].name]; PrintIndex[fti];
WriteString[", version: "]; PrintFileVersion[fti];
(MobComData.data.table).DropNotify[DebugNotify]};
Utility Prints
PrintControlLink: PROC[link: MobDefs.Link] ~ {
SELECT link.tag FROM
$var => {WriteDecimal["var[", link.modIndex]; WriteDecimal[",", link.offset]};
$proc => {WriteDecimal["proc[", link.modIndex]; WriteDecimal[",", link.offset]};
$type => {WriteDecimal["type[", link.offset]};
ENDCASE => {WriteDecimal["other[", link.modIndex]; WriteDecimal[",", link.offset]};
WriteChar[']]};
PrintFileName: PROC[fti: FTIndex] ~ {
SELECT fti FROM
FTNull => WriteString["(null)"];
FTSelf => WriteString["(self)"];
ENDCASE => WriteName[ftb[fti].name]};
PrintFileVersion: PROC[fti: FTIndex] ~ INLINE
{PrintVersion[ftb[fti].version]};
PrintVersion: PROC[version: VersionStamp] ~ {
WriteChar['(];
IF version = NullVersion THEN WriteString["<null version>"]
ELSE {
StampDigits: CARDINAL ~ 2*VersionStamp.BYTES;
str: PACKED ARRAY [0..StampDigits) OF [0..16) ~ LOOPHOLE[version];
digit: STRING ~ "0123456789abcdef";
WriteChar['"];
FOR i: NAT IN [0..StampDigits) DO WriteChar[digit[str[i]]] ENDLOOP;
WriteChar['"]};
WriteChar[')]};
PrintIndex: PROC[index: Base RELATIVE LONG POINTER] ~ {
WriteChar['[];
IF index = LOOPHOLE[LAST[CARD]-1] THEN WriteString["Null"]
ELSE (MobComData.data.errorStream).Put1[IO.card[LOOPHOLE[index, CARD]]];
WriteChar[']]};
PrintShortIndex: PROC[index: UNSPECIFIED] ~ {
WriteChar['[];
IF index = LAST[CARDINAL]-1 THEN WriteString["Null"]
ELSE (MobComData.data.errorStream).Put1[IO.card[LOOPHOLE[index, CARDINAL]]];
WriteChar[']]};
WriteNameFromTable: PROC[n: Namee] ~ {
ntLimit: NTIndex ~ (MobComData.data.table).Top[nttype];
FOR nti: NTIndex ¬ NTIndex.FIRST, nti + NTRecord.SIZE UNTIL nti = ntLimit DO
IF ntb[nti].item = n THEN {WriteName[ntb[nti].name]; EXIT};
ENDLOOP
};
Relocation printing
PrintRelocations: PUBLIC PROC[relHead: MobBindDefs.RelocHandle] ~ {
WriteCR[];
WriteString["Relocations:"];
FOR rel: MobBindDefs.RelocHandle ¬ relHead, rel.link UNTIL rel = NIL DO
PrintRel[rel] ENDLOOP;
WriteCR[]};
PrintRel: PUBLIC PROC[rel: MobBindDefs.RelocHandle] ~ {
relType: ARRAY MobBindDefs.RelocType OF Rope.ROPE ~ [
outer~"outer", inner~"inner", file~"file"];
mti: MTIndex;
r: Rope.ROPE;
(MobComData.data.table).AddNotify[DebugNotify];
Indent[2];
r ¬ relType[rel.type];
WriteRope[r];
IF rel.import < CARDINAL[rel.importLimit-IMPIndex.FIRST] THEN {
WriteDecimal[" imports: [", rel.import];
WriteDecimal["..", (rel.importLimit-IMPIndex.FIRST)-IMPRecord.SIZE];
WriteString["],"]};
WriteIndex[" context: ", rel.context];
IF rel.type = $file AND (mti ¬ MTIndex.FIRST+rel.module) # MTNull THEN {
WriteString[", module: "]; WriteName[mtb[mti].name]; PrintIndex[mti]};
WriteDecimal[", firstgfi: ", INT[rel.firstgfi]];
WriteDecimal[", lastgfi: ", INT[rel.lastgfi]];
WriteDecimal[", dummygfi: ", INT[rel.dummygfi]];
WriteDecimal[", orig1stdummy: ", INT[rel.originalfirstdummy]];
(MobComData.data.table).DropNotify[DebugNotify]};
}.