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: BOOLEANFALSE;
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....