-- ListImpl.Mesa
-- Edited by Sweet on 3-Sep-80 12:36:48
DIRECTORY
AltoDefs: FROM "altodefs",
BcdDefs,
BcdOps USING [NameString],
CommanderDefs USING [AddCommand, CommandBlockHandle],
GPsortDefs USING [CompareProcType, GetProcType, PutProcType, Sort],
IODefs,
ListerDefs,
OutputDefs,
SegmentDefs,
StreamDefs,
String,
Symbols,
SymbolTable USING [Acquire, Base, Release, TableForSegment];
ListImpl: PROGRAM
IMPORTS
CommanderDefs, GPsortDefs, IODefs, ListerDefs, OutputDefs, SegmentDefs,
StreamDefs, String, SymbolTable =
BEGIN OPEN OutputDefs, BcdDefs;
bcd: POINTER TO BCD;
tb: Base;
ssb: BcdOps.NameString;
evb: Base;
spb: Base;
ctb: Base;
mtb: Base;
itb: Base;
etb: Base;
sgb: Base;
ftb: Base;
ntb: Base;
typb: Base;
InstallBcd: PROCEDURE [seg: SegmentDefs.FileSegmentHandle] =
BEGIN OPEN SegmentDefs;
size: CARDINAL;
SwapIn[seg];
bcd ← FileSegmentAddress[seg];
IF (size ← bcd.nPages) # seg.pages THEN
BEGIN
Unlock[seg];
MoveFileSegment[seg, seg.base, size];
SwapIn[seg];
bcd ← FileSegmentAddress[seg];
END;
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;
typb ← tb + bcd.typOffset;
RETURN
END;
UnstallBcd: PROCEDURE [seg: SegmentDefs.FileSegmentHandle] =
BEGIN OPEN SegmentDefs;
IF seg.swappedin THEN Unlock[seg];
SwapOut[seg];
RETURN
END;
ScanExports: PROCEDURE [action: PROC[EXPIndex]] =
BEGIN
eti: EXPIndex ← FIRST[EXPIndex];
UNTIL eti = bcd.expLimit DO
action[eti !
SegmentDefs.FileNameError =>
BEGIN OPEN IODefs, etb[eti];
WriteString["Can't find "L];
WriteName[ftb[file].name];
WriteChar[CR];
CONTINUE
END;
ListerDefs.MultipleModules =>
BEGIN OPEN IODefs, etb[eti];
WriteString["Bad format for "L];
WriteName[ftb[file].name];
WriteChar[CR];
CONTINUE
END;
ListerDefs.NoSymbols =>
BEGIN OPEN IODefs, etb[eti];
WriteString["No symbols for "L];
WriteName[ftb[file].name];
WriteChar[CR];
CONTINUE
END;
ListerDefs.IncorrectVersion =>
BEGIN OPEN IODefs, etb[eti];
WriteString["Wrong version: "L];
WriteName[ftb[file].name];
WriteChar[CR];
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;
ExportsToSort: PROC [eti: EXPIndex] =
BEGIN OPEN etb[eti];
i: CARDINAL;
n: CARDINAL ← 0;
link: BcdDefs.Link;
sei: Symbols.ISEIndex;
interfaceName.length ← 0;
AppendName[interfaceName, name];
FOR i IN [0..size) DO
link ← links[i];
IF link # BcdDefs.NullLink THEN
BEGIN
IF ~loaded THEN LoadSymbols[file];
sei ← SeiForItem[i];
IF sei = Symbols.ISENull THEN LOOP;
RecordExport[sei, TRUE];
END;
ENDLOOP;
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;
AddInterface: PROC =
BEGIN OPEN Symbols, symbols;
interfaceName.length ← 0;
String.AppendString[interfaceName, moduleName];
LoadSymbolsName[moduleName !
SegmentDefs.FileNameError =>
BEGIN OPEN IODefs;
WriteString["Can't find "L];
WriteString[moduleName];
WriteChar[CR];
GO TO cant;
END];
FOR sei: ISEIndex ← FirstCtxSe[stHandle.outerCtx],
NextSe[sei] UNTIL sei = ISENull DO
SELECT LinkMode[sei] FROM
val, ref => RecordExport[sei, FALSE];
ENDCASE;
ENDLOOP;
UnloadSymbols[];
EXITS
cant => NULL;
END;
symbols: SymbolTable.Base ← NIL;
sseg: SegmentDefs.FileSegmentHandle ← NIL;
loaded: BOOLEAN ← FALSE;
LoadSymbols: PROCEDURE [file: FTIndex] =
BEGIN OPEN ListerDefs;
s: STRING ← [60];
IF file = FTNull OR file = FTSelf OR symbols # NIL OR sseg # NIL THEN ERROR;
GetBcdName[s, ftb[file].name];
LoadSymbolsName[s];
IF ftb[file].version # symbols.stHandle.version THEN
SIGNAL ListerDefs.IncorrectVersion;
END;
LoadSymbolsName: PROCEDURE [s: STRING] =
BEGIN OPEN ListerDefs;
cseg: SegmentDefs.FileSegmentHandle;
bs: STRING ← [50];
String.AppendString[bs, s];
FOR i: CARDINAL IN [0..bs.length) DO
IF bs[i] = '. THEN EXIT;
REPEAT
FINISHED => String.AppendString[bs, ".bcd"L];
ENDLOOP;
[code: cseg, symbols: sseg] ← Load[bs ! NoCode, NoFGT => RESUME ];
IF cseg # NIL THEN SegmentDefs.DeleteFileSegment[cseg];
symbols ← SymbolTable.Acquire[SymbolTable.TableForSegment[sseg]];
SetRoutineSymbols[symbols];
loaded ← TRUE;
END;
UnloadSymbols: PROCEDURE =
BEGIN OPEN SegmentDefs;
IF symbols # NIL THEN SymbolTable.Release[symbols];
IF sseg # NIL THEN DeleteFileSegment[sseg ! SwapError => CONTINUE];
symbols ← NIL;
sseg ← NIL;
loaded ← FALSE;
END;
-- Utility Prints
PrintGarbage: PROCEDURE =
BEGIN
PutString["? looks like garbage to me ..."];
PutCR[];
RETURN
END;
GetBcdName: PUBLIC PROCEDURE [s: STRING, n: NameRecord] =
BEGIN
i: CARDINAL;
ssd: String.SubStringDescriptor ←
[base: @ssb.string, offset: n, length: MIN[ssb.size[n], 100]];
s.length ← 0;
String.AppendSubString[s, @ssd];
FOR i IN [0..s.length) DO IF s[i] = '. THEN RETURN ENDLOOP;
String.AppendString[s, ".bcd"L];
RETURN
END;
-- Utility Puts
PutName: PUBLIC PROCEDURE [n: NameRecord] =
BEGIN
ssd: String.SubStringDescriptor ←
[base: @ssb.string, offset: n, length: MIN[ssb.size[n], 100]];
PutSubString[@ssd];
RETURN
END;
AppendName: PUBLIC PROCEDURE [s: STRING, n: NameRecord] =
BEGIN
ssd: String.SubStringDescriptor ←
[base: @ssb.string, offset: n, length: MIN[ssb.size[n], 100]];
String.AppendSubString[s, @ssd];
RETURN
END;
WriteName: PUBLIC PROCEDURE [n: NameRecord] =
BEGIN
ssd: String.SubStringDescriptor ←
[base: @ssb.string, offset: n, length: MIN[ssb.size[n], 100]];
IODefs.WriteSubString[@ssd];
RETURN
END;
RecordExport: PROC [item: Symbols.ISEIndex, present: BOOLEAN] =
BEGIN OPEN String;
desc: String.SubStringDescriptor;
sortLength: CARDINAL;
buffer↑ ← [
interface: NULL,
module: NULL,
item: [length: 0, maxlength: 100, text:]];
symbols.SubStringForHash[@desc, symbols.HashForSe[item]];
AppendSubString[@buffer.item, @desc];
buffer.interface ←
LOOPHOLE[sortLength ← WordsForString[buffer.item.length] + 2];
buffer[buffer.interface] ← [length: 0, maxlength: 100, text:];
AppendString[@buffer[buffer.interface], interfaceName];
sortLength ← sortLength + WordsForString[interfaceName.length];
IF ~present THEN buffer.module ← NullString
ELSE
BEGIN
buffer.module ← LOOPHOLE[sortLength];
buffer[buffer.module] ← [length: 0, maxlength: 100, text:];
AppendString[@buffer[buffer.module], moduleName];
sortLength ← sortLength + WordsForString[moduleName.length];
END;
buffer ← OutToSort[sortLength];
END;
Compare: PROCEDURE [p1, p2: POINTER] RETURNS [i: INTEGER] =
BEGIN
k1:KeyBase = p1;
k2: KeyBase = p2;
i ← String.CompareStrings[@k1[k1.interface], @k2[k2.interface]];
IF i = 0 THEN i ← String.CompareStrings[@k1.item, @k2.item];
IF i = 0 THEN i ← String.CompareStrings[@k1[k1.module], @k2[k2.module]];
END;
lastInterface: STRING ← [60];
lastItem: STRING ← [60];
first: BOOLEAN ← TRUE;
Put: PROC [p: POINTER, len: CARDINAL] =
BEGIN
key: KeyBase = p;
NextItem[
interface: @key[key.interface],
item: @key.item,
module: IF key.module = NullString THEN NIL ELSE @key[key.module]];
END;
NextItem: PROCEDURE [interface, item, module: STRING] =
BEGIN OPEN OutputDefs;
IF ~String.EqualString[interface, lastInterface] THEN
BEGIN
IF ~first THEN PutChar[')];
first ← TRUE;
PutCR[];
PutCR[];
PutString[interface];
lastInterface.length ← 0;
String.AppendString[lastInterface, interface];
lastItem.length ← 0;
END;
IF ~String.EqualString[item, lastItem] THEN
{IF ~first THEN PutChar[')];
PutCR[]; PutString[" "L]; PutString[item];
lastItem.length ← 0; String.AppendString[lastItem, item];
first ← TRUE};
IF module # NIL THEN
BEGIN
IF first THEN {PutString[" ("L]; first ← FALSE}
ELSE PutString[", "L];
PutString[module];
END;
END;
KeyBase: TYPE = BASE POINTER TO SortKey;
SortKey: TYPE = RECORD [
interface, module: KeyBase RELATIVE POINTER TO StringBody,
item: StringBody];
NullString: KeyBase RELATIVE POINTER TO StringBody = LOOPHOLE[0];
buffer: KeyBase;
interfaceName: STRING ← [60];
moduleName: STRING ← [40];
port: TYPE = MACHINE DEPENDENT RECORD [in, out: UNSPECIFIED];
OutToSort: PORT [len: CARDINAL] RETURNS [POINTER];
SortStarter: TYPE = PORT [
get: GPsortDefs.GetProcType, put: GPsortDefs.PutProcType,
compare: GPsortDefs.CompareProcType, expectedItemSize: CARDINAL,
maxItemSize: CARDINAL, reservedPages: CARDINAL] RETURNS [POINTER];
SortStopper: TYPE = PORT [len: CARDINAL ← 0];
onLine: CARDINAL;
firstFile: BOOLEAN ← TRUE;
Implementors: PROCEDURE [fileList: STRING] =
BEGIN OPEN String, StreamDefs, OutputDefs;
s: STRING ← [50];
ch: CHARACTER;
-- open list of names
cs: StreamHandle ← NewByteStream[
fileList, Read ! SegmentDefs.FileNameError => GO TO notFound];
-- crank up the sort package
LOOPHOLE[OutToSort, port].out ← GPsortDefs.Sort;
buffer ← LOOPHOLE[OutToSort, SortStarter][
get: LOOPHOLE[@OutToSort, GPsortDefs.GetProcType], put: Put,
compare: Compare, expectedItemSize: 40, maxItemSize: 70, reservedPages: 90];
OutputDefs.OpenOutput[fileList, ".iml"];
PutString["Interface items implemented by:"];
PutCR[]; onLine ← 0;
-- go through list of names, calling OutToSort
UNTIL cs.endof[cs] DO
s.length ← 0;
WHILE ~cs.endof[cs] AND (ch ← cs.get[cs]) # ' DO
AppendChar[s, ch]; ENDLOOP;
IF s.length > 0 THEN
BEGIN OPEN IODefs;
WriteChar[CR];
WriteString[" "L];
WriteString[s];
ProcessFile[s];
END;
ENDLOOP;
IODefs.WriteChar[IODefs.CR];
cs.destroy[cs];
PutCR[];
-- get ready to write output
lastInterface.length ← 0;
lastItem.length ← 0;
-- shut down the sort package (and call Put many times)
LOOPHOLE[OutToSort, SortStopper][];
IF ~first THEN PutChar[')];
OutputDefs.PutCR[];
OutputDefs.CloseOutput[];
EXITS notFound => IODefs.WriteLine[" Command file not found"L];
END;
ProcessFile: PROCEDURE [root: STRING] =
BEGIN
i: CARDINAL;
bcdfile: STRING ← [40];
file: STRING ← [40];
seg: SegmentDefs.FileSegmentHandle;
BEGIN OPEN String;
FOR i IN [0..root.length) DO
IF root[i] = '. THEN EXIT;
AppendChar[bcdfile, root[i]];
ENDLOOP;
AppendString[file, bcdfile];
AppendString[bcdfile, ".bcd"];
END;
BEGIN OPEN SegmentDefs;
seg ← NewFileSegment[
NewFile[bcdfile, Read, DefaultVersion ! FileNameError => GO TO NoFile], 1,
1, Read];
InstallBcd[seg];
BEGIN
name: BcdDefs.NameRecord = mtb[FIRST[BcdDefs.MTIndex]].name;
moduleName.length ← 0; AppendName[moduleName, name];
IF firstFile THEN firstFile ← FALSE ELSE PutChar[',];
IF onLine + file.length > 70 THEN {PutCR[]; onLine ← 0}
ELSE {PutChar[' ]; onLine ← onLine + 2}; -- 1 for the comma
PutString[file]; onLine ← onLine + file.length;
IF bcd.definitions THEN AddInterface[]
ELSE ScanExports[ExportsToSort];
END;
UnstallBcd[seg];
EXITS NoFile => IODefs.WriteString[" File not found"];
END;
RETURN
END;
Init: PROCEDURE =
BEGIN
command: CommanderDefs.CommandBlockHandle;
command ← CommanderDefs.AddCommand[
"Implementors", LOOPHOLE[Implementors], 1];
command.params[0] ← [type: string, prompt: "fileList"];
END;
Init[];
END....