-- 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]; }; }.