-- ListBcd.Mesa -- Last edited by Lewis on 14-Jan-81 16:04:17 -- Last edited by Sweet on 17-Feb-81 12:23:01 -- Last edited by Satterthwaite on September 20, 1982 1:36 pm DIRECTORY BcdDefs: TYPE USING [ Base, BCD, Link, CTIndex, CTNull, CTRecord, EXPIndex, EXPRecord, EVIndex, EVNull, EVRecord, FPIndex, FPRecord, FTIndex, FTNull, FTRecord, FTSelf, IMPIndex, IMPRecord, LFIndex, LFNull, MTIndex, MTRecord, Namee, NameRecord, NTIndex, NTNull, NTRecord, NullName, NullLink, RFIndex, RFNull, SGIndex, SGNull, SGRecord, SpaceID, SPIndex, SPRecord, TFIndex, TFNull, TYPNull, VersionID, VersionStamp], BcdOps: TYPE USING [BcdBase, MTHandle, NameString], CommanderOps: TYPE USING [AddCommand, CommandBlockHandle], Environment: TYPE USING [PageCount, PageNumber, wordsPerPage], FileSegment: TYPE USING [Pages], ListerDefs: TYPE USING [ Indent, MapPages, PrintRTBcd, WriteChar, WriteDecimal, WriteOctal, WriteString, WriteVersionId], OSMiscOps: TYPE USING [FileError, FindFile], OutputDefs: TYPE USING [ CloseOutput, OpenOutput, PutChar, PutCR, PutDecimal, PutLongSubString, PutOctal, PutString, PutTime], RTBcd: TYPE USING [RTBase], Space: TYPE USING [Error, Handle, LongPointer, Delete], Strings: TYPE USING [AppendString, SubStringDescriptor], Time: TYPE USING [Append, Unpack]; ListBcd: PROGRAM IMPORTS CommanderOps, ListerDefs, OSMiscOps, OutputDefs, Space, Strings, Time = { OPEN OutputDefs, BcdDefs; bcdSpace: Space.Handle; bcd: BcdOps.BcdBase; tb: BcdDefs.Base; ssb: BcdOps.NameString; evb: BcdDefs.Base; spb: BcdDefs.Base; fpb: BcdDefs.Base; ctb: BcdDefs.Base; mtb: BcdDefs.Base; lfb: BcdDefs.Base; tfb: BcdDefs.Base; rfb: BcdDefs.Base; itb: BcdDefs.Base; etb: BcdDefs.Base; sgb: BcdDefs.Base; ftb: BcdDefs.Base; ntb: BcdDefs.Base; rtHeader: RTBcd.RTBase; InstallBcd: PROC [seg: FileSegment.Pages] = { DO bcdSpace ← ListerDefs.MapPages[seg]; bcd ← bcdSpace.LongPointer; IF bcd.nPages <= seg.span.pages THEN EXIT; seg.span.pages ← bcd.nPages; Space.Delete[bcdSpace]; ENDLOOP; tb ← LOOPHOLE[bcd]; ssb ← LOOPHOLE[bcd + bcd.ssOffset]; ctb ← tb + bcd.ctOffset; mtb ← tb + bcd.mtOffset; IF bcd.extended THEN { lfb ← tb + bcd.lfOffset; tfb ← tb + bcd.tfOffset; rfb ← tb + bcd.rfOffset}; itb ← tb + bcd.impOffset; etb ← tb + bcd.expOffset; sgb ← tb + bcd.sgOffset; ftb ← tb + bcd.ftOffset; ntb ← tb + bcd.ntOffset; evb ← tb + bcd.evOffset; spb ← tb + bcd.spOffset; fpb ← tb + bcd.fpOffset; rtHeader ← IF bcd.extended AND bcd.rtPages.pages # 0 THEN LOOPHOLE[bcd + bcd.rtPages.relPageBase*Environment.wordsPerPage] ELSE NIL}; UnstallBcd: PROC [seg: FileSegment.Pages] = { Space.Delete[bcdSpace]}; WriteBcdID: PROC [name: STRING, bcd: BcdOps.BcdBase] = { PutString[name]; PutString[", version "L]; ListerDefs.WriteVersionId[bcd.version]; IF bcd.source # NullName THEN { PutString["\n source "L]; PutName[bcd.source]; PutString[" of "L]; PutTime[[bcd.sourceVersion.time]]}; IF bcd.versionIdent # BcdDefs.VersionID THEN { PutString["\n (obsolete) version ID = "L]; PutDecimal[bcd.versionIdent]}; PutString["\n creator "L]; ListerDefs.WriteVersionId[bcd.creator]; PutString["\n\n"L]}; PrintStamps: PROC = { PutString["Imports:\n\n"L]; FOR iti: IMPIndex ← FIRST[IMPIndex], iti + SIZE[IMPRecord] UNTIL iti = bcd.impLimit DO OPEN ii: itb[iti]; IF LOOPHOLE[iti, CARDINAL] > LOOPHOLE[bcd.impLimit, CARDINAL] THEN GO TO Bogus; IF ii.namedInstance THEN {PutInstanceName[[import[iti]]]; PutString[": "L]}; PutName[ii.name]; PutFileStamp[ii.file, ii.name]; REPEAT Bogus => PrintGarbage[]; ENDLOOP; PutCR[]; PutString["Exports:\n\n"L]; FOR eti: EXPIndex ← FIRST[EXPIndex], eti + etb[eti].size + SIZE[EXPRecord] UNTIL eti = bcd.expLimit DO OPEN ee: etb[eti]; IF LOOPHOLE[eti, CARDINAL] > LOOPHOLE[bcd.expLimit, CARDINAL] THEN GO TO Bogus; IF ee.namedInstance THEN {PutInstanceName[[export[eti]]]; PutString[": "L]}; PutName[ee.name]; PutFileStamp[ee.file, ee.name]; REPEAT Bogus => PrintGarbage[]; ENDLOOP; PutString["\nModules:\n\n"L]; FOR mti: MTIndex ← FIRST[MTIndex], mti + MTSize[mti] UNTIL mti = bcd.mtLimit DO OPEN mm: mtb[mti]; IF LOOPHOLE[mti, CARDINAL] > LOOPHOLE[bcd.mtLimit, CARDINAL] THEN GO TO Bogus; IF mm.namedInstance THEN {PutInstanceName[[module[mti]]]; PutString[": "L]}; PutName[mm.name]; PutFileStamp[mm.file, mm.name]; REPEAT Bogus => PrintGarbage[]; ENDLOOP}; PutFileStamp: PROC [fti: FTIndex, mName: NameRecord] = { OPEN ftb[fti]; SELECT fti FROM FTNull => PutString["(null)"L]; FTSelf => PutString["(self)"L]; ENDCASE => { IF name # mName THEN {PutString[", file: "L]; PutName[name]}; PutString[", version: "L]; ListerDefs.WriteVersionId[version]}; PutCR[]}; PrintBcd: PROC = { PrintHeader[]; PrintConfigs[]; PrintImports[]; PrintExports[]; PrintExpVars[]; PrintModules[]; PrintFiles[]; PrintFramePacks[]; PrintSpaces[]}; PrintHeader: PROC = { PutString["Configurations: "L]; PutDecimal[bcd.nConfigs]; PutString[", Modules: "L]; PutDecimal[bcd.nModules]; PutString[", Imports: "L]; PutDecimal[bcd.nImports]; PutString[", Exports: "L]; PutDecimal[bcd.nExports]; PutString[", Dummy: "L]; PutDecimal[bcd.firstdummy]; PutString[", #Dummies: "L]; PutDecimal[bcd.nDummies]; PutCR[]; IF ~bcd.definitions THEN PutChar['~]; PutString["definitions, "L]; IF ~bcd.repackaged THEN PutChar['~]; PutString["repackaged, "L]; IF ~bcd.typeExported THEN PutChar['~]; PutString["type exported, "L]; IF ~bcd.tableCompiled THEN PutChar['~]; PutString["table compiled, "L]; IF ~bcd.versions THEN PutChar['~]; PutString["versions, "L]; IF ~bcd.extended THEN PutChar['~]; PutString["extended\n\n"L]}; PrintConfigs: PROC = { cti: CTIndex ← FIRST[CTIndex]; PutString["Configurations"L]; PrintIndex[bcd.ctOffset]; PutString[":\n"L]; UNTIL cti = bcd.ctLimit DO PrintConfig[cti]; cti ← cti + SIZE[CTRecord] + ctb[cti].nControls; IF LOOPHOLE[cti, CARDINAL] > LOOPHOLE[bcd.ctLimit, CARDINAL] THEN GO TO Bogus; REPEAT Bogus => PrintGarbage[]; ENDLOOP; PutCR[]}; PrintConfig: PROC [cti: CTIndex] = { OPEN ctb[cti]; Tab[2]; PutName[name]; PrintIndex[cti]; IF namedInstance THEN { PutString[", instance name: "L]; PutInstanceName[[config[cti]]]}; PutString[", file: "L]; PrintFileName[file]; PrintIndex[file]; IF config # CTNull THEN { PutString[", parent: "L]; PutName[ctb[config].name]; PrintIndex[config]}; PutString[", #controls: "L]; PutDecimal[nControls]; IF nControls # 0 THEN { PutString[", controls:"L]; FOR i: CARDINAL IN [0..nControls) DO IF i MOD 6 = 0 THEN Tab[6] ELSE PutString[", "L]; WITH c: controls[i] SELECT FROM module => PutName[mtb[c.mti].name]; config => {PutName[ctb[c.cti].name]; PutChar['*]}; ENDCASE => ERROR; PrintIndex[controls[i]]; ENDLOOP}; PutCR[]}; PrintImports: PROC = { iti: IMPIndex ← FIRST[IMPIndex]; PutString["Imports"L]; PrintIndex[bcd.impOffset]; PutChar[':]; PutCR[]; UNTIL iti = bcd.impLimit DO PrintImport[iti]; iti ← iti + SIZE[IMPRecord]; IF LOOPHOLE[iti, CARDINAL] > LOOPHOLE[bcd.impLimit, CARDINAL] THEN GO TO Bogus; REPEAT Bogus => PrintGarbage[]; ENDLOOP; PutCR[]; PutCR[]}; PrintImport: PROC [iti: IMPIndex] = { OPEN itb[iti]; Tab[2]; PutName[name]; PrintIndex[iti]; IF port = module THEN PutString[" (module)"L]; IF namedInstance THEN { PutString[", instance name: "L]; PutInstanceName[[import[iti]]]}; PutString[", file: "L]; PrintFileName[file]; PrintIndex[file]; PutString[", gfi: "L]; PutDecimal[gfi]; PutString[", ngfi: "L]; PutDecimal[ngfi]}; PrintExports: PROC = { eti: EXPIndex ← FIRST[EXPIndex]; PutString["Exports"L]; PrintIndex[bcd.expOffset]; PutChar[':]; PutCR[]; UNTIL eti = bcd.expLimit DO PrintExport[eti]; eti ← eti + etb[eti].size + SIZE[EXPRecord]; IF LOOPHOLE[eti, CARDINAL] > LOOPHOLE[bcd.expLimit, CARDINAL] THEN GO TO Bogus; REPEAT Bogus => PrintGarbage[]; ENDLOOP; IF DumpLinks # all THEN PutCR[]; PutCR[]}; PrintExport: PROC [eti: EXPIndex] = { OPEN etb[eti]; Tab[2]; PutName[name]; PrintIndex[eti]; IF port = module THEN PutString[" (module)"L]; IF namedInstance THEN { PutString[", instance name: "L]; PutInstanceName[[export[eti]]]}; PutString[", file: "L]; PrintFileName[file]; PrintIndex[file]; PutString[", "L]; IF ~typeExported THEN PutChar['~]; PutString["typeExported"L]; PutString[", #links: "L]; PutDecimal[size]; IF DumpLinks = all THEN { PutString[", links:"L]; FOR i: CARDINAL IN [0..size) DO IF i MOD 7 = 0 THEN Tab[4] ELSE PutChar[' ]; PrintControlLink[links[i]]; IF i + 1 # size THEN PutChar[',]; ENDLOOP}; IF DumpLinks = all THEN PutCR[]}; PrintExpVars: PROC = { evi: EVIndex ← FIRST[EVIndex]; evLimit: EVIndex = bcd.evLimit; PutString["Exported variables:\n"L]; UNTIL evi = evLimit DO PrintExpVar[evi]; evi ← evi + evb[evi].length + SIZE[EVRecord]; ENDLOOP; PutCR[]}; PrintExpVar: PROC [evi: EVIndex] = { OPEN evb[evi]; Tab[2]; PrintIndex[evi]; PutString[", #offsets: "L]; PutDecimal[length]; PutString[", offsets:"L]; FOR i: CARDINAL IN [1..length] DO IF i MOD 8 = 1 THEN Tab[4] ELSE PutChar[' ]; PutOctal[offsets[i]]; IF i # length THEN PutChar[',]; ENDLOOP; PutCR[]}; PrintSpaces: PROC = { spi: SPIndex ← FIRST[SPIndex]; spLimit: SPIndex = bcd.spLimit; PutString["Spaces:\n"L]; UNTIL spi = spLimit DO PrintSpace[spi]; spi ← spi + SIZE[SPRecord] + spb[spi].length*SIZE[SpaceID]; ENDLOOP; PutCR[]}; PrintSpace: PROC [spi: SPIndex] = { OPEN spb[spi]; Tab[2]; PrintIndex[spi]; PutString[", segment: "L]; PrintIndex[seg]; PutString[", #code packs: "L]; PutDecimal[length]; IF length # 0 THEN PutString[", code packs: "L]; FOR i: CARDINAL IN [0..length) DO Tab[4]; PutString[" code pack "L]; PutName[spaces[i].name]; PutString[", "L]; IF ~spaces[i].resident THEN PutChar['~]; PutString["resident, offset: "L]; PutOctal[spaces[i].offset]; PutString[", pages: "L]; PutDecimal[spaces[i].pages]; PutCR[]; ENDLOOP}; PrintModules: PROC = { mti: MTIndex ← FIRST[MTIndex]; PutString["Modules"L]; PrintIndex[bcd.mtOffset]; PutString[":\n"L]; UNTIL mti = bcd.mtLimit DO PrintModule[@mtb[mti], mti]; mti ← mti + MTSize[mti]; IF LOOPHOLE[mti, CARDINAL] > LOOPHOLE[bcd.mtLimit, CARDINAL] THEN GO TO Bogus; REPEAT Bogus => PrintGarbage[]; ENDLOOP; PutCR[]}; PrintModule: PROC [mth: BcdOps.MTHandle, mti: MTIndex] = { OPEN mth; Tab[2]; PutName[name]; PrintIndex[mti]; IF namedInstance THEN { PutString["instance name: "L]; PutInstanceName[[module[mti]]]}; PutString[", file: "L]; PrintFileName[file]; PrintIndex[file]; IF config # CTNull THEN { PutString[", config: "L]; PutName[ctb[config].name]; PrintIndex[config]}; Tab[4]; IF tableCompiled THEN PutString["table compiled, "L] ELSE { PutSwitch: PROC [sw: CHAR, value: BOOL] = { IF ~value THEN PutChar['-]; PutChar[sw]}; PutString["switches: "L]; PutSwitch['b, boundsChecks]; PutSwitch['c, long]; PutSwitch['j, crossJumped]; PutSwitch['l, linkLoc = code]; PutSwitch['n, nilChecks]; PutSwitch['s, ~initial]; PutString[", "L]}; IF ~packageable THEN PutChar['~]; PutString["packageable, "L]; IF residentFrame THEN PutString["resident frame, "L]; Tab[4]; PutString["framesize: "L]; PutDecimal[framesize]; PutString[", gfi: "L]; PutDecimal[gfi]; PutString[", ngfi: "L]; PutDecimal[ngfi]; PutString[", links: "L]; PutString[IF linkLoc = frame THEN "frame"L ELSE "code"L]; Tab[4]; PutString["code: "L]; PrintSegment[code.sgi]; PutString[", offset: "L]; PutOctal[code.offset]; PutString[", length: "L]; PutOctal[code.length]; IF code.linkspace THEN PutString[", link space"L]; IF code.packed THEN PutString[", packed"L]; Tab[4]; PutString["symbols: "L]; PrintSegment[sseg]; IF variables # EVNull THEN { Tab[4]; PutString["exported variables: "L]; PrintIndex[variables]}; WITH mm: mth↑ SELECT FROM direct => { Tab[4]; PutString["#links: "L]; PutDecimal[mm.length]; IF DumpLinks = all THEN { PutString[", links:"L]; FOR i: CARDINAL IN [0..mm.length) DO IF i MOD 7 = 0 THEN Tab[6] ELSE PutChar[' ]; PrintControlLink[mm.frag[i]]; IF i + 1 # mm.length THEN PutChar[',]; ENDLOOP}}; indirect => {Tab[4]; PrintLinks[mm.links]}; multiple => { Tab[4]; PrintLinks[mm.links]; Tab[4]; PrintTypes[mm.types]; IF mm.frameRefs THEN { Tab[5]; PutString["frame type: "L]; PutDecimal[mm.frameType]}; Tab[4]; PrintRefLits[mm.refLiterals]}; ENDCASE; PutCR[]}; MTSize: PROC [mti: MTIndex] RETURNS [NAT] = { RETURN [WITH m: mtb[mti] SELECT FROM direct => SIZE[direct MTRecord] + m.length, indirect => SIZE[indirect MTRecord], multiple => SIZE[multiple MTRecord], ENDCASE => ERROR]}; PrintLinks: PROC [lfi: LFIndex] = { PutString["#links: "L]; IF lfi = LFNull THEN PutString["none"L] ELSE { PutDecimal[lfb[lfi].length]; IF DumpLinks = all THEN { PutString[", links:"L]; FOR i: CARDINAL IN [0..lfb[lfi].length) DO IF i MOD 7 = 0 THEN Tab[6] ELSE PutChar[' ]; PrintControlLink[lfb[lfi].frag[i]]; IF i + 1 # lfb[lfi].length THEN PutChar[',]; ENDLOOP}}}; PrintTypes: PROC [tfi: TFIndex] = { PutString["#types: "L]; IF tfi = TFNull THEN PutString["none"L] ELSE { PutDecimal[tfb[tfi].length]; PutString[", offset: "L]; PutDecimal[tfb[tfi].offset]; IF DumpLinks # none THEN { PutString[", indices:"L]; FOR i: CARDINAL IN [0..tfb[tfi].length) DO IF i MOD 7 = 0 THEN Tab[6] ELSE PutChar[' ]; PrintRTIndex[tfb[tfi].frag[i]]; IF i + 1 # tfb[tfi].length THEN PutChar[',]; ENDLOOP}}}; PrintRefLits: PROC [rfi: RFIndex] = { PutString["#ref lits: "L]; IF rfi = RFNull THEN PutString["none"L] ELSE { PutDecimal[rfb[rfi].length]; PutString[", offset: "L]; PutDecimal[rfb[rfi].offset]; IF DumpLinks # none THEN { PutString[", indices:"L]; FOR i: CARDINAL IN [0..rfb[rfi].length) DO IF i MOD 7 = 0 THEN Tab[6] ELSE PutChar[' ]; PrintRTIndex[rfb[rfi].frag[i]]; IF i + 1 # rfb[rfi].length THEN PutChar[',]; ENDLOOP}}}; PrintFramePacks: PROC = { fpi: FPIndex ← FIRST[FPIndex]; fpLimit: FPIndex = bcd.fpLimit; PutString["Frame Packs:\n"L]; UNTIL fpi = fpLimit DO PrintFramePack[fpi]; fpi ← fpi + SIZE[FPRecord] + fpb[fpi].length*SIZE[MTIndex]; ENDLOOP; PutCR[]}; PrintFramePack: PROC [fpi: FPIndex] = { OPEN fpb[fpi]; Tab[2]; PutName[name]; PrintIndex[fpi]; PutString[", #modules: "L]; PutDecimal[length]; PutString[", modules:\n"L]; FOR i: CARDINAL IN [0..length) DO IF i MOD 4 = 0 THEN Tab[4] ELSE PutChar[' ]; PutName[mtb[modules[i]].name]; PrintIndex[modules[i]]; IF i # length - 1 THEN PutChar[',]; ENDLOOP; PutCR[]}; PrintSegment: PROC [sgi: SGIndex] = { IF sgi = BcdDefs.SGNull THEN PutString["(null)"L] ELSE { PrintFileName[sgb[sgi].file]; PutString[" [base: "L]; PutDecimal[sgb[sgi].base]; PutString[", pages: "L]; PutDecimal[sgb[sgi].pages]; IF sgb[sgi].extraPages # 0 THEN {PutChar['+]; PutDecimal[sgb[sgi].extraPages]}; PutChar[']]}}; PrintFiles: PROC = { fti: FTIndex ← FIRST[FTIndex]; PutString["Files"L]; PrintIndex[bcd.ftOffset]; PutString[":\n"L]; UNTIL fti = bcd.ftLimit DO PrintFile[fti]; fti ← fti + SIZE[FTRecord]; IF LOOPHOLE[fti, CARDINAL] > LOOPHOLE[bcd.ftLimit, CARDINAL] THEN GO TO Bogus; REPEAT Bogus => PrintGarbage[]; ENDLOOP; PutCR[]; PutCR[]}; PrintFile: PROC [fti: FTIndex] = { OPEN ftb[fti]; Tab[2]; SELECT fti FROM FTNull => PutString["(null)"L]; FTSelf => PutString["(self)"L]; ENDCASE => { PutName[name]; PrintIndex[fti]; PutString[", version: "L]; ListerDefs.WriteVersionId[version]}}; PrintRTBcdExt: PROC = { PrintHeader[]; PrintConfigs[]; PrintModules[]; IF rtHeader = NIL THEN PutString["No RT Extensions"L] ELSE { ListerDefs.PrintRTBcd[rtHeader]; PrintSymbolSegments[]}; PutCR[]; PutCR[]}; PrintSymbolSegments: PROC = { sgi: SGIndex ← FIRST[SGIndex]; PutString["Symbol Segments\n"L]; UNTIL sgi = bcd.sgLimit DO IF sgb[sgi].class = symbols THEN { Tab[1]; PrintIndex[sgi]; PutChar[' ]; PrintSegment[sgi]}; sgi ← sgi + SIZE[SGRecord]; ENDLOOP; PutCR[]}; -- Utility Prints PrintControlLink: PROC [link: Link] = { SELECT TRUE FROM (link = BcdDefs.NullLink) => PutString["(null link)"L]; link.proc => { PutString["proc["L]; PutDecimal[link.gfi]; PutChar[',]; PutDecimal[link.ep]; PutChar[']]}; link.type => { PutString["type["L]; IF link.typeID = BcdDefs.TYPNull THEN PutString["null"L] ELSE PutDecimal[LOOPHOLE[link.typeID]]; PutChar[']]}; ENDCASE => { PutString["var["L]; PutDecimal[link.vgfi]; PutChar[',]; PutDecimal[link.var]; PutChar[']]}}; PrintRTIndex: PROC [index: NAT] = { PutChar['[]; PutDecimal[index]; PutChar[']]}; PrintFileName: PROC [fti: FTIndex] = { SELECT fti FROM FTNull => PutString["(null)"L]; FTSelf => PutString["(self)"L]; ENDCASE => PutName[ftb[fti].name]}; PrintIndex: PROC [index: UNSPECIFIED] = { PutString[" ["L]; PutDecimal[index]; PutChar[']]}; PrintGarbage: PROC = { Tab[2]; PutString["? Looks like garbage ...\n"L]}; PrintAnonName: PROC = {PutString[" (anon) "L]}; -- Utility Puts PutName: PROC [n: NameRecord] = { ssd: Strings.SubStringDescriptor ← [base: @ssb.string, offset: n, length: MIN[ssb.size[n], 100]]; PutLongSubString[@ssd]}; Tab: PROC [n: CARDINAL] = {ListerDefs.Indent[n]}; PutInstanceName: PROC [n: Namee] = { FindName: PROC [ntb: Base, nti: NTIndex] RETURNS [stop: BOOLEAN] = { RETURN [ntb[nti].item = n]}; nti: NTIndex = EnumerateNameTable[FindName]; IF nti = NTNull THEN PrintAnonName[] ELSE PutName[ntb[nti].name]}; EnumerateNameTable: PROC [ proc: PROC [Base, NTIndex] RETURNS [BOOLEAN]] RETURNS [nti: NTIndex] = { FOR nti ← FIRST[NTIndex], nti + SIZE[NTRecord] UNTIL nti = bcd.ntLimit DO IF proc[ntb, nti] THEN RETURN[nti]; ENDLOOP; RETURN [NTNull]}; Version: PROC [root: STRING] = { bcdfile: STRING ← [40]; seg: FileSegment.Pages; Strings.AppendString[bcdfile, root]; FOR i: CARDINAL IN [0..bcdfile.length) DO IF bcdfile[i] = '. THEN EXIT; REPEAT FINISHED => Strings.AppendString[bcdfile, ".bcd"L]; ENDLOOP; seg ← [ file: OSMiscOps.FindFile[bcdfile ! OSMiscOps.FileError => GO TO NoFile], span: [base: 1, pages: 10]]; InstallBcd[seg]; ListerDefs.WriteChar['\n]; ListerDefs.WriteString[bcdfile]; ListerDefs.WriteString[", version "L]; WriteVersion[bcd.version]; IF bcd.source # BcdDefs.NullName THEN { ListerDefs.WriteString["\n source "L]; WriteName[bcd.source]; ListerDefs.WriteString[" of "L]; WriteTime[bcd.sourceVersion.time]}; IF bcd.versionIdent # VersionID THEN { ListerDefs.WriteString["\n (obsolete) version ID = "L]; ListerDefs.WriteDecimal[bcd.versionIdent]}; ListerDefs.WriteString["\n creator "L]; WriteVersion[bcd.creator]; ListerDefs.WriteChar['\n]; UnstallBcd[seg]; EXITS NoFile => ListerDefs.WriteString["File not found"L]}; WriteVersion: PROC [stamp: BcdDefs.VersionStamp] = { StampWords: CARDINAL = SIZE[BcdDefs.VersionStamp]; str: PACKED ARRAY [0..4*StampWords) OF [0..16) = LOOPHOLE[stamp]; digit: STRING = "0123456789abcdef"L; ListerDefs.WriteChar['"]; FOR i: CARDINAL IN [0..4*StampWords) DO ListerDefs.WriteChar[digit[str[i]]] ENDLOOP; ListerDefs.WriteString["\" ("L]; WriteTime[stamp.time]; ListerDefs.WriteString[", "]; WriteMachine[stamp]}; WriteTime: PROC [time: LONG CARDINAL] = { t: STRING ← [20]; Time.Append[t, Time.Unpack[LOOPHOLE[time]]]; ListerDefs.WriteString[t]}; WriteName: PROC [n: BcdDefs.NameRecord] = { ssd: Strings.SubStringDescriptor ← [base: @ssb.string, offset: n, length: MIN[ssb.size[n], 100]]; FOR i: CARDINAL IN [ssd.offset .. ssd.offset+ssd.length) DO ListerDefs.WriteChar[ssd.base[i]]; ENDLOOP}; WriteMachine: PROC [version: BcdDefs.VersionStamp] = { ListerDefs.WriteOctal[version.net]; ListerDefs.WriteChar['#]; ListerDefs.WriteOctal[version.host]; ListerDefs.WriteChar['#]}; BcdProc: PROC [ root: STRING, base: Environment.PageNumber, pages: Environment.PageCount, proc: PROC] = { bcdfile: STRING ← [40]; seg: FileSegment.Pages; Strings.AppendString[bcdfile, root]; FOR i: CARDINAL IN [0..bcdfile.length) DO IF bcdfile[i] = '. THEN EXIT; REPEAT FINISHED => Strings.AppendString[bcdfile, ".bcd"L]; ENDLOOP; seg ← [ file: OSMiscOps.FindFile[bcdfile, ! OSMiscOps.FileError => GO TO NoFile], span: [base: base, pages: pages]]; InstallBcd[seg]; OpenOutput[root, ".bl"L]; WriteBcdID[bcdfile, bcd]; proc[]; CloseOutput[]; UnstallBcd[seg]; EXITS NoFile => ListerDefs.WriteString["File not found"L]}; Stamps: PROC [root: STRING] = { BcdProc[root, 1, 10, PrintStamps]}; Files: PROC [root: STRING] = { BcdProc[root, 1, 10, PrintFiles]}; Bcd: PROC [root: STRING] = { BcdProc[root, 1, 10, PrintBcd]}; BcdLinks: PROC [root: STRING] = { DumpLinks ← all; Bcd[root]; DumpLinks ← none}; BcdSegment: PROC [ root: STRING, base: Environment.PageNumber, pages: Environment.PageCount, links: BOOLEAN] = { DumpLinks ← IF links THEN all ELSE none; BEGIN BcdProc[root, base, pages, PrintBcd ! Space.Error => GO TO BadSegment]; EXITS BadSegment => ListerDefs.WriteString["Bad Segment"L]; END; DumpLinks ← none}; RTBcdExt: PROC [root: STRING] = { DumpLinks ← rt; BcdProc[root, 1, 10, PrintRTBcdExt]; DumpLinks ← none}; DumpLinks: {none, rt, all} ← none; Init: PROC = { command: CommanderOps.CommandBlockHandle; command ← CommanderOps.AddCommand["Bcd", LOOPHOLE[Bcd], 1]; command.params[0] ← [type: string, prompt: "Filename"]; command ← CommanderOps.AddCommand["BcdLinks", LOOPHOLE[BcdLinks], 1]; command.params[0] ← [type: string, prompt: "Filename"]; command ← CommanderOps.AddCommand["Version", LOOPHOLE[Version], 1]; command.params[0] ← [type: string, prompt: "Filename"]; command ← CommanderOps.AddCommand["Stamps", LOOPHOLE[Stamps], 1]; command.params[0] ← [type: string, prompt: "Filename"]; command ← CommanderOps.AddCommand["Files", LOOPHOLE[Files], 1]; command.params[0] ← [type: string, prompt: "Filename"]; command ← CommanderOps.AddCommand["BcdSegment", LOOPHOLE[BcdSegment], 4]; command.params[0] ← [type: string, prompt: "Filename"]; command.params[1] ← [type: numeric, prompt: "Base"]; command.params[2] ← [type: numeric, prompt: "Pages"]; command.params[3] ← [type: boolean, prompt: "Links"]; command ← CommanderOps.AddCommand["RTBcd", LOOPHOLE[RTBcdExt], 1]; command.params[0] ← [type: string, prompt: "Filename"]}; Init[]; }.