-- ListUnbound.Mesa -- Edited by Sweet on July 8, 1980 9:42 AM -- Edited by Bruce on 13-Jan-81 11:06:19 -- Edited by Satterthwaite on September 20, 1982 1:42 pm DIRECTORY BcdDefs: TYPE USING [ Base, BCD, EXPIndex, EXPRecord, FTIndex, FTNull, FTSelf, NameRecord, NullName], BcdOps: TYPE USING [BcdBase, NameString], CommanderOps: TYPE USING [AddCommand, CommandBlockHandle], FileSegment: TYPE USING [Pages], ListerDefs: TYPE USING [ IncorrectVersion, Indent, Load, MapPages, MultipleModules, NoCode, NoFGT, NoFile, NoSymbols, PrintSei, SetRoutineSymbols, WriteString, WriteVersionId], OSMiscOps: TYPE USING [FileError, FindFile], OutputDefs: TYPE USING [ CloseOutput, OpenOutput, PutCR, PutString, PutLongSubString], Space: TYPE USING [Handle, Delete, LongPointer], Strings: TYPE USING [AppendString, AppendSubString, SubStringDescriptor], Symbols: TYPE USING [ISEIndex, ISENull], SymbolTable: TYPE USING [Acquire, Base, Release]; ListUnbound: PROGRAM IMPORTS CommanderOps, ListerDefs, Strings, OSMiscOps, OutputDefs, Space, SymbolTable = BEGIN OPEN OutputDefs, BcdDefs; bcdSpace: Space.Handle; bcd: BcdOps.BcdBase; tb: Base; ssb: BcdOps.NameString; evb: Base; spb: Base; ctb: Base; mtb: Base; itb: Base; etb: Base; sgb: Base; ftb: Base; ntb: Base; InstallBcd: PROCEDURE [seg: FileSegment.Pages] = BEGIN DO nPages: CARDINAL; bcdSpace ← ListerDefs.MapPages[seg]; bcd ← bcdSpace.LongPointer; IF (nPages ← bcd.nPages) = seg.span.pages THEN EXIT; seg.span.pages ← nPages; Space.Delete[bcdSpace]; ENDLOOP; tb ← LOOPHOLE[bcd]; ssb ← LOOPHOLE[bcd + bcd.ssOffset]; ctb ← tb + bcd.ctOffset; mtb ← tb + bcd.mtOffset; 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; RETURN END; UnstallBcd: PROCEDURE [seg: FileSegment.Pages] = BEGIN Space.Delete[bcdSpace]; RETURN END; WriteBcdID: PROCEDURE [name: STRING, bcd: BcdOps.BcdBase] = BEGIN PutString[name]; PutString[", version "L]; ListerDefs.WriteVersionId[bcd.version]; IF bcd.source # BcdDefs.NullName THEN BEGIN PutString[", source "L]; PutName[bcd.source] END; PutString["\n creator "L]; ListerDefs.WriteVersionId[bcd.creator]; PutCR[]; PutCR[]; END; PrintUnbound: PROCEDURE = BEGIN eti: EXPIndex ← FIRST[EXPIndex]; UNTIL eti = bcd.expLimit DO CheckExport[ eti ! ListerDefs.NoFile => BEGIN OPEN etb[eti]; PutString["Can't find "L]; PutName[ftb[file].name]; PutCR[]; CONTINUE END; ListerDefs.MultipleModules => BEGIN OPEN etb[eti]; PutString["Bad format for "L]; PutName[ftb[file].name]; PutCR[]; CONTINUE END; ListerDefs.NoSymbols => BEGIN OPEN etb[eti]; PutString["No symbols for "L]; PutName[ftb[file].name]; PutCR[]; CONTINUE END; ListerDefs.IncorrectVersion => BEGIN OPEN etb[eti]; PutString["Wrong version: "L]; PutName[ftb[file].name]; PutCR[]; CONTINUE END]; UnloadSymbols[]; eti ← eti + etb[eti].size + SIZE[EXPRecord]; IF LOOPHOLE[eti, CARDINAL] > LOOPHOLE[bcd.expLimit, CARDINAL] THEN GO TO Bogus; REPEAT Bogus => PrintGarbage[]; ENDLOOP; RETURN END; CheckExport: PUBLIC PROCEDURE [eti: EXPIndex] = BEGIN OPEN etb[eti]; i: CARDINAL; n: CARDINAL ← 0; sei: Symbols.ISEIndex; FOR i IN [0..size) DO IF links[i].gfi = 0 THEN BEGIN IF ~loaded THEN LoadSymbols[file]; sei ← SeiForItem[i]; IF sei = Symbols.ISENull THEN LOOP; IF n = 0 THEN BEGIN PutString["Unbound exports to "L]; PutName[name]; PutString[": "L]; END; IF n MOD 3 = 0 THEN Tab[2] ELSE PutString[", "L]; n ← n + 1; ListerDefs.PrintSei[sei]; END; ENDLOOP; IF n # 0 THEN BEGIN PutCR[]; PutCR[]; END; RETURN END; SeiForItem: PROCEDURE [item: CARDINAL] RETURNS [sei: Symbols.ISEIndex] = BEGIN OPEN symbols; FOR sei ← FirstCtxSe[stHandle.outerCtx], NextSe[sei] UNTIL sei = Symbols.ISENull DO IF seb[sei].idValue = item THEN SELECT LinkMode[ sei] FROM val => IF seb[sei].extended THEN RETURN[Symbols.ISENull] ELSE RETURN; ref => RETURN[sei]; manifest => LOOP; -- constant ENDCASE => RETURN[Symbols.ISENull]; ENDLOOP; ERROR; END; symbols: SymbolTable.Base ← NIL; sseg: FileSegment.Pages; loaded: BOOLEAN ← FALSE; LoadSymbols: PROCEDURE [file: FTIndex] = BEGIN OPEN ListerDefs; s: STRING ← [60]; IF file = FTNull OR file = FTSelf OR symbols # NIL THEN ERROR; GetBcdName[s, ftb[file].name]; [symbols: sseg] ← Load[s ! NoCode, NoFGT => RESUME ]; symbols ← SymbolTable.Acquire[sseg]; SetRoutineSymbols[symbols]; loaded ← TRUE; END; UnloadSymbols: PROCEDURE = BEGIN IF symbols # NIL THEN SymbolTable.Release[symbols]; symbols ← NIL; loaded ← FALSE; END; -- Utility Prints PrintGarbage: PROCEDURE = BEGIN Tab[2]; PutString["? looks like garbage to me ..."]; PutCR[]; RETURN END; GetBcdName: PUBLIC PROCEDURE [s: STRING, n: NameRecord] = BEGIN i: CARDINAL; ssd: Strings.SubStringDescriptor ← [base: @ssb.string, offset: n, length: MIN[ssb.size[n], 100]]; s.length ← 0; Strings.AppendSubString[s, @ssd]; FOR i IN [0..s.length) DO IF s[i] = '. THEN RETURN ENDLOOP; Strings.AppendString[s, ".bcd"L]; RETURN END; -- Utility Puts PutName: PUBLIC PROCEDURE [n: NameRecord] = BEGIN ssd: Strings.SubStringDescriptor ← [base: @ssb.string, offset: n, length: MIN[ssb.size[n], 100]]; PutLongSubString[@ssd]; RETURN END; Tab: PROCEDURE [n: CARDINAL] = BEGIN ListerDefs.Indent[n]; RETURN END; UnboundExports: PROCEDURE [root: STRING] = BEGIN 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; BEGIN seg ← [ file: OSMiscOps.FindFile[bcdfile, ! OSMiscOps.FileError => GO TO NoFile], span: [base: 1, pages: 1]]; InstallBcd[seg]; OpenOutput[root, ".xl"L]; WriteBcdID[bcdfile, bcd]; PrintUnbound[]; CloseOutput[]; UnstallBcd[seg]; EXITS NoFile => ListerDefs.WriteString["File not found"L]; END; RETURN END; Init: PROCEDURE = BEGIN command: CommanderOps.CommandBlockHandle; command ← CommanderOps.AddCommand[ "UnboundExports", LOOPHOLE[UnboundExports], 1]; command.params[0] ← [type: string, prompt: "Bcd name"]; END; Init[]; END....