-- MDFakeBcdImpl.Mesa
-- last edit by Schmidt, 2-Mar-82 12:49:02
-- last edit by Satterthwaite, January 31, 1983 9:23 am
-- Mesa 7.0/ Pilot 6.0
-- procedures to load and start modules in a Model
-- can't use PilotLoaderOps since it is not exported by CoPilotDorado.Config
-- may use PilotLoadStateOps, however
-- links:
-- IF gfi > firstdummy, then gfi is index into Import table
-- and ep is index into the export record pared with that import
-- binding is simply to copy control link in the export record
-- into this link
-- IF gfi < firstdummy, then gfi in this link is an index into the config's
-- moduletable. Do not alter the ep
-- spaces:
-- assume there are n modules
-- there will be
-- 1 space in MDS for all the frames (and frame links)
-- 1 space in VM for the Fake Config Bcd for the load state
-- n ReadOnly spaces for Code
-- n (up to n) subspaces for the code links
-- n subspaces for the code segments
-- (unless the bcd is Binder-output)
-- n spaces for the Bcd headers
-- (deleted on UnLoad)
DIRECTORY
BcdDefs: TYPE USING [Base, BCD, CTIndex, CTNull, CTRecord, EXPIndex, EXPRecord,
FTIndex, FTNull, FTRecord, FTSelf, GFTIndex,
Link, MTIndex, MTRecord, NameRecord, NullVersion, SGIndex, SGRecord, VersionID],
BcdOps: TYPE USING [BcdBase, MTHandle, NameString, ProcessModules],
CWF: TYPE USING [WF0, WF1, WF2, WF3, WF4],
Dir: TYPE USING [FileInfo],
Environment: TYPE USING [wordsPerPage],
File: TYPE USING [Capability],
Inline: TYPE USING [LowHalf],
LowLoader: TYPE USING [CloseLinkSpace, DummyMapSeq, InterfaceSeq, LinkSegmentLength,
LoadInfoSeq, OpenLinkSpace, ReadLink, Zero],
MDLoad: TYPE USING [],
MDModel: TYPE USING [APPLSymbol, LISTSymbol, LOCSymbol, MODELSymbol,
NarrowToAPPL, NarrowToLIST, NarrowToLOC,
NarrowToPROC, PROCSymbol, Symbol, SymbolSeq, TraverseList, TraverseTree],
PilotLoadStateOps: TYPE USING [ConfigIndex, EnterModule, ReleaseLoadState, UpdateLoadState],
PrincOps: TYPE USING [ControlLink, GFTIndex, GlobalFrameHandle, NullLink, UnboundLink],
Space: TYPE USING [Create, Delete, ForceOut, Handle, LongPointer, Map,
nullHandle, virtualMemory],
Subr: TYPE USING [NewFile, ReadWrite];
MDFakeBcdImpl: PROGRAM
IMPORTS BcdOps, CWF, Inline, LowLoader, MDModel, PilotLoadStateOps, Space, Subr
EXPORTS MDLoad = {
-- no MDS usage!
MTPAGE: CARDINAL = (SIZE[BcdDefs.BCD]/Environment.wordsPerPage) + 1;
nmtp: CARDINAL = 20;
FTPAGE: CARDINAL = MTPAGE + nmtp;
nftp: CARDINAL = 6;
SGPAGE: CARDINAL = FTPAGE + nftp;
nsgp: CARDINAL = 6;
CTPAGE: CARDINAL = SGPAGE + nsgp;
nctp: CARDINAL = 1;
SSPAGE: CARDINAL = CTPAGE + nctp;
nssp: CARDINAL = 16;
EXPAGE: CARDINAL = SSPAGE + nssp;
nexp: CARDINAL = 3;
BCDPAGES: CARDINAL = EXPAGE + nexp;
-- also updates the load state with the modules
BuildFakeBcd: PUBLIC PROC[spmodel: MDModel.MODELSymbol, symbolseq: MDModel.SymbolSeq] = {
bcdSpace: Space.Handle ← Space.nullHandle;
{
ENABLE UNWIND =>
IF bcdSpace ~= Space.nullHandle THEN Space.Delete[bcdSpace];
Cbcdbase: BcdOps.BcdBase;
Cctb, Cmtb, Csgb, Cftb, Cetb: BcdDefs.Base;
Cmti: BcdDefs.MTIndex ← FIRST[BcdDefs.MTIndex];
Cfti: BcdDefs.FTIndex ← FIRST[BcdDefs.FTIndex];
Csgi: BcdDefs.SGIndex ← FIRST[BcdDefs.SGIndex];
Ceti: BcdDefs.EXPIndex ← FIRST[BcdDefs.EXPIndex];
Cnamei: CARDINAL;
Cnamestring: BcdOps.NameString;
Cngfi: CARDINAL ← 1;
cap: File.Capability;
ProcAnalyze: PROC[sp: MDModel.Symbol, spmodel: MDModel.MODELSymbol]
RETURNS[proceed: BOOL ← TRUE] = {
sgb, ftb: BcdDefs.Base;
bcdbase: BcdOps.BcdBase;
sploc: MDModel.LOCSymbol;
namestring: BcdOps.NameString;
ForEachModule: PROC[mth: BcdOps.MTHandle, mti: BcdDefs.MTIndex]
RETURNS[stop: BOOL] = {
rgfi: CARDINAL;
stop ← FALSE;
Check[Cmti + MTRecordLength[mth], Cbcdbase.mtLimit];
Cmtb[Cmti] ← mth↑;
Cmtb[Cmti].name ← NewName[namestring, mth.name];
Cmtb[Cmti].gfi ← Cngfi;
Cmtb[Cmti].extension ← direct[length: 0, frag:];
IF mth.gfi >= sploc.fi.loadInfoSeq.dummymapseq.size THEN ERROR;
rgfi ← sploc.fi.loadInfoSeq.dummymapseq[mth.gfi].ind;
FOR i: CARDINAL IN [0 .. mth.ngfi) DO
PilotLoadStateOps.EnterModule[rgfi+i, [resolved: TRUE,
config: spmodel.configindex, gfi: Cngfi+i]];
ENDLOOP;
Cngfi ← Cngfi + mth.ngfi;
Check[Cfti + SIZE[BcdDefs.FTRecord], Cbcdbase.ftLimit];
IF mth.file = BcdDefs.FTSelf THEN {
-- get info from header
Cftb[Cfti] ← [NewName[namestring, bcdbase.source],
bcdbase.version];
Cmtb[Cmti].file ← Cfti;
Cfti ← Cfti + SIZE[BcdDefs.FTRecord];
}
ELSE IF mth.file = BcdDefs.FTNull THEN {
Cmtb[Cmti].file ← BcdDefs.FTNull;
}
ELSE {
Cftb[Cfti] ← ftb[mth.file];
Cftb[Cfti].name ← NewName[namestring,
ftb[mth.file].name];
Cmtb[Cmti].file ← Cfti;
Cfti ← Cfti + SIZE[BcdDefs.FTRecord];
};
Check[Csgi + SIZE[BcdDefs.SGRecord], Cbcdbase.sgLimit];
Csgb[Csgi] ← sgb[mth.sseg];
Cmtb[Cmti].sseg ← Csgi;
Check[Cfti + SIZE[BcdDefs.FTRecord], Cbcdbase.ftLimit];
IF Csgb[Csgi].file = BcdDefs.FTSelf THEN {
-- if self then the symbols are in the config's file
Cftb[Cfti] ← [NewString[sploc.fi.bcdFileName],
bcdbase.version];
Csgb[Csgi].file ← Cfti;
Cfti ← Cfti + SIZE[BcdDefs.FTRecord];
}
ELSE IF Csgb[Csgi].file = BcdDefs.FTNull THEN {
Csgb[Csgi].file ← BcdDefs.FTNull;
}
ELSE {
Cftb[Cfti] ← ftb[Csgb[Csgi].file];
Cftb[Cfti].name ← NewName[namestring,
ftb[Csgb[Csgi].file].name];
Csgb[Csgi].file ← Cfti;
Cfti ← Cfti + SIZE[BcdDefs.FTRecord];
};
Csgi ← Csgi + SIZE[BcdDefs.SGRecord];
Cmti ← Cmti + SIZE[BcdDefs.MTRecord[direct]];
Cbcdbase.nModules ← Cbcdbase.nModules + 1;
};
IF sp.stype ~= typeLOC THEN RETURN;
sploc ← MDModel.NarrowToLOC[sp];
IF sploc.fi = NIL OR sploc.fi.loadInfoSeq = NIL THEN RETURN;
bcdbase ← sploc.fi.loadInfoSeq.bcdbase;
sgb ← LOOPHOLE[bcdbase + bcdbase.sgOffset, BcdDefs.Base];
ftb ← LOOPHOLE[bcdbase + bcdbase.ftOffset, BcdDefs.Base];
namestring ← LOOPHOLE[bcdbase + bcdbase.ssOffset];
[] ← BcdOps.ProcessModules[bcdbase, ForEachModule];
};
NewName: PROC[namestring: BcdOps.NameString, oldname: BcdDefs.NameRecord]
RETURNS[newname: BcdDefs.NameRecord] = {
newname ← LOOPHOLE[Cnamei];
Check[(Cnamei + namestring.size[oldname] + 1)/2 + 1, Cbcdbase.ssLimit];
Cnamestring.size[newname] ← namestring.size[oldname];
FOR i: CARDINAL IN [0 .. Cnamestring.size[newname]) DO
Cnamestring.string.text[newname + i] ←
namestring.string.text[oldname + i];
ENDLOOP;
Cnamei ← Cnamei + Cnamestring.size[newname] + 1;
};
NewString: PROC[oldstring: LONG STRING]
RETURNS[newname: BcdDefs.NameRecord] = {
newname ← LOOPHOLE[Cnamei];
Check[(Cnamei + oldstring.length + 1)/2, Cbcdbase.ssLimit];
Cnamestring.size[newname] ← oldstring.length;
FOR i: CARDINAL IN [0 .. Cnamestring.size[newname]) DO
Cnamestring.string.text[newname + i] ← oldstring[i];
ENDLOOP;
Cnamei ← Cnamei + Cnamestring.size[newname] + 1;
};
AddToExports: PROC[interfaceseq: LowLoader.InterfaceSeq] = {
Check[Cfti + SIZE[BcdDefs.FTRecord], Cbcdbase.ftLimit];
Check[Ceti + SIZE[BcdDefs.EXPRecord] + interfaceseq.size, Cbcdbase.expLimit];
Cftb[Cfti] ← [name: NewString[interfaceseq.intname], version: interfaceseq.versstamp];
Cetb[Ceti] ← [name: NewString[interfaceseq.intname], size: interfaceseq.size,
port: interface, namedInstance: FALSE, typeExported: FALSE,
file: Cfti, links: ];
FOR i: CARDINAL IN [0 .. Cetb[Ceti].size) DO
Cetb[Ceti].links[i] ← interfaceseq[i].blink;
ENDLOOP;
Cfti ← Cfti + SIZE[BcdDefs.FTRecord];
Ceti ← Ceti + SIZE[BcdDefs.EXPRecord] + interfaceseq.size;
Cbcdbase.nExports ← Cbcdbase.nExports + 1;
};
bcdSpace ← Space.Create[size: BCDPAGES, parent: Space.virtualMemory];
cap ← Subr.NewFile["FakeConfig.Bcd"L, Subr.ReadWrite, BCDPAGES];
Space.Map[space: bcdSpace, window: [cap, 1]];
Cbcdbase ← Space.LongPointer[bcdSpace];
LowLoader.Zero[Cbcdbase, BCDPAGES * Environment.wordsPerPage];
Cbcdbase.versionIdent ← BcdDefs.VersionID;
Cbcdbase.nPages ← BCDPAGES;
Cbcdbase.version ← BcdDefs.NullVersion;
Cbcdbase.nConfigs ← 1;
Cbcdbase.nModules ← 0;
Cbcdbase.extended ← TRUE; -- to keep the RT happy
Cbcdbase.nImports ← Cbcdbase.nExports ← 0;
-- all the Limit vars are set to 0
Cbcdbase.impOffset ← Cbcdbase.evOffset ← 0;
Cbcdbase.spOffset ← Cbcdbase.ntOffset ← Cbcdbase.typOffset ← 0;
Cbcdbase.tmOffset ← Cbcdbase.fpOffset ← 0;
Cbcdbase.ctOffset ← CTPAGE * Environment.wordsPerPage;
Cbcdbase.mtOffset ← MTPAGE * Environment.wordsPerPage;
Cbcdbase.sgOffset ← SGPAGE * Environment.wordsPerPage;
Cbcdbase.ftOffset ← FTPAGE * Environment.wordsPerPage;
Cbcdbase.expOffset ← EXPAGE * Environment.wordsPerPage;
Cbcdbase.ssOffset ← SSPAGE * Environment.wordsPerPage;
Cnamei ← 0;
Cctb ← LOOPHOLE[Cbcdbase + Cbcdbase.ctOffset, BcdDefs.Base];
Cmtb ← LOOPHOLE[Cbcdbase + Cbcdbase.mtOffset, BcdDefs.Base];
Csgb ← LOOPHOLE[Cbcdbase + Cbcdbase.sgOffset, BcdDefs.Base];
Cftb ← LOOPHOLE[Cbcdbase + Cbcdbase.ftOffset, BcdDefs.Base];
Cetb ← LOOPHOLE[Cbcdbase + Cbcdbase.expOffset, BcdDefs.Base];
Cnamestring ← LOOPHOLE[Cbcdbase + Cbcdbase.ssOffset, BcdDefs.Base];
Cbcdbase.ctLimit ← FIRST[BcdDefs.CTIndex] + SIZE[BcdDefs.CTRecord];
Cbcdbase.mtLimit ← LOOPHOLE[nmtp * Environment.wordsPerPage];
Cbcdbase.ftLimit ← LOOPHOLE[nftp * Environment.wordsPerPage];
Cbcdbase.sgLimit ← LOOPHOLE[nsgp * Environment.wordsPerPage];
Cbcdbase.expLimit ← LOOPHOLE[nexp * Environment.wordsPerPage];
Cbcdbase.ssLimit ← LOOPHOLE[nssp * Environment.wordsPerPage];
LOOPHOLE[Cnamestring+1, LONG POINTER TO CARDINAL]↑ ← (Cbcdbase.ssLimit-2)*2; -- the maxlength of namestring
Cnamestring.string.length ← Cnamestring.string.maxlength;
Cctb[FIRST[BcdDefs.CTIndex]] ← [name: NewString["FakeConfig"L],
namedInstance: FALSE, file: BcdDefs.FTNull, config: BcdDefs.CTNull,
nControls: 0, controls:];
-- that sets all the booleans to FALSE, etc.
MDModel.TraverseTree[spmodel, symbolseq, ProcAnalyze, TRUE];
-- now put exports in export table
{
splist: MDModel.LISTSymbol;
spproc: MDModel.PROCSymbol ← NIL;
splist ← spmodel.model;
WHILE splist ~= NIL AND splist.first.stype ~= typePROC DO
splist ← splist.rest;
ENDLOOP;
spproc ← MDModel.NarrowToPROC[splist.first];
splist ← spproc.procret;
WHILE splist ~= NIL DO
IF splist.first.stype = typeAPPL THEN {
spappl: MDModel.APPLSymbol ← MDModel.NarrowToAPPL[splist.first];
IF spappl.interfaceseq ~= NIL THEN
AddToExports[spappl.interfaceseq];
};
splist ← splist.rest;
ENDLOOP;
};
Cbcdbase.firstdummy ← Cngfi; -- # gfi's needed for the modules in the config
Cbcdbase.mtLimit ← Cmti;
Cbcdbase.ftLimit ← Cfti;
Cbcdbase.sgLimit ← Csgi;
Cbcdbase.expLimit ← Ceti;
Cbcdbase.ssLimit ← (Cnamei/2)+1;
spmodel.fakebcdspace ← bcdSpace;
-- now insert the new bcdbase
-- newer version of BcdOps
PilotLoadStateOps.UpdateLoadState[spmodel.configindex, LOOPHOLE[Cbcdbase]];
PilotLoadStateOps.ReleaseLoadState[];
CWF.WF1["Total # of gfi's needed to load: %u.\n"L, @Cngfi];
Space.ForceOut[bcdSpace];
CWF.WF0["Fake bcd written out on FakeConfig.Bcd\n"L];
}};
Check: PROC[val, limit: UNSPECIFIED] = {
IF LOOPHOLE[val, CARDINAL] >= LOOPHOLE[limit, CARDINAL] THEN ERROR;
};
MTRecordLength: PROC[mth: BcdOps.MTHandle] RETURNS[len: CARDINAL] = {
RETURN[WITH m: mth SELECT FROM
direct => SIZE[BcdDefs.MTRecord[direct]] + m.length*SIZE[BcdDefs.Link],
indirect => SIZE[BcdDefs.MTRecord[indirect]],
multiple => SIZE[BcdDefs.MTRecord[multiple]],
ENDCASE => ERROR];
};
PrintFrameLinks: PROC[frame: PrincOps.GlobalFrameHandle,
bcdbase: BcdOps.BcdBase, mth: BcdOps.MTHandle] = {
links: LONG POINTER;
l, t: POINTER;
links ← LowLoader.OpenLinkSpace[frame, mth, bcdbase];
l ← Inline.LowHalf[links];
t ← l + LowLoader.LinkSegmentLength[mth, bcdbase];
CWF.WF3["Links from %bB to %bB, frame at %bB.\n"L, @l, @t, @frame];
FOR i: CARDINAL IN [0..LowLoader.LinkSegmentLength[mth, bcdbase]) DO
PrintCLink[i, LowLoader.ReadLink[i]];
ENDLOOP;
LowLoader.CloseLinkSpace[frame];
};
-- also in LowLoader, this one uses this CWF
PrintCLink: PROC[j: CARDINAL, link: PrincOps.ControlLink] = {
IF link = PrincOps.NullLink THEN
CWF.WF1["#%u: NullLink\n"L, @j]
ELSE IF link = PrincOps.UnboundLink THEN
CWF.WF1["#%u: UnboundLink\n"L, @j]
ELSE {
gfi, ep: CARDINAL;
gfi ← link.gfi;
ep ← link.ep;
CWF.WF4["#%u: gfi %bB ep %u, address %bB\n"L, @j, @gfi, @ep, @link];
};
};
PrintFrames: PROC[spmodel: MDModel.MODELSymbol,
symbolseq: MDModel.SymbolSeq] = {
ProcAnalyze: PROC[sptop: MDModel.Symbol, spmodel: MDModel.MODELSymbol]
RETURNS[proceed: BOOL ← TRUE] = {
-- calls itself recursively
-- spmodel, sptop is passed in
ProcLoc: PROC[spl: MDModel.Symbol] = {
IF spl = NIL THEN RETURN;
IF spl.stype = typeLIST THEN
MDModel.TraverseList[MDModel.NarrowToLIST[spl], ProcLoc]
ELSE IF spl.stype = typeLOC THEN {
mti: BcdDefs.MTIndex ← FIRST[BcdDefs.MTIndex];
mth: BcdOps.MTHandle;
bcdbase: BcdOps.BcdBase;
sploc: MDModel.LOCSymbol;
sploc ← MDModel.NarrowToLOC[spl];
IF sploc.fi = NIL OR sploc.fi.loadInfoSeq = NIL THEN RETURN; -- defs file
CWF.WF1["Frame of %s.Bcd:\n"L, sploc.tail];
FOR m: CARDINAL IN [0 .. sploc.fi.loadInfoSeq.size) DO
bcdbase ← sploc.fi.loadInfoSeq.bcdbase;
mth ← @LOOPHOLE[bcdbase + bcdbase.mtOffset,
BcdDefs.Base][mti];
PrintFrameLinks[sploc.fi.loadInfoSeq[m].frame,
bcdbase, mth];
mti ← mti + MTRecordLength[mth];
ENDLOOP;
};
};
WITH spt: sptop SELECT FROM
typeTYPE => ProcLoc[spt.typeval];
typeAPPL => ProcLoc[spt.applval];
typeLET => ProcLoc[spt.letval];
ENDCASE => NULL;
RETURN[TRUE];
};
CWF.WF0["Print Frames:\n"L];
MDModel.TraverseTree[spmodel, symbolseq, ProcAnalyze, TRUE];
};
PrintInterfaceSeqs: PROC[spmodel: MDModel.MODELSymbol,
symbolseq: MDModel.SymbolSeq] = {
ProcAnalyze: PROC[sptop: MDModel.Symbol, spmodel: MDModel.MODELSymbol]
RETURNS[proceed: BOOL ← TRUE] = {
WITH spt: sptop SELECT FROM
typeAPPL => {
i: CARDINAL;
interfaceseq: LowLoader.InterfaceSeq;
interfaceseq ← spt.interfaceseq;
IF interfaceseq = NIL THEN RETURN;
CWF.WF2["%s: %u entries:\n"L, spt.applsym, @interfaceseq.size];
FOR i IN [0 .. interfaceseq.size) DO
PrintCLink[i, interfaceseq[i].clink];
ENDLOOP;
};
ENDCASE => NULL;
RETURN[TRUE];
};
CWF.WF0["Print Interface Records:\n"L];
MDModel.TraverseTree[spmodel, symbolseq, ProcAnalyze, TRUE];
};
}.