MBLoadState.mesa
Last modified by Sandman on March 13, 1981 4:01 PM
Last modified by Lewis on 21-Sep-81 17:08:04
Last modified by Levin on September 30, 1983 5:06 pm
DIRECTORY
BasicLoadStateFormat
USING [
BcdInfo, ConfigIndex, LoadStateObject, ModuleInfo, nullConfig, nullModule, versionID],
BasicLoadStateFormatExtension USING [Extension, nullType],
BcdDefs USING [BcdBase, MTIndex, MTNull],
MB USING [BHandle, Error, Handle],
MBLoaderOps USING [Binding, BindingRecord, BindLink, EnumerationDirection],
MBVM USING [AllocData, DataSeg, HyperSpace, LongCopyWrite, LongPointerFromSeg, Write],
PrincOps USING [GFT, GFTIndex, GlobalFrame, GlobalFrameHandle],
PrincOpsUtils USING [PagesForWords];
MBLoadState:
PROGRAM
IMPORTS MB, MBVM, PrincOpsUtils
EXPORTS MBLoaderOps =
BEGIN
OPEN MB;
data: MB.Handle ← NIL;
loadstate: REF BasicLoadStateFormat.LoadStateObject ← NIL;
extension: REF BasicLoadStateFormatExtension.Extension ← NIL;
lsWords, extensionWords: CARDINAL;
nextGFI: CARDINAL ← 1; -- gfi 0 is never used
InitLoadState: PUBLIC PROC [h: MB.Handle] = {data ← h};
FinishLoadState:
PUBLIC
PROC = {
loadstate ← NIL;
extension ← NIL;
data ← NIL;
};
InputLoadState:
PUBLIC
PROC
RETURNS [nbcds: BasicLoadStateFormat.ConfigIndex] = {
IF loadstate =
NIL
THEN {
IF ~data.germ
THEN {
lsWords ←
SIZE[BasicLoadStateFormat.LoadStateObject[BasicLoadStateFormat.ConfigIndex.LAST]];
extensionWords ← SIZE[BasicLoadStateFormatExtension.Extension];
data.lsseg ←
MBVM.AllocData[
base: MBVM.HyperSpace,
pages: PrincOpsUtils.PagesForWords[lsWords+extensionWords],
dir: up
];
data.lsseg.info.readOnly ← FALSE;
data.lsseg.bootLoaded ← TRUE;
};
allocate temporary copy of loadstate (written into MBVM loadstate by WriteLoadState)
loadstate ←
NEW[BasicLoadStateFormat.LoadStateObject[BasicLoadStateFormat.ConfigIndex.LAST]];
loadstate.versionident ← BasicLoadStateFormat.versionID;
FOR gfi: PrincOps.GFTIndex
IN [0..data.gftLength)
DO
loadstate.gft[gfi] ← BasicLoadStateFormat.nullModule;
ENDLOOP;
FOR i: BasicLoadStateFormat.ConfigIndex
IN [0..BasicLoadStateFormat.ConfigIndex.
LAST)
DO
loadstate.bcds[i] ← [ptr[NIL]];
ENDLOOP;
loadstate.nBcds ← 0;
extension ← NEW[BasicLoadStateFormatExtension.Extension];
FOR gfi: PrincOps.GFTIndex
IN [0..data.gftLength)
DO
extension[gfi] ← [mti: BcdDefs.MTNull, type: BasicLoadStateFormatExtension.nullType];
ENDLOOP;
nextGFI ← 1;
};
RETURN[loadstate.nBcds]
};
UpdateLoadState:
PUBLIC
PROC [
config: BasicLoadStateFormat.ConfigIndex, handle: MB.BHandle] = {
bcd: BcdDefs.BcdBase = handle.bcd;
IF config = BasicLoadStateFormat.nullConfig THEN ERROR;
loadstate.bcds[config].bcd ←
IF data.germ THEN NIL ELSE MBVM.LongPointerFromSeg[handle.bcdSeg];
loadstate.bcds[config].typeExported ← bcd.typeExported;
loadstate.bcds[config].exports ← (bcd.nExports ~= 0);
IF config >= loadstate.nBcds THEN loadstate.nBcds ← loadstate.nBcds + 1;
};
WriteLoadState:
PUBLIC
PROC = {
p: LONG POINTER;
IF data.germ THEN RETURN;
p ← MBVM.LongPointerFromSeg[data.lsseg];
MBVM.LongCopyWrite[
from: LOOPHOLE[loadstate], to: p,
nwords: lsWords
];
MBVM.LongCopyWrite[
from: LOOPHOLE[extension], to: p + lsWords,
nwords: extensionWords
];
EnterModule:
PUBLIC
PROC [
rgfi: PrincOps.GFTIndex, module: BasicLoadStateFormat.ModuleInfo,
mti: BcdDefs.MTIndex ← BcdDefs.MTNull] = {
loadstate.gft[rgfi] ← module;
IF mti ~= BcdDefs.MTNull THEN extension[rgfi].mti ← mti;
GetModule:
PUBLIC
PROC [rgfi: PrincOps.GFTIndex]
RETURNS [module: BasicLoadStateFormat.ModuleInfo] = {
RETURN[loadstate.gft[rgfi]]};
AcquireBcd:
PUBLIC
PROC [config: BasicLoadStateFormat.ConfigIndex]
RETURNS [handle: MB.BHandle] = {
RETURN[data.inputBCDs.bcds[config]]};
InitBinding:
PUBLIC
PROC [bcd: BcdDefs.BcdBase]
RETURNS [binding: MBLoaderOps.Binding] = {
binding ←
NEW[MBLoaderOps.BindingRecord[bcd.nDummies] ← [
bias: bcd.firstdummy,
b: NULL --ALL[MBLoaderOps.BindLink[whichgfi: 0, body: notbound[]]]
]];
FOR i:
CARDINAL
IN [0..binding.n)
DO
binding.b[i] ← MBLoaderOps.BindLink[whichgfi: 0, body: notbound[]];
ENDLOOP;
BcdUnresolved:
PUBLIC
PROC [
bcd: BasicLoadStateFormat.ConfigIndex] RETURNS [BOOL] = {
FOR i: PrincOps.GFTIndex
IN [0..data.gftLength)
DO
IF bcd = loadstate.gft[i].config AND ~loadstate.gft[i].resolved THEN RETURN[TRUE];
ENDLOOP;
RETURN[FALSE]
};
BcdExports:
PUBLIC
PROC [bcd: BasicLoadStateFormat.ConfigIndex]
RETURNS [
BOOL] = {
RETURN[loadstate.bcds[bcd].exports]};
BcdExportsTypes:
PUBLIC
PROC [bcd: BasicLoadStateFormat.ConfigIndex]
RETURNS [
BOOL] = {
RETURN[loadstate.bcds[bcd].typeExported]};
GFT management
GetNextGFI:
PUBLIC
PROC [reserve:
CARDINAL]
RETURNS [next: PrincOps.GFTIndex] = {
IF (next ← nextGFI) >= data.gftLength THEN MB.Error["GFT overflow"];
nextGFI ← nextGFI + reserve;
};
SetGFTEntry:
PUBLIC
PROC [
frame: PrincOps.GlobalFrameHandle, gfi: PrincOps.GFTIndex, ngfi: CARDINAL] = {
IF gfi+ngfi >= data.gftLength THEN MB.Error["GFT Full"];
FOR i:
CARDINAL
IN [gfi..gfi+ngfi)
DO
bias: CARDINAL = (i-gfi);
MBVM.Write[
@PrincOps.GFT[i].framePtr,
(frame + bias)]; -- bottom two bits of GFT entries bias evi's
ENDLOOP;
EnumerateModules:
PUBLIC
PROC [
proc: PROC [rgfi: PrincOps.GFTIndex, module: BasicLoadStateFormat.ModuleInfo] RETURNS [BOOL]]
RETURNS [i: PrincOps.GFTIndex] = {
FOR i
IN [0..nextGFI)
DO
IF loadstate.gft[i].config ~= BasicLoadStateFormat.nullConfig
AND proc[i, loadstate.gft[i]]
THEN
EXIT;
ENDLOOP;
EnumerateBcds:
PUBLIC
PROC [
dir: MBLoaderOps.EnumerationDirection,
proc: PROC [BasicLoadStateFormat.ConfigIndex] RETURNS [BOOL]]
RETURNS [config: BasicLoadStateFormat.ConfigIndex] = {
SELECT dir
FROM
recentfirst =>
FOR config
DECREASING
IN [0..loadstate.nBcds)
DO
IF proc[config] THEN RETURN;
ENDLOOP;
recentlast =>
FOR config
IN [0..loadstate.nBcds)
DO
IF proc[config] THEN RETURN;
ENDLOOP;
ENDCASE;
RETURN[BasicLoadStateFormat.nullConfig]
};