-- CTFakeBcdImpl.Mesa, last edit March 21, 1983 5:52 pm
-- procedures to build the fake config in the compile tool
DIRECTORY
BcdDefs: TYPE USING [Base, BCD, CTIndex, CTNull, CTRecord, EXPIndex,
FTIndex, FTNull, FTRecord, FTSelf, GFTIndex,
Link, MTIndex, MTRecord, NameRecord, NullVersion, SGIndex, SGRecord, VersionID],
BcdOps: TYPE USING [BcdBase, MTHandle, NameString, ProcessModules],
Environment: TYPE USING [wordsPerPage],
File: TYPE USING [Capability],
IO: TYPE USING[card, PutF, rope],
-- CedarLinkerOps: TYPE USING[Export],
CS: TYPE USING[NewFile, ReadWrite],
CT: TYPE USING[GenUniqueBcdName, Global, MI, ModuleList],
CTFakeBcd: TYPE USING[],
CTLoad: TYPE USING [LoadInfoSeq, Zero],
PilotLoadStateFormat: TYPE USING [ConfigIndex],
PilotLoadStateOps: TYPE USING [ConfigIndex, EnterModule, GetMap,
Map, ReleaseLoadState, ReleaseMap, UpdateLoadState],
PrincOps: TYPE USING[GFTIndex],
Rope: TYPE USING[Text],
Space: TYPE USING [Create, Delete, -- ForceOut, -- Handle, LongPointer, Map,
nullHandle, virtualMemory];
CTFakeBcdImpl: PROGRAM
IMPORTS BcdOps, -- CedarLinkerOps, -- CS, CT, CTLoad, IO, PilotLoadStateOps, Space
EXPORTS CTFakeBcd = {
-- 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[g: CT.Global] = {
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;
ProcAnalyze: PROC[mi: CT.MI] = {
sgb, ftb: BcdDefs.Base;
bcdbase: BcdOps.BcdBase;
namestring: BcdOps.NameString;
ForEachModule: PROC[mth: BcdOps.MTHandle, mti: BcdDefs.MTIndex]
RETURNS[stop: BOOL] = {
rgfi: PrincOps.GFTIndex;
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 >= mi.loadInfoSeq.dummymapseq.size THEN ERROR;
-- this has previously been done in
-- CedarLoaderImpl.CreateGlobalFrames
-- we do it here to set the map for the fake config
rgfi ← mi.loadInfoSeq.dummymapseq[mth.gfi].ind;
FOR i: CARDINAL IN [0 .. mth.ngfi) DO
PilotLoadStateOps.EnterModule[rgfi+i, [resolved: TRUE,
config: g.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[mi.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 mi.loadInfoSeq = NIL THEN RETURN;
bcdbase ← mi.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[oldrope: Rope.Text] RETURNS[newname: BcdDefs.NameRecord] = {
oldstring: LONG STRING ← LOOPHOLE[oldrope];
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;
};
{
cap: File.Capability;
map: PilotLoadStateOps.Map;
bcdSpace ← Space.Create[size: BCDPAGES, parent: Space.virtualMemory];
g.fakeBcdFileName ← CT.GenUniqueBcdName["FakeConfig"];
cap ← CS.NewFile[g.fakeBcdFileName, CS.ReadWrite, BCDPAGES];
Space.Map[space: bcdSpace, window: [cap, 1]];
Cbcdbase ← Space.LongPointer[bcdSpace];
[] ← CTLoad.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[g.fakeBcdFileName],
namedInstance: FALSE, file: BcdDefs.FTNull, config: BcdDefs.CTNull,
nControls: 0, controls:];
-- that sets all the booleans to FALSE, etc.
FOR l: CT.ModuleList ← g.moduleList, l.rest UNTIL l = NIL DO
ProcAnalyze[l.first];
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;
g.fakebcdspace ← bcdSpace;
-- now insert the new bcdbase
-- newer version of BcdOps
PilotLoadStateOps.UpdateLoadState[g.configindex, LOOPHOLE[Cbcdbase]];
map ← PilotLoadStateOps.GetMap[g.configindex];
-- CedarLinkerOps.Export[LOOPHOLE[Cbcdbase], map];
PilotLoadStateOps.ReleaseMap[map];
PilotLoadStateOps.ReleaseLoadState[];
g.dout.PutF["Total # of gfi's needed to load: %s.\n", IO.card[Cngfi]];
-- this ForceOut is expensive, only need it for debugging
-- Space.ForceOut[bcdSpace];
g.dout.PutF["Fake bcd written out on %s\n", IO.rope[g.fakeBcdFileName]];
}}};
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];
};
}.
-- no longer needed
AddToExports: PROC[interfaceseq: CTLoad.InterfaceSeq] = {
Check[Cfti + SIZE[BcdDefs.FTRecord], Cbcdbase.ftLimit];
Check[Ceti + SIZE[BcdDefs.EXPRecord] + interfaceseq.size, Cbcdbase.expLimit];
Cftb[Cfti] ← [name: NewString[interfaceseq.name], version: interfaceseq.bcdVers];
Cetb[Ceti] ← [name: NewString[interfaceseq.name], 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;
};
-- now put exports in export table
{
mi: CT.MI;
FOR l: CT.ModuleList ← g.moduleList, l.rest UNTIL l = NIL DO
mi ← l.first;
IF mi.exportedInterface THEN {
FOR l: LIST OF CTLoad.InterfaceSeq ← g.moduleExports, l.rest UNTIL l = NIL DO
IF l.first.bcdVers = mi.bcdVers THEN {
AddToExports[l.first];
EXIT;
};
REPEAT
FINISHED => {
g.ttyout.PutF["Error - cannot find %s exported by this program.\n",
IO.rope[mi.bcdFileName]];
};
ENDLOOP;
};
ENDLOOP;
};