DIRECTORY Basics USING [BITAND], BcdDefs USING [Base, BcdBase, Link, CTHandle, CTIndex, CTNull, EVNull, FPHandle, FPIndex, ModuleIndex, MTHandle, MTIndex, NameString, VarLimit, VersionID], BcdOps USING [ProcessConfigs, ProcessFramePacks, ProcessModules], FS USING [Close, GetInfo, Open, OpenFile, PagesForBytes, Read], IO USING [PutChar, PutF, PutF1, PutFR1, PutRope, STREAM], MB USING [Abort, AllocateFrames, BHandle, BIndex, EnumerateControlList, EnumerateFramePacks, EnumerateGlobalFrames, Error, Handle, ModuleInfo, ModuleInfoSequence, MT], MBLoaderOps USING [Bind, ConfigIndex, EnterModule, FileNotFound, FindFiles, FindCode, GetModule, GetNextGFI, GetVirtualLinks, InputLoadState, LinkFragLength, ModuleInfo, ProcessUnboundImports, RealLinks, RealLinksTable, SetGFTEntry, UpdateLoadState, VersionMismatch, VirtualLinks, WriteLoadState, WriteLinks], MBVM USING [AllocFile, Base, CopyWrite, FileSeg, HyperSpace, Links, LinksObject, Read, Write], PrincOps USING [AV, ControlLink, ControlModule, FrameCodeBase, GFTIndex, GlobalFrame, GlobalFrameHandle, NullControl, NullLink, UnboundLink], PrincOpsUtils USING [MakeFsi], VM USING [AddressForPageNumber, Allocate, Free, Interval, PageNumberForAddress]; MBLoaderCore: CEDAR PROGRAM IMPORTS Basics, BcdOps, FS, IO, MB, MBLoaderOps, MBVM, PrincOpsUtils, VM EXPORTS MB, MBLoaderOps = BEGIN CMTable: TYPE = RECORD [SEQUENCE length: NAT OF CMEntry]; CMEntry: TYPE = RECORD [bh: MB.BHandle, cm: PrincOps.ControlModule]; data: MB.Handle _ NIL; controlModules: REF CMTable _ NIL; InitLoaderCore: PUBLIC PROC [h: MB.Handle] = {data _ h}; FinishLoaderCore: PUBLIC PROC = { FOR i: MB.BIndex IN [0..data.inputBCDs.nBcds) DO loadee: MB.BHandle = data.inputBCDs.bcds[i]; IF loadee.bcd ~= NIL THEN TRUSTED { VM.Free[[page: VM.PageNumberForAddress[loadee.bcd], count: loadee.pages]]; loadee.bcd _ NIL; }; ENDLOOP; data _ NIL; }; Load: PUBLIC PROC = TRUSTED { typescript: IO.STREAM = data.typescript; loadmap: IO.STREAM = data.loadmap; versionError: BOOL _ FALSE; controlModules _ NEW[CMTable[data.inputBCDs.nBcds]]; data.nModules _ 0; FOR i: MB.BIndex IN [0..data.inputBCDs.nBcds) DO loadee: MB.BHandle = data.inputBCDs.bcds[i]; missingCodeFile: BOOL _ FALSE; config: MBLoaderOps.ConfigIndex; IF i # 0 THEN IO.PutRope[typescript, ", "]; IO.PutRope[typescript, loadee.name]; IF ~LoadBcd[loadee] THEN { IO.PutF1[typescript, "\N! Invalid file %g", [rope[loadee.name]]]; ERROR MB.Abort }; IO.PutF1[loadmap, "Global Frames for Modules in %g:\N", [rope[loadee.name]]]; IF ~data.germ THEN { loadee.bcdSeg _ MBVM.AllocFile[ file: loadee.name, fileBase: 0, base: MBVM.HyperSpace, pages: loadee.bcd.nPages]; loadee.bcdSeg.bIndex _ i; }; MBLoaderOps.FindFiles[loadee ! MBLoaderOps.FileNotFound => { IO.PutF1[typescript, "\N! Can't find file %g", [rope[name]]]; missingCodeFile _ TRUE; RESUME } ]; IF missingCodeFile THEN { IO.PutChar[typescript, '\N]; MB.Error["One or more missing code files"]; }; config _ LoadModules[loadee]; MBLoaderOps.FindCode[loadee]; controlModules[i] _ [bh: loadee, cm: AssignControlModules[loadee]]; IF config = FIRST[MBLoaderOps.ConfigIndex] THEN JustRelocateLinks[loadee] ELSE MBLoaderOps.Bind[loadee, config ! MBLoaderOps.VersionMismatch => { IO.PutF[typescript, "\N! Version mismatch: %g, [%g, %g]", [rope[interface]], [rope[ref1]], [rope[ref2]]]; versionError _ TRUE; RESUME } ]; IO.PutChar[loadmap, '\N]; ENDLOOP; IO.PutRope[typescript, "\N"]; data.header.controlList _ BuildTopLevelControlList[]; MBLoaderOps.WriteLoadState[]; data.nGFIs _ MBLoaderOps.GetNextGFI[reserve: 0]; IO.PutF[loadmap, "\NTotal of %d modules, %d GFIs\N", [cardinal[data.nModules]], [cardinal[data.nGFIs]]]; IF versionError THEN MB.Error["One or more version mismatches"]; MBLoaderOps.ProcessUnboundImports[]; IO.PutRope[typescript, "Finished loading.\N"]; }; LoadBcd: PROC [loadee: MB.BHandle] RETURNS [ok: BOOL _ TRUE] = { file: FS.OpenFile = FS.Open[name: loadee.name]; bcdPages: INT _ MIN[FS.PagesForBytes[FS.GetInfo[file].bytes], 10]; buffer: VM.Interval _ VM.Allocate[bcdPages]; bcd: BcdDefs.BcdBase; TRUSTED { bcd _ VM.AddressForPageNumber[buffer.page]; FS.Read[file: file, from: 0, nPages: buffer.count, to: bcd]; IF (ok _ bcd.versionIdent = BcdDefs.VersionID AND ~bcd.definitions) THEN { bcdPages _ bcd.nPages - (IF bcd.extended THEN bcd.rtPages.pages ELSE 0); SELECT bcdPages FROM < buffer.count => VM.Free[[buffer.page+bcdPages, buffer.count - bcdPages]]; > buffer.count => { VM.Free[buffer]; buffer _ VM.Allocate[bcdPages]; bcd _ VM.AddressForPageNumber[buffer.page]; FS.Read[file: file, from: 0, nPages: buffer.count, to: bcd]; }; ENDCASE; loadee.bcd _ bcd; loadee.pages _ bcdPages; } ELSE VM.Free[buffer]; }; file.Close[]; }; SetupModuleTable: PROC [loadee: MB.BHandle] RETURNS [ngfi: CARDINAL _ 0] = TRUSTED { CountEntries: PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS [stop: BOOL _ FALSE] = TRUSTED { ngfi _ ngfi + mth.ngfi; }; SetEntriesForOneModule: PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS [stop: BOOL _ FALSE] = TRUSTED { FOR i: CARDINAL IN [mth.gfi..mth.gfi+mth.ngfi) DO loadee.mt[i] _ MB.ModuleInfo[mth: mth, frame: NIL, code: NIL, codeLinks: NIL]; ENDLOOP; }; [] _ BcdOps.ProcessModules[loadee.bcd, CountEntries]; loadee.mt _ NEW[MB.ModuleInfoSequence[ngfi+1]]; -- +1 because index 0 isn't used loadee.mt[0] _ MB.ModuleInfo[mth: NIL, frame: NIL, code: NIL]; [] _ BcdOps.ProcessModules[loadee.bcd, SetEntriesForOneModule]; }; LoadModules: PROC [loadee: MB.BHandle] RETURNS [config: MBLoaderOps.ConfigIndex] = TRUSTED { bcd: BcdDefs.BcdBase = loadee.bcd; mtb: BcdDefs.Base = LOOPHOLE[bcd + bcd.mtOffset]; mt: MB.MT; ngfi: CARDINAL; gfiOffset: CARDINAL; framePtr: POINTER; frameSpace: CARDINAL _ 0; useFrameHeap: BOOL = (bcd.nModules = 1); inFrameHeap: BOOL; framesResident: BOOL _ FALSE; ProcessOneFramePack: PROC [fph: BcdDefs.FPHandle, fpi: BcdDefs.FPIndex] RETURNS [BOOL] = TRUSTED { frameSpace _ 0; framesResident _ FALSE; FOR i: CARDINAL IN [0..fph.length) DO GetFrameSize[@mtb[fph.modules[i]]]; ENDLOOP; [framePtr, inFrameHeap] _ MB.AllocateFrames[ size: NextMultipleOfFour[frameSpace], single: useFrameHeap, resident: framesResident OR ResidentFramePack[fph] -- specified in bootmesa file--]; FOR i: CARDINAL IN [0..fph.length) DO FrameInit[fph.modules[i]]; ENDLOOP; RETURN[FALSE] }; GetFrameSize: PROC [mth: BcdDefs.MTHandle] = TRUSTED { IF ~(mth.linkLoc = code AND mth.code.linkspace) THEN -- frame links frameSpace _ frameSpace + MBLoaderOps.LinkFragLength[loadee, mth]; frameSpace _ NextMultipleOfFour[frameSpace] + mth.framesize; framesResident _ framesResident OR mth.residentFrame; }; FrameInit: PROC [mti: BcdDefs.MTIndex] = TRUSTED { mth: BcdDefs.MTHandle = @mtb[mti]; frame: PrincOps.GlobalFrameHandle; gf: PrincOps.GlobalFrame; gfi: PrincOps.GFTIndex = gfiOffset + mth.gfi; -- module's biased gfi framelinks: BOOL = ~(mth.linkLoc = code AND mth.code.linkspace); codeLinks: MBVM.Links _ NIL; nLinks: CARDINAL = MBLoaderOps.LinkFragLength[loadee, mth]; data.nModules _ data.nModules + 1; IF framelinks THEN framePtr _ (framePtr + nLinks) ELSE codeLinks _ NEW[MBVM.LinksObject[nLinks]]; frame _ LOOPHOLE[NextMultipleOfFour[LOOPHOLE[framePtr, CARDINAL]]]; framePtr _ (frame + mth.framesize); FOR i: CARDINAL IN [0..mth.ngfi) DO mt[mth.gfi + i].frame _ frame; mt[mth.gfi + i].codeLinks _ codeLinks; ENDLOOP; MBLoaderOps.SetGFTEntry[frame: frame, gfi: gfi, ngfi: mth.ngfi]; FOR i: CARDINAL IN [0..mth.ngfi) DO MBLoaderOps.EnterModule[ rgfi: (gfi + i), module: MBLoaderOps.ModuleInfo[ config: config, module: mth.gfi + i, resolved: nLinks = 0], mti: mti ]; ENDLOOP; gf.gfi _ gfi; gf.copied _ gf.shared _ gf.started _ gf.trapxfers _ FALSE; gf.codelinks _ NOT framelinks; gf.alloced _ inFrameHeap; gf.code.longbase _ NIL; -- to initialize both halves gf.code.out _ TRUE; gf.code.fill _ mth.code.offset; MBVM.CopyWrite[from: @gf, to: frame, nwords: SIZE[PrincOps.GlobalFrame]]; MBVM.Write[@frame.global[0], PrincOps.NullControl]; -- no control module PrintLoadmapEntry[bcd: bcd, mth: mth, frame: frame, gfiOffset: gfiOffset]; }; OtherFrameSizes: PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS [BOOL] =TRUSTED { IF mt[mth.gfi].frame = NIL THEN GetFrameSize[mth]; RETURN[FALSE] }; OtherFrameInit: PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS [BOOL] = TRUSTED { IF mt[mth.gfi].frame = NIL THEN FrameInit[mti]; RETURN[FALSE] }; ngfi _ SetupModuleTable[loadee]; mt _ loadee.mt; config _ MBLoaderOps.InputLoadState[]; loadee.gfiOffset _ gfiOffset _ MBLoaderOps.GetNextGFI[reserve: ngfi] - 1; [] _ BcdOps.ProcessFramePacks[bcd, ProcessOneFramePack]; frameSpace _ 0; framesResident _ FALSE; [] _ BcdOps.ProcessModules[bcd, OtherFrameSizes]; IF frameSpace ~= 0 THEN { -- there are frames not in frame packs [framePtr, inFrameHeap] _ MB.AllocateFrames[ size: NextMultipleOfFour[frameSpace], single: useFrameHeap, resident: framesResident OR AnyResidentGlobalFrames[loadee]]; [] _ BcdOps.ProcessModules[bcd, OtherFrameInit]}; }; ResidentFramePack: PROC [f: BcdDefs.FPHandle] RETURNS [resident: BOOL] = TRUSTED { CheckOne: PROC [bh: MB.BHandle, fph: BcdDefs.FPHandle] RETURNS [BOOL] = CHECKED { RETURN[resident _ (f = fph)]}; MB.EnumerateFramePacks[resident, CheckOne]; }; AnyResidentGlobalFrames: PROC [loadee: MB.BHandle] RETURNS [resident: BOOL] = TRUSTED { CheckOne: PROC [bh: MB.BHandle, mth: BcdDefs.MTHandle] RETURNS [BOOL] = CHECKED { RETURN[resident _ (bh = loadee)]}; MB.EnumerateGlobalFrames[resident, CheckOne]; }; NextMultipleOfFour: PROC [x: CARDINAL] RETURNS [CARDINAL] = TRUSTED INLINE { RETURN [Basics.BITAND[x+3, 177774B]]; }; PrintLoadmapEntry: PROC [ bcd: BcdDefs.BcdBase, mth: BcdDefs.MTHandle, frame: POINTER, gfiOffset: CARDINAL] = TRUSTED { ssb: BcdDefs.NameString _ LOOPHOLE[bcd + bcd.ssOffset]; map: IO.STREAM _ data.loadmap; map.PutF1[" New: g = %06n ", [cardinal[LOOPHOLE[frame, CARDINAL]]]]; FOR i: CARDINAL IN [mth.name .. mth.name+ssb.size[mth.name]) DO map.PutChar[ssb.string.text[i]]; ENDLOOP; map.PutF1[" [%n]\N", [cardinal[LOOPHOLE[PrincOps.ControlLink[procedure[gfi: gfiOffset + mth.gfi, ep: 0, tag: FALSE]], CARDINAL] ]]]; }; CMMapItem: TYPE = RECORD [ cti: BcdDefs.CTIndex, cm: PrincOps.ControlModule, depth: CARDINAL ]; AssignControlModules: PROC [loadee: MB.BHandle] RETURNS [cm: PrincOps.ControlModule] = TRUSTED { bcd: BcdDefs.BcdBase = loadee.bcd; mt: MB.MT = loadee.mt; ctb: BcdDefs.Base _ LOOPHOLE[bcd + bcd.ctOffset]; mtb: BcdDefs.Base _ LOOPHOLE[bcd + bcd.mtOffset]; CMMap: TYPE = RECORD [ nConfigs: CARDINAL, configs: SEQUENCE length: CARDINAL --subconfig#-- OF CMMapItem]; cmMap: REF CMMap; maxDepth: CARDINAL _ 0; cti: BcdDefs.CTIndex; EnterControlInfoForConfig: PROC [ cth: BcdDefs.CTHandle, cti: BcdDefs.CTIndex] RETURNS [stop: BOOL] = TRUSTED { cm: PrincOps.ControlModule; depth: CARDINAL _ 0; -- depth of config in Bcd's config structure IF cth.nControls = 0 THEN cm _ PrincOps.NullControl ELSE { cm _ AllocateControlList[cth.nControls]; MBVM.Write[@cm.list.nModules, (cth.nControls + 1)]; FOR i: CARDINAL IN [0..cth.nControls) DO WITH cItem: cth.controls[i] SELECT FROM module => MBVM.Write[@cm.list.frames[i+1], mt[mtb[cItem.mti].gfi].frame]; config => MB.Error["Configurations in control lists aren't supported yet."]; ENDCASE; ENDLOOP; cm.multiple _ TRUE; FOR c: BcdDefs.CTIndex _ ctb[cti].config, ctb[c].config UNTIL c = BcdDefs.CTNull DO depth _ depth + 1; ENDLOOP; }; maxDepth _ MAX[maxDepth, depth]; cmMap.configs[cmMap.nConfigs] _ CMMapItem[cti: cti, cm: cm, depth: depth]; cmMap.nConfigs _ cmMap.nConfigs + 1; RETURN[FALSE] }; IF bcd.nModules = 1 THEN { frame: PrincOps.GlobalFrameHandle _ mt[1].frame; MBVM.Write[@frame.global[0], PrincOps.NullControl]; RETURN [[frame[frame]]] }; cmMap _ NEW[CMMap[bcd.nConfigs]]; cmMap.nConfigs _ 0; [] _ BcdOps.ProcessConfigs[bcd, EnterControlInfoForConfig]; FOR depth: CARDINAL DECREASING IN [0..maxDepth] DO FOR index: CARDINAL IN [0..cmMap.nConfigs) DO list, listHead, oldCm: PrincOps.ControlModule; SetModulesControl: PROC [ mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS [stop: BOOL] = TRUSTED { frame: PrincOps.GlobalFrameHandle _ mt[mth.gfi].frame; IF mth.config ~= cti THEN RETURN[FALSE]; IF MBVM.Read[@frame.global[0]] = PrincOps.NullControl THEN MBVM.Write[@frame.global[0], GetLink[cm]]; RETURN[FALSE] }; IF cmMap.configs[index].depth ~= depth OR (cm _ cmMap.configs[index].cm) = PrincOps.NullControl THEN LOOP; list _ cm; list.multiple _ FALSE; cti _ cmMap.configs[index].cti; listHead _ SetLink[cm: cm, frame: MBVM.Read[@list.list.frames[1]]]; MBVM.Write[@list.list.frames[1], listHead]; -- restore old value FOR i: CARDINAL IN [2..ctb[cti].nControls+1) DO oldCm _ SetLink[cm: GetLink[listHead], frame: MBVM.Read[@list.list.frames[i]]]; MBVM.Write[@list.list.frames[i], oldCm]; ENDLOOP; [] _ BcdOps.ProcessModules[bcd, SetModulesControl]; ENDLOOP; ENDLOOP; FOR index: CARDINAL IN [0..cmMap.nConfigs) DO parent: CARDINAL; list: PrincOps.ControlModule _ cmMap.configs[index].cm; IF list = PrincOps.NullControl THEN LOOP; list.multiple _ FALSE; IF (cti _ ctb[cmMap.configs[index].cti].config) = BcdDefs.CTNull THEN cm _ PrincOps.NullControl ELSE { FOR parent IN [0..cmMap.nConfigs) DO IF cmMap.configs[parent].cti = cti THEN EXIT; ENDLOOP; cm _ GetLink[cmMap.configs[parent].cm]; }; MBVM.Write[@list.list.frames[0], cm]; ENDLOOP; FOR i: CARDINAL IN [0..cmMap.nConfigs) DO IF ctb[cmMap.configs[i].cti].config = BcdDefs.CTNull THEN { cm _ GetLink[cmMap.configs[i].cm]; EXIT }; ENDLOOP; }; AllocFault: PUBLIC ERROR = CODE; Alloc: PUBLIC PROC [fsi: CARDINAL] RETURNS [p: POINTER] = TRUSTED { DO p _ MBVM.Read[PrincOps.AV + fsi]; SELECT LOOPHOLE[p, CARDINAL] MOD 4 FROM 0 => EXIT; -- a free frame 1, 3 => ERROR AllocFault; 2 => fsi _ LOOPHOLE[p, CARDINAL]/4; -- use an fsi for larger frames ENDCASE; ENDLOOP; MBVM.Write[PrincOps.AV + fsi, MBVM.Read[p]]; RETURN[p] }; AllocateControlList: PUBLIC PROC [nControls: CARDINAL] RETURNS [cm: PrincOps.ControlModule] = TRUSTED { fsi: CARDINAL = PrincOpsUtils.MakeFsi[words: (nControls + 1) + 1]; cm.list _ Alloc[fsi ! AllocFault => MB.Error[IO.PutFR1["Larger frame heap needed (fsi=%d) for control list", [cardinal[fsi]]]] ]; }; GetLink: PROC [ cm: PrincOps.ControlModule] RETURNS [--frame--PrincOps.ControlModule] = TRUSTED { list: PrincOps.ControlModule; DO -- search up backward pointers for the actual frame to start IF ~cm.multiple THEN RETURN[cm]; list _ cm; list.multiple _ FALSE; cm _ MBVM.Read[@list.list.frames[1]]; ENDLOOP; }; SetLink: PROC [cm: PrincOps.ControlModule, frame: PrincOps.GlobalFrameHandle] RETURNS [PrincOps.ControlModule] = TRUSTED { old: PrincOps.ControlModule = MBVM.Read[@frame.global[0]]; MBVM.Write[@frame.global[0], cm]; RETURN[IF old ~= PrincOps.NullControl THEN old ELSE [frame[frame]]] }; JustRelocateLinks: PROC [loadee: MB.BHandle] = TRUSTED { bcd: BcdDefs.BcdBase = loadee.bcd; mt: MB.MT = loadee.mt; realLinks: MBLoaderOps.RealLinks = NEW[MBLoaderOps.RealLinksTable]; RelocateLinksForModule: PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS [BOOL] = TRUSTED { mi: BcdDefs.ModuleIndex = mth.gfi; frame: PrincOps.GlobalFrameHandle _ mt[mi].frame; resolved: BOOL _ TRUE; virtualLinks: MBLoaderOps.VirtualLinks _ MBLoaderOps.GetVirtualLinks[loadee, mth]; IF LENGTH[virtualLinks] ~= 0 THEN { -- relocate external links FOR i: CARDINAL IN [0..LENGTH[virtualLinks]) DO link: BcdDefs.Link _ virtualLinks[i]; SELECT link.vtag FROM proc1, proc0 => IF link.gfi >= bcd.firstdummy THEN {resolved _ FALSE; realLinks[i] _ PrincOps.UnboundLink} ELSE realLinks[i] _ ConvertLink[link]; var => IF link.gfi >= bcd.firstdummy THEN {resolved _ FALSE; realLinks[i] _ PrincOps.NullLink} ELSE realLinks[i] _ ConvertVariableLink[link]; ENDCASE => {resolved _ FALSE; realLinks[i] _ PrincOps.NullLink}; ENDLOOP; MBLoaderOps.WriteLinks[loadee: loadee, mth: mth, links: realLinks]; }; FOR i: CARDINAL IN [mi..mi+mth.ngfi) DO info: MBLoaderOps.ModuleInfo _ MBLoaderOps.GetModule[i]; info.resolved _ resolved; MBLoaderOps.EnterModule[i, info]; ENDLOOP; RETURN[FALSE] }; ConvertVariableLink: PROC [link: BcdDefs.Link] RETURNS [PrincOps.ControlLink] = TRUSTED { mth: BcdDefs.MTHandle; frame: PrincOps.GlobalFrameHandle; mi: BcdDefs.ModuleIndex = link.gfi; evb: BcdDefs.Base = LOOPHOLE[bcd + bcd.evOffset]; vp: CARDINAL; [mth: mth, frame: frame] _ mt[mi]; IF mi >= bcd.firstdummy THEN RETURN[PrincOps.NullLink]; vp _ BcdDefs.VarLimit*(mi - mth.gfi) + link.var; IF vp = 0 THEN RETURN[LOOPHOLE[frame]]; IF mth.variables = BcdDefs.EVNull THEN RETURN[PrincOps.NullLink] ELSE RETURN[LOOPHOLE[frame + evb[mth.variables].offsets[vp]]] }; MBLoaderOps.UpdateLoadState[FIRST[MBLoaderOps.ConfigIndex], loadee]; [] _ BcdOps.ProcessModules[bcd, RelocateLinksForModule]; }; ConvertLink: PROC [bl: BcdDefs.Link] RETURNS [PrincOps.ControlLink] = INLINE { RETURN[LOOPHOLE[bl]]; }; BuildTopLevelControlList: PROC RETURNS [cm: PrincOps.ControlModule] = TRUSTED { nControls: CARDINAL _ 0; index: CARDINAL _ 1; CountControls: PROC [bh: MB.BHandle, cth: BcdDefs.CTHandle] RETURNS [BOOL _ FALSE] = TRUSTED { IF cth.nControls ~= 0 THEN nControls _ nControls + 1; }; FillInControls: PROC [bh: MB.BHandle, cth: BcdDefs.CTHandle] RETURNS [BOOL _ FALSE] = TRUSTED { IF cth.nControls ~= 0 THEN { FOR i: NAT IN [0..controlModules.length) DO IF controlModules[i].bh = bh THEN { MBVM.Write[@cm.list.frames[index], controlModules[i].cm]; index _ index + 1; EXIT }; ENDLOOP; }; }; [] _ MB.EnumerateControlList[CountControls]; IF nControls = 0 THEN RETURN[PrincOps.NullControl]; cm _ AllocateControlList[nControls]; MBVM.Write[@cm.list.nModules, nControls + 1]; MBVM.Write[@cm.list.frames[0], PrincOps.NullControl]; [] _ MB.EnumerateControlList[FillInControls]; cm.multiple _ TRUE; }; END. HMBLoaderCore.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Sandman on 6-Aug-81 15:41:04 Lewis on 23-Sep-81 15:59:10 Levin on January 16, 1984 9:41 am Russ Atkinson (RRA) May 13, 1985 11:27:22 pm PDT buffer is too large; free excess buffer too small; grow it. The firstdummy field in the bcd header is not to be trusted. If the bcd consists of a single module, it was probably generated by the Compiler. The Compiler sets the firstdummy field to an arbitrary value which is higher than the number of gfis needed to load the module. The ngfi field of the module table entry is the correct one to use. For a multi-module bcd (created by the Binder), bcd.firstdummy-1 is the number of gfis needed. The code sidesteps this ugliness by using a two-pass algorithm to set up the module table. allocate global frame record global frame handle in module table (mt) enter into GFT, and loadstate if not making germ initialize global frame gfi 0 in each input BCD is not used. Thus, gfiOffset is set one less than the first gfi actually allocated to us, since all subsequent indexing uses the 0-origin gfi's in the input BCD. control module information for each (sub)config in bcd list.frames[0] is bkwds pointer to cm for enclosing config (st. first) create subconfig# -> (subconfig & control module info) map list.frames[1]'s global[0] has ControlModule (possibly list) for config for each module, set global[0] to the actual cm frame for config for each config, set backwards pointer to cm frame for the enclosing config set "cm" to the actual cm frame for the outermost config Ê¡˜codešœ™Kšœ Ïmœ1™K˜?Kšœ˜K˜—š Ÿ œžœ žœ žœ%žœ˜\K˜"Kšœžœ˜1Kšœžœžœ˜ Kšœžœ˜Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜Kšœžœ˜(Kšœ žœ˜Kšœžœžœ˜š Ÿœžœ.žœžœžœ˜bK˜Kšœžœ˜šžœžœžœž˜%K˜#Kšžœ˜—šœžœ˜,K˜&K˜Kšœžœ œ˜T—šžœžœžœž˜%K˜Kšžœ˜—Kšžœžœ˜ Kšœ˜—šŸ œžœžœ˜6šžœžœžœ ˜DK˜B—K˜