<> <> <> DIRECTORY BcdDefs: TYPE USING [Base, CTIndex, CTNull, CTRecord, EXPIndex, EXPRecord, FTIndex, FTNull, FTRecord, FTSelf, IMPIndex, IMPRecord, Link, MTIndex, MTRecord, NameRecord, SGIndex, VersionID, VersionStamp], CWF: TYPE USING [SWF0, WF0, WF1], Directory: TYPE USING [Error, Handle, Lookup], Environment: TYPE USING [wordsPerPage], File: TYPE USING [Capability, nullCapability, read], FileParms: TYPE USING [nullSymbolSpace, SymbolSpace], LeafSubr: TYPE USING [RemoteMap], LongString: TYPE USING [AppendString, AppendSubString, EquivalentString, SubString, SubStringDescriptor], ProcBcds: TYPE USING [Innards, ProcDep, ProcMod], RTBcd: TYPE USING[RTBase], Space: TYPE USING [Create, CreateUniformSwapUnits, Delete, Handle, LongPointer, Map, nullHandle, virtualMemory], Subr: TYPE USING [AllocateString, Any, ControlChars, FreeString, SubStrCopy, strcpy], Symbols: TYPE USING [HTIndex, HTNull, HTRecord, MDIndex, MDRecord, OwnMdi], SymbolSegment: TYPE USING [FGHeader, STHeader, VersionID], Table: TYPE USING [Base], Time: TYPE USING [Current], TimeStamp: TYPE USING [Stamp]; ProcBcdsImpl: PROGRAM IMPORTS CWF, Directory, LeafSubr, LongString, Space, Subr, Time EXPORTS ProcBcds = { useonespace: BOOL = TRUE; -- FALSE has never worked Sym: TYPE = POINTER TO SymRecord; SymRecord: TYPE = RECORD[ stHandle: LONG POINTER TO SymbolSegment.STHeader _ NIL, stHandleSpace: Space.Handle _ Space.nullHandle, <<>> <> ht: LONG DESCRIPTOR FOR ARRAY Symbols.HTIndex OF Symbols.HTRecord _ NULL, htSpace: Space.Handle _ Space.nullHandle, <<>> ssb: LONG STRING _ NIL, -- id string ssbSpace: Space.Handle _ Space.nullHandle, <<>> mdb: Table.Base _ NIL, -- module directory base mdbSpace: Space.Handle _ Space.nullHandle, mdLimit: Symbols.MDIndex _ NULL, -- module directory size <<>> fgptr: LONG POINTER TO SymbolSegment.FGHeader _ NIL, -- ptr to beginning of fine grain table fgptrSpace: Space.Handle _ Space.nullHandle ]; InvalidBcd: PUBLIC SIGNAL = CODE; ReadInSegmentsBcd: PUBLIC PROC [innards: ProcBcds.Innards] = { local: BOOL; npages: CARDINAL; IF innards.cap = File.nullCapability AND innards.fh = NIL THEN ERROR; local _ innards.fh = NIL; <> innards.bcdheaderspace _ Space.Create[size: 10, parent: Space.virtualMemory]; IF local THEN Space.Map[space: innards.bcdheaderspace, window: [file: innards.cap, base: 1]] ELSE LeafSubr.RemoteMap[space: innards.bcdheaderspace, fh: innards.fh, base: 0]; innards.bcd _ Space.LongPointer[innards.bcdheaderspace]; IF innards.bcd.versionIdent ~= BcdDefs.VersionID THEN { <> Space.Delete[innards.bcdheaderspace]; innards.bcdheaderspace _ Space.nullHandle; innards.bcd _ NIL; SIGNAL InvalidBcd; RETURN; }; npages _ innards.bcd.nPages; IF npages > 10 THEN { Space.Delete[innards.bcdheaderspace]; <> innards.bcdheaderspace _ Space.Create[size: npages, parent: Space.virtualMemory]; IF local THEN Space.Map[space: innards.bcdheaderspace, window: [file: innards.cap, base: 1]] ELSE LeafSubr.RemoteMap[space: innards.bcdheaderspace, fh: innards.fh, base: 0]; innards.bcd _ Space.LongPointer[innards.bcdheaderspace]; }; Space.CreateUniformSwapUnits[parent: innards.bcdheaderspace, size: 8]; innards.upperLimit _ npages * Environment.wordsPerPage; }; InstallAddressesBcd: PUBLIC PROC[innards: ProcBcds.Innards] = { innards.tb _ LOOPHOLE[innards.bcd]; innards.ssb _ LOOPHOLE[innards.bcd + innards.bcd.ssOffset]; innards.ctb _ innards.tb + innards.bcd.ctOffset; innards.mtb _ innards.tb + innards.bcd.mtOffset; innards.itb _ innards.tb + innards.bcd.impOffset; innards.etb _ innards.tb + innards.bcd.expOffset; innards.sgb _ innards.tb + innards.bcd.sgOffset; innards.ftb _ innards.tb + innards.bcd.ftOffset; innards.ntb _ innards.tb + innards.bcd.ntOffset; innards.evb _ innards.tb + innards.bcd.evOffset; innards.spb _ innards.tb + innards.bcd.spOffset; innards.fpb _ innards.tb + innards.bcd.fpOffset; }; UnstallBcd: PUBLIC PROC [innards: ProcBcds.Innards] = { IF innards.bcdheaderspace = Space.nullHandle THEN ERROR; Space.Delete[innards.bcdheaderspace]; innards^ _ [bcdheaderspace: Space.nullHandle]; -- others are defaulted }; PrintDepends: PUBLIC PROC [innards: ProcBcds.Innards, procMod: ProcBcds.ProcMod,procDep: ProcBcds.ProcDep, print, calltwice, less: BOOL, bcdfilename: LONG STRING] RETURNS [success, isconfig, isdefns: BOOL, nimp, nexp, ntype: CARDINAL] = { uns: UNSPECIFIED; cti: BcdDefs.CTIndex _ FIRST[BcdDefs.CTIndex]; nullstring: STRING _ ""L; altoCode, boundsChecks, cedarSwitch, crossJump, linksInCode, nilChecks, sortByUsage: BOOL _ FALSE; notcodebound: BOOL; symbolSpace: FileParms.SymbolSpace _ FileParms.nullSymbolSpace; rtVersionID: CARDINAL _ 0; sourcefile: LONG STRING _ Subr.AllocateString[100]; interfacename: LONG STRING _ Subr.AllocateString[100]; switches: LONG STRING _ Subr.AllocateString[100]; {ENABLE UNWIND => { Subr.FreeString[sourcefile]; Subr.FreeString[interfacename]; Subr.FreeString[switches]}; success _ isconfig _ isdefns _ FALSE; nexp _ nimp _ ntype _ 0; IF nullstring.length ~= 0 THEN ERROR; IF innards.bcd.versionIdent ~= BcdDefs.VersionID THEN { CWF.WF0[" Error - wrong bcd version.\n"L]; GO TO return; }; <> PutName[innards, innards.bcd.source, sourcefile]; IF sourcefile.length >0 AND sourcefile[sourcefile.length -1] = '. THEN sourcefile.length _ sourcefile.length - 1; <> IF Subr.ControlChars[sourcefile] THEN { CWF.WF0[" Error - bad sourcefile.\n"L]; GO TO return; }; success _ GetModuleName[innards, interfacename]; IF NOT success THEN GO TO return; <> <> isconfig _ innards.bcd.nConfigs > 0; IF NOT isconfig THEN { sSeg: BcdDefs.SGIndex _ innards.mtb[FIRST[BcdDefs.MTIndex]].sseg; altoCode _ innards.mtb[FIRST[BcdDefs.MTIndex]].altoCode; boundsChecks _ innards.mtb[FIRST[BcdDefs.MTIndex]].boundsChecks; crossJump _ innards.mtb[FIRST[BcdDefs.MTIndex]].crossJumped; cedarSwitch _ IF NOT altoCode THEN innards.mtb[FIRST[BcdDefs.MTIndex]].long ELSE FALSE; nilChecks _ innards.mtb[FIRST[BcdDefs.MTIndex]].nilChecks; linksInCode _ innards.mtb[FIRST[BcdDefs.MTIndex]].linkLoc = code; sortByUsage _ NOT innards.mtb[FIRST[BcdDefs.MTIndex]].initial; -- /s switch, initial = FALSE is /s symbolSpace _ [file: innards.cap, span: [base: innards.sgb[sSeg].base, pages: innards.sgb[sSeg].pages]]; }; notcodebound _ IF isconfig THEN NotCodeBound[innards, BcdDefs.CTNull] ELSE TRUE; isdefns _ innards.bcd.definitions; IF isdefns THEN uns _ procMod[sourcefile, interfacename, innards.bcd.version, innards.bcd.sourceVersion, innards.bcd.creator, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, symbolSpace, 0] ELSE { IF innards.bcd.extended AND innards.bcd.rtPages.pages > 0 THEN rtVersionID _ LOOPHOLE[innards.bcd + innards.bcd.rtPages.relPageBase*Environment.wordsPerPage, RTBcd.RTBase].versionIdent; uns _ procMod[sourcefile, interfacename, innards.bcd.version, innards.bcd.sourceVersion, innards.bcd.creator, FALSE, isconfig, NOT notcodebound, innards.bcd.tableCompiled, altoCode, boundsChecks, cedarSwitch, crossJump, linksInCode, nilChecks, sortByUsage, symbolSpace, rtVersionID]; }; IF NOT isconfig THEN { IF innards.bcd.extended THEN ntype _ PrintDirectory[innards, procDep, uns, print, bcdfilename] ELSE [,ntype] _ PrintSymbolsFile[innards, procDep, uns, print, FALSE, less, bcdfilename]; }; IF NOT isdefns THEN nexp _ PrintExports[innards, procDep, uns, print]; IF calltwice AND NOT isdefns AND (ntype > 50 OR nexp > 30) THEN { <> uns _ procMod[ sourcefile, interfacename, innards.bcd.version, innards.bcd.sourceVersion, innards.bcd.creator, FALSE, isconfig, NOT notcodebound, innards.bcd.tableCompiled, altoCode, boundsChecks, cedarSwitch, crossJump, linksInCode, nilChecks, sortByUsage, symbolSpace, rtVersionID]; }; nimp _ PrintImports[innards, procDep, uns, print]; IF isconfig THEN { PrintConfigDepends[innards, procDep, uns, notcodebound, FALSE]; IF NOT notcodebound AND print THEN CWF.WF0["(code bound)\n"L]; }; success _ TRUE; EXITS return => {}; }; -- of ENABLE UNWIND Subr.FreeString[sourcefile]; Subr.FreeString[interfacename]; Subr.FreeString[switches]; }; PrintDirectory: PROC [innards: ProcBcds.Innards, procDep: ProcBcds.ProcDep, uns: UNSPECIFIED, print: BOOL, bcdfilename: LONG STRING] RETURNS [ntype: CARDINAL] = { modulename: LONG STRING _ Subr.AllocateString[100]; filename: LONG STRING _ Subr.AllocateString[100]; fti: BcdDefs.FTIndex _ FIRST[BcdDefs.FTIndex]; {ENABLE UNWIND => {Subr.FreeString[modulename]; Subr.FreeString[filename]}; ntype _ 0; UNTIL fti = innards.bcd.ftLimit DO PutName[innards, innards.ftb[fti].name, filename]; IF NOT Subr.Any[filename, '.] THEN LongString.AppendString[filename, ".bcd"L]; procDep[defstype, GuessModulename[innards, fti, modulename], filename, innards.ftb[fti].version, uns]; ntype _ ntype + 1; fti _ fti + SIZE[BcdDefs.FTRecord]; IF LOOPHOLE[fti, CARDINAL] > LOOPHOLE[innards.bcd.ftLimit, CARDINAL] THEN GO TO Bogus; REPEAT Bogus => { CWF.WF1["Error - Garbage FileTable in %s.\n"L, bcdfilename]; GO TO return; }; ENDLOOP; IF print THEN CWF.WF1[" %d types.\n"L, @ntype]; EXITS return => {}; }; -- of ENABLE UNWIND Subr.FreeString[modulename]; Subr.FreeString[filename]; }; GuessModulename: PROC [innards: ProcBcds.Innards, fti: BcdDefs.FTIndex, modulename: LONG STRING] RETURNS[LONG STRING] = { <> iti: BcdDefs.IMPIndex _ FIRST[BcdDefs.IMPIndex]; eti: BcdDefs.EXPIndex _ FIRST[BcdDefs.EXPIndex]; WHILE LOOPHOLE[iti, CARDINAL] < LOOPHOLE[innards.bcd.impLimit, CARDINAL] DO IF innards.itb[iti].file = fti THEN { PutName[innards, innards.itb[iti].name, modulename]; RETURN[modulename]; }; iti _ iti + SIZE[BcdDefs.IMPRecord]; ENDLOOP; WHILE LOOPHOLE[eti, CARDINAL] < LOOPHOLE[innards.bcd.expLimit, CARDINAL] DO IF innards.etb[eti].file = fti THEN { PutName[innards, innards.etb[eti].name, modulename]; RETURN[modulename]; }; eti _ eti + SIZE[BcdDefs.IMPRecord] + innards.etb[eti].size; ENDLOOP; RETURN[NIL]; }; PrintSymbolsFile: PUBLIC PROC [innards: ProcBcds.Innards, procDep: ProcBcds.ProcDep, uns: UNSPECIFIED, print, allsyms, less: BOOL, bcdfilename: LONG STRING] RETURNS[success: BOOL, ntype: CARDINAL] = { <> mti, mtLimit: BcdDefs.MTIndex; symseg: BcdDefs.SGIndex; symrecord: SymRecord _ []; shortstr: LONG STRING _ Subr.AllocateString[100]; nullstr: STRING _ ""L; {ENABLE UNWIND => {Subr.FreeString[shortstr]}; ntype _ 0; success _ FALSE; mti _ FIRST[BcdDefs.MTIndex]; mtLimit _ IF allsyms THEN innards.bcd.mtLimit ELSE mti + 1; UNTIL LOOPHOLE[mti, CARDINAL] >= LOOPHOLE[mtLimit, CARDINAL] DO symseg _ innards.mtb[mti].sseg; success _ InitSym[innards, @symrecord, symseg, less, bcdfilename]; IF NOT success THEN EXIT; [success, ntype] _ PrintModuleEntries[innards, @symrecord, procDep, uns, print, bcdfilename]; IF NOT success THEN EXIT; IF NOT less THEN { FindSourceFileName[@symrecord, shortstr]; IF shortstr.length > 0 THEN procDep[sourcefile, nullstr, shortstr, symrecord.stHandle.sourceVersion, uns]; }; FreeSym[@symrecord]; mti _ mti + (WITH m: innards.mtb[mti] SELECT FROM direct => SIZE[BcdDefs.MTRecord[direct]] + m.length*SIZE[BcdDefs.Link], indirect => SIZE[BcdDefs.MTRecord[indirect]], multiple => SIZE[BcdDefs.MTRecord[multiple]], ENDCASE => ERROR) ENDLOOP; }; -- of ENABLE UNWIND Subr.FreeString[shortstr]; RETURN[success, ntype]; }; InitSym: PROC[innards: ProcBcds.Innards, sym: Sym, symseg: BcdDefs.SGIndex, less: BOOL, bcdfilename: LONG STRING] RETURNS[success: BOOL _ FALSE] = { <> npages: CARDINAL; cap: File.Capability; local: BOOL; base: CARDINAL; p: LONG POINTER; sfnsym: LONG STRING _ Subr.AllocateString[100]; {ENABLE UNWIND => {Subr.FreeString[sfnsym]}; IF innards.sgb[symseg].class ~= symbols THEN { CWF.WF0["Error - badly formed symbols.\n"L]; GO TO return; }; IF innards.sgb[symseg].pages = 0 THEN { CWF.WF1["Warning - No symbols in %s.\n"L, bcdfilename]; GO TO return; }; IF innards.sgb[symseg].file ~= BcdDefs.FTSelf THEN { PrintFileName[innards, innards.sgb[symseg].file, sfnsym]; cap _ Directory.Lookup[ fileName: sfnsym, permissions: File.read ! Directory.Error => GOTO err]; EXITS err => { CWF.WF1["Error - can't find '%s'\n"L, sfnsym]; GO TO return; }; } ELSE cap _ innards.cap; npages _ innards.sgb[symseg].pages; IF NOT less THEN npages _ npages + innards.sgb[symseg].extraPages; IF useonespace THEN sym.stHandleSpace _ Space.Create[parent: Space.virtualMemory, size: npages] ELSE sym.stHandleSpace _ Space.Create[ parent: Space.virtualMemory, size: (SIZE[SymbolSegment.STHeader]/Environment.wordsPerPage) + 1]; local _ innards.fh = NIL; IF local THEN { base _ innards.sgb[symseg].base; Space.Map[space: sym.stHandleSpace, window: [file: cap, base: base]] } ELSE { base _ innards.sgb[symseg].base - 1; LeafSubr.RemoteMap[sym.stHandleSpace, innards.fh, base]; }; sym.stHandle _ Space.LongPointer[sym.stHandleSpace]; IF sym.stHandle.versionIdent ~= SymbolSegment.VersionID THEN { CWF.WF0["Error - Symbols versions do not agree.\n"L]; GO TO return; }; <> IF useonespace THEN { b: LONG POINTER; tB: Table.Base; b _ LOOPHOLE[sym.stHandle]; tB _ LOOPHOLE[sym.stHandle]; sym.ht _ DESCRIPTOR[b+sym.stHandle.htBlock.offset, sym.stHandle.htBlock.size/SIZE[Symbols.HTRecord]]; sym.ssb _ b + sym.stHandle.ssBlock.offset; sym.mdb _ tB + sym.stHandle.mdBlock.offset; sym.mdLimit _ FIRST[Symbols.MDIndex] + sym.stHandle.mdBlock.size; IF NOT less THEN sym.fgptr _ LOOPHOLE[ sym.stHandle + sym.stHandle.fgRelPgBase * Environment.wordsPerPage]; } ELSE { [p, sym.htSpace] _ GetSpace[innards, sym, base, sym.stHandle.htBlock.offset, sym.stHandle.htBlock.size]; sym.ht _ DESCRIPTOR[p, sym.stHandle.htBlock.size/SIZE[Symbols.HTRecord]]; [sym.ssb, sym.ssbSpace] _ GetSpace[innards, sym, base, sym.stHandle.ssBlock.offset, sym.stHandle.ssBlock.size]; [LOOPHOLE[sym.mdb, LONG POINTER], sym.mdbSpace] _ GetSpace[innards, sym, base, sym.stHandle.mdBlock.offset, sym.stHandle.mdBlock.size]; sym.mdLimit _ FIRST[Symbols.MDIndex] + sym.stHandle.mdBlock.size; IF NOT less THEN [LOOPHOLE[sym.fgptr, LONG POINTER], sym.fgptrSpace] _ GetSpace[ innards, sym, base, sym.stHandle.fgRelPgBase * Environment.wordsPerPage, Environment.wordsPerPage]; }; success _ TRUE; EXITS return => {}; }; -- of ENABLE UNWIND Subr.FreeString[sfnsym]; }; GetSpace: PROC[innards: ProcBcds.Innards, sym: Sym, pbase, offset, size: CARDINAL] RETURNS[buffer: LONG POINTER, space: Space.Handle] = { <> pstart, pnum: CARDINAL; pageoffset: CARDINAL _ offset/Environment.wordsPerPage; pstart _ pbase + pageoffset; pnum _ ((size+offset)/Environment.wordsPerPage) - pageoffset + 1; space _ Space.Create[parent: Space.virtualMemory, size: pnum]; IF innards.cap ~= File.nullCapability THEN Space.Map[space, [innards.cap, pstart]] ELSE LeafSubr.RemoteMap[space, innards.fh, pstart]; buffer _ Space.LongPointer[space]; buffer _ buffer + (offset - (pageoffset*Environment.wordsPerPage)); }; PrintModuleEntries: PROC[innards: ProcBcds.Innards, sym: Sym, procDep: ProcBcds.ProcDep, uns: UNSPECIFIED, print: BOOL, bcdfilename: LONG STRING] RETURNS[success: BOOL, ntype: CARDINAL] = { <> <> mdi: Symbols.MDIndex _ FIRST[Symbols.MDIndex]; sfn: LONG STRING _ Subr.AllocateString[100]; smodulename: LONG STRING _ Subr.AllocateString[100]; substr: LongString.SubStringDescriptor; {ENABLE UNWIND => {Subr.FreeString[sfn]; Subr.FreeString[smodulename]}; ntype _ 0; success _ FALSE; DO <> IF mdi = Symbols.OwnMdi THEN mdi _ mdi + SIZE[Symbols.MDRecord]; IF mdi = sym.mdLimit THEN EXIT; SubStringForHash[sym, @substr, sym.mdb[mdi].moduleId]; smodulename.length _ 0; LongString.AppendSubString[smodulename, @substr]; SubStringForHash[sym, @substr, sym.mdb[mdi].fileId]; sfn.length _ 0; LongString.AppendSubString[sfn, @substr]; IF sfn.length > 0 AND sfn[sfn.length-1] = '. THEN sfn.length _ sfn.length - 1; -- strip "." <> ntype _ ntype + 1; procDep[defstype, smodulename, sfn, sym.mdb[mdi].stamp, uns]; mdi _ mdi + SIZE[Symbols.MDRecord]; IF LOOPHOLE[mdi, CARDINAL] > LOOPHOLE[sym.mdLimit, CARDINAL] THEN { CWF.WF1["Warning - symbols MDRecord is garbage in %s.\n"L, bcdfilename]; GO TO return; }; ENDLOOP; IF print THEN CWF.WF1["%u types, "L, @ntype]; success _ TRUE; EXITS return => {}; }; -- of ENABLE UNWIND Subr.FreeString[sfn]; Subr.FreeString[smodulename]; }; FindSourceFileName: PROC[sym: Sym, tostr: LONG STRING] = { <> IF sym.stHandle.fgRelPgBase > 0 AND sym.stHandle.fgPgCount > 0 THEN { tostr.length _ 0; LongString.AppendString[tostr, @sym.fgptr.sourceFile]; <> IF tostr.length > 0 AND tostr[tostr.length-1] = '. THEN tostr.length _ tostr.length - 1; -- strip "." } ELSE tostr.length _ 0; <\n"L, tostr];>> }; FreeSym: PROC[sym: Sym] = { <> IF sym.stHandleSpace ~= Space.nullHandle THEN { Space.Delete[sym.stHandleSpace]; sym.stHandleSpace _ Space.nullHandle; }; IF sym.htSpace ~= Space.nullHandle THEN { Space.Delete[sym.htSpace]; sym.htSpace _ Space.nullHandle; }; IF sym.ssbSpace ~= Space.nullHandle THEN { Space.Delete[sym.ssbSpace]; sym.ssbSpace _ Space.nullHandle; }; IF sym.mdbSpace ~= Space.nullHandle THEN { Space.Delete[sym.mdbSpace]; sym.mdbSpace _ Space.nullHandle; }; IF sym.fgptrSpace ~= Space.nullHandle THEN { Space.Delete[sym.fgptrSpace]; sym.fgptrSpace _ Space.nullHandle; }; }; SubStringForHash: PROC [sym: Sym, s: LongString.SubString, hti: Symbols.HTIndex] = { s.base _ sym.ssb; IF hti = Symbols.HTNull THEN s.offset _ s.length _ 0 ELSE s.length _ sym.ht[hti].ssIndex - (s.offset _ sym.ht[hti-1].ssIndex) }; GetModuleName: PUBLIC PROC[innards: ProcBcds.Innards, interfacename: LONG STRING] RETURNS[success: BOOL] = { <> <> <> cti: BcdDefs.CTIndex _ FIRST[BcdDefs.CTIndex]; IF innards.bcd.nConfigs = 0 THEN PutName[innards, innards.mtb[FIRST[BcdDefs.MTIndex]].name, interfacename] ELSE UNTIL cti = innards.bcd.ctLimit DO IF innards.ctb[cti].config = BcdDefs.CTNull THEN { PutName[innards, innards.ctb[cti].name, interfacename]; <> EXIT; }; cti _ cti+innards.ctb[cti].nControls + SIZE[BcdDefs.CTRecord]; IF LOOPHOLE[cti, CARDINAL] > LOOPHOLE[innards.bcd.ctLimit, CARDINAL] THEN { CWF.WF0["Garbage Garbage Garbage.\n"L]; RETURN[FALSE]; }; ENDLOOP; RETURN[TRUE]; }; PrintExports: PROC[innards: ProcBcds.Innards, procDep: ProcBcds.ProcDep, uns: UNSPECIFIED, print: BOOL] RETURNS[nexp: CARDINAL] = { eti: BcdDefs.EXPIndex _ FIRST[BcdDefs.EXPIndex]; nexp _ 0; UNTIL eti = innards.bcd.expLimit DO PrintExport[innards, eti, procDep, uns]; nexp _ nexp + 1; eti _ eti + innards.etb[eti].size + SIZE[BcdDefs.EXPRecord]; IF LOOPHOLE[eti, CARDINAL] > LOOPHOLE[innards.bcd.expLimit, CARDINAL] THEN GO TO Bogus; REPEAT Bogus => { CWF.WF0["Garbage Garbage Garbage.\n"L]; RETURN; }; ENDLOOP; IF print THEN CWF.WF1[" %d exp, "L, @nexp]; }; PrintExport: PROC [innards: ProcBcds.Innards, eti: BcdDefs.EXPIndex, procDep: ProcBcds.ProcDep, uns: UNSPECIFIED] = { OPEN innards.etb[eti]; stemp: LONG STRING _ Subr.AllocateString[100]; stemp1: LONG STRING _ Subr.AllocateString[100]; vers: BcdDefs.VersionStamp; {ENABLE UNWIND => {Subr.FreeString[stemp]; Subr.FreeString[stemp1]}; PutName[innards, name, stemp]; PrintFileName[innards, file, stemp1]; IF stemp.length = 0 OR Subr.ControlChars[stemp] OR stemp1.length = 0 OR Subr.ControlChars[stemp1] THEN { CWF.WF0["name garbaged up\n"L]; GO TO return; }; vers _ innards.ftb[file].version; procDep[exports, stemp, stemp1, vers, uns]; EXITS return => {}; }; -- of ENABLE UNWIND Subr.FreeString[stemp]; Subr.FreeString[stemp1]; }; PrintImports: PROC[innards: ProcBcds.Innards, procDep: ProcBcds.ProcDep, uns: UNSPECIFIED, print: BOOL] RETURNS[nimp: CARDINAL] = { iti: BcdDefs.IMPIndex _ FIRST[BcdDefs.IMPIndex]; nullstring: STRING _ ""L; nimp _ 0; UNTIL iti = innards.bcd.impLimit DO PrintImport[innards, iti, procDep, uns]; nimp _ nimp + 1; iti _ iti + SIZE[BcdDefs.IMPRecord]; IF LOOPHOLE[iti, CARDINAL] > LOOPHOLE[innards.bcd.impLimit, CARDINAL] THEN GO TO Bogus; REPEAT Bogus => { CWF.WF0["Garbage Garbage Garbage.\n"L]; RETURN; }; ENDLOOP; IF print THEN CWF.WF1[" %d imp.\n"L, @nimp]; }; PrintImport: PROC [innards: ProcBcds.Innards, iti: BcdDefs.IMPIndex, procDep: ProcBcds.ProcDep, uns: UNSPECIFIED] = { OPEN innards.itb[iti]; stemp: LONG STRING _ Subr.AllocateString[100]; stemp1: LONG STRING _ Subr.AllocateString[100]; vers: BcdDefs.VersionStamp; {ENABLE UNWIND => {Subr.FreeString[stemp]; Subr.FreeString[stemp1]}; PutName[innards, name, stemp]; PrintFileName[innards, file, stemp1]; IF stemp.length = 0 OR Subr.ControlChars[stemp] OR stemp1.length = 0 OR Subr.ControlChars[stemp1] THEN { CWF.WF0["name garbaged up\n"L]; GO TO return; }; vers _ innards.ftb[file].version; procDep[imports, stemp, stemp1, vers, uns]; EXITS return => {}; }; -- of ENABLE UNWIND Subr.FreeString[stemp]; Subr.FreeString[stemp1]; }; NotCodeBound: PROC[innards: ProcBcds.Innards, parent: BcdDefs.CTIndex] RETURNS [notcodebound: BOOL] = { <> <> cti: BcdDefs.CTIndex _ FIRST[BcdDefs.CTIndex]; notcodebound _ FALSE; UNTIL cti = innards.bcd.ctLimit DO IF innards.ctb[cti].config = parent THEN { notcodebound _ notcodebound OR NotCodeBound[innards, cti]; notcodebound _ notcodebound OR NotCodeBoundModule[innards, cti]; }; cti _ cti + innards.ctb[cti].nControls + SIZE[BcdDefs.CTRecord]; IF LOOPHOLE[cti, CARDINAL] > LOOPHOLE[innards.bcd.ctLimit, CARDINAL] THEN { CWF.WF0["Garbage Config.\n"L]; RETURN; }; ENDLOOP; }; NotCodeBoundModule: PROC[innards: ProcBcds.Innards, cti: BcdDefs.CTIndex] RETURNS[notcodebound: BOOL] = { codeseg: BcdDefs.SGIndex; mti: BcdDefs.MTIndex _ FIRST[BcdDefs.MTIndex]; notcodebound _ FALSE; UNTIL mti = innards.bcd.mtLimit DO IF innards.mtb[mti].config = cti THEN { IF innards.mtb[mti].file ~= BcdDefs.FTSelf THEN { codeseg _ innards.mtb[mti].code.sgi; IF innards.sgb[codeseg].class ~= code THEN { CWF.WF0["Error - not code seg\n"L]; RETURN; }; notcodebound _ notcodebound OR innards.sgb[codeseg].file ~= BcdDefs.FTSelf; }; }; mti _ mti + (WITH m: innards.mtb[mti] SELECT FROM direct => SIZE[BcdDefs.MTRecord[direct]] + m.length*SIZE[BcdDefs.Link], indirect => SIZE[BcdDefs.MTRecord[indirect]], multiple => SIZE[BcdDefs.MTRecord[multiple]], ENDCASE => ERROR); IF LOOPHOLE[mti, CARDINAL] > LOOPHOLE[innards.bcd.mtLimit, CARDINAL] THEN { CWF.WF0["Garbage Module.\n"L]; RETURN; }; ENDLOOP; }; PrintConfigDepends: PROC[innards: ProcBcds.Innards, procDep: ProcBcds.ProcDep,uns: UNSPECIFIED, notcodebound, stopnesting: BOOL] = { <> <> <> <> <> cti: BcdDefs.CTIndex _ FIRST[BcdDefs.CTIndex]; modname: LONG STRING _ Subr.AllocateString[100]; filename: LONG STRING _ Subr.AllocateString[100]; topcti: BcdDefs.CTIndex; ok: BOOL; {ENABLE UNWIND => {Subr.FreeString[modname]; Subr.FreeString[filename]}; UNTIL cti = innards.bcd.ctLimit DO ok _ FALSE; topcti _ innards.ctb[cti].config; -- first level parent WHILE topcti ~= BcdDefs.CTNull AND innards.ctb[topcti].file = BcdDefs.FTSelf DO topcti _ innards.ctb[topcti].config; ENDLOOP; IF topcti = BcdDefs.CTNull OR innards.ctb[topcti].config = BcdDefs.CTNull THEN ok _ TRUE; IF ok AND innards.ctb[cti].file ~= BcdDefs.FTSelf THEN { PutName[innards, innards.ctb[cti].name, modname]; PrintFileName[innards, innards.ctb[cti].file, filename]; procDep[ IF notcodebound THEN otherdepends ELSE canignore, modname, filename, innards.ftb[innards.ctb[cti].file].version, uns]; }; cti _ cti + innards.ctb[cti].nControls + SIZE[BcdDefs.CTRecord]; IF LOOPHOLE[cti, CARDINAL] > LOOPHOLE[innards.bcd.ctLimit, CARDINAL] THEN { CWF.WF0["Garbage Config.\n"L]; GO TO return; }; ENDLOOP; ProcessModuleTable[innards, procDep, uns, notcodebound]; EXITS return => {}; }; -- of ENABLE UNWIND Subr.FreeString[modname]; Subr.FreeString[filename]; }; ProcessModuleTable: PROC [innards: ProcBcds.Innards, procDep: ProcBcds.ProcDep, uns: UNSPECIFIED, notcodebound: BOOL] = { symseg, codeseg: BcdDefs.SGIndex; mti: BcdDefs.MTIndex _ FIRST[BcdDefs.MTIndex]; modname: LONG STRING _ Subr.AllocateString[100]; filename: LONG STRING _ Subr.AllocateString[100]; cti: BcdDefs.CTIndex; {ENABLE UNWIND => {Subr.FreeString[modname]; Subr.FreeString[filename]}; UNTIL mti = innards.bcd.mtLimit DO cti _ innards.mtb[mti].config; WHILE innards.ctb[cti].file = BcdDefs.FTSelf DO IF innards.ctb[cti].config = BcdDefs.CTNull THEN EXIT; cti _ innards.ctb[cti].config; ENDLOOP; IF innards.ctb[cti].config = BcdDefs.CTNull THEN { symseg _ innards.mtb[mti].sseg; IF innards.sgb[symseg].class ~= symbols THEN { CWF.WF0["Error - not symseg\n"L]; GO TO return; }; IF innards.sgb[symseg].file ~= BcdDefs.FTSelf AND innards.sgb[symseg].file ~= BcdDefs.FTNull THEN { PrintFileName[innards, innards.sgb[symseg].file, filename]; PutName[innards, innards.mtb[mti].name,modname]; IF NOT LongString.EquivalentString[filename, modname] THEN { symfilevers: TimeStamp.Stamp; symfilevers _ innards.ftb[innards.sgb[symseg].file].version; procDep[symbolsfile, modname, filename, symfilevers, uns]; }; }; IF innards.mtb[mti].file ~= BcdDefs.FTSelf AND innards.mtb[mti].file ~= BcdDefs.FTNull THEN { codeseg _ innards.mtb[mti].code.sgi; IF innards.sgb[codeseg].class ~= code THEN { CWF.WF0["Error - not code seg\n"L]; GO TO return; }; PutName[innards, innards.mtb[mti].name, modname]; PrintFileName[innards, innards.mtb[mti].file, filename]; procDep[IF notcodebound THEN otherdepends ELSE canignore, modname,filename, innards.ftb[innards.mtb[mti].file].version, uns]; }; }; mti _ mti + (WITH m: innards.mtb[mti] SELECT FROM direct => SIZE[BcdDefs.MTRecord[direct]] + m.length*SIZE[BcdDefs.Link], indirect => SIZE[BcdDefs.MTRecord[indirect]], multiple => SIZE[BcdDefs.MTRecord[multiple]], ENDCASE => ERROR); IF LOOPHOLE[mti, CARDINAL] > LOOPHOLE[innards.bcd.mtLimit, CARDINAL] THEN { CWF.WF0["Garbage Module.\n"L]; GO TO return; }; ENDLOOP; EXITS return => {}; }; -- of ENABLE UNWIND Subr.FreeString[modname]; Subr.FreeString[filename]; }; IsRealTime: PUBLIC PROC[stamp: LONG CARDINAL] RETURNS[isrealtime: BOOL] = { <> <> time: LONG CARDINAL _ Time.Current[]; RETURN[time >= stamp AND stamp >= time - 30000000]; }; PutName: PROC [innards: ProcBcds.Innards, n: BcdDefs.NameRecord, stemp: LONG STRING] = { i: INTEGER; str: LONG STRING _ Subr.AllocateString[100]; ssd: LongString.SubStringDescriptor _ [base: @innards.ssb.string, offset: n, length: MIN[innards.ssb.size[n], 100]]; {ENABLE UNWIND => {Subr.FreeString[str]}; <> LongString.AppendSubString[str, @ssd]; i _ IF str.length > 0 THEN str.length - 1 ELSE 0; WHILE i >= 0 DO IF str[i] = '> OR str[i] = '/ THEN EXIT; i _ i - 1; ENDLOOP; IF i >= 0 THEN Subr.SubStrCopy[stemp, str, i+1] ELSE Subr.strcpy[stemp, str]; }; -- of ENABLE UNWIND Subr.FreeString[str]; }; PrintFileName: PROC [innards: ProcBcds.Innards, fti: BcdDefs.FTIndex, stemp: LONG STRING] = { <> SELECT fti FROM BcdDefs.FTNull => { CWF.SWF0[stemp, "(null)"L]; ERROR; }; BcdDefs.FTSelf => { CWF.SWF0[stemp, "(self)"L]; ERROR; }; ENDCASE => { PutName[innards, innards.ftb[fti].name, stemp]; IF NOT Subr.Any[stemp, '.] THEN LongString.AppendString[stemp, ".bcd"L]; }; RETURN }; }.