-- UnNewConfig.mesa; edited by Geschke on September 7, 1978 3:29 PM
DIRECTORY
BcdDefs: FROM "bcddefs" USING [MTHandle, MTIndex, UnboundLink],
CodeDefs: FROM "codedefs" USING [CodeHandle],
ControlDefs: FROM "controldefs" USING [
ControlLink, FrameCodeBase, Free, GFT, GFTIndex, GFTItem,
GlobalFrameHandle, NullGlobalFrame, TrapLink],
FrameDefs: FROM "framedefs" USING [
EnumerateGlobalFrames, GlobalFrame, LockCode, UnlockCode, UnNew],
GlobalFrameDefs: FROM "globalframedefs" USING [GlobalFrameHandle],
InlineDefs: FROM "inlinedefs" USING [BITAND],
LoaderBcdUtilDefs: FROM "loaderbcdutildefs" USING [
BcdBase, EnumerateModuleTable, ReleaseBcdSeg, SetUpBcd],
LoaderDefs: FROM "loaderdefs",
LoadStateDefs: FROM "loadstatedefs" USING [
BcdAddress, BcdSegFromLoadState, ConfigIndex, EnumerateLoadStateBcds,
InitializeRelocation, InputLoadState, MapRealToConfig, ReleaseLoadState,
ReleaseRelocation, Relocation, RemoveConfig, SetUnresolvedImports],
SegmentDefs: FROM "segmentdefs" USING [
DeleteFileSegment, FileSegmentHandle, SwapError, SwapIn, SwapUp, Unlock],
SystemDefs: FROM "systemdefs" USING [FreeSegment],
XMesaDefs: FROM "xmesadefs" USING [LowHalfPtr, XCOPY, XFileSegmentAddress];
UnNewConfig: PROGRAM
IMPORTS CodeDefs, FrameDefs, LoadStateDefs, LoaderBcdUtilDefs, SegmentDefs, SystemDefs, XMesaDefs
EXPORTS LoaderDefs = BEGIN
ConfigIndex: TYPE = LoadStateDefs.ConfigIndex;
Relocation: TYPE = LoadStateDefs.Relocation;
BcdBase: TYPE = LoaderBcdUtilDefs.BcdBase;
GlobalFrameHandle: TYPE = ControlDefs.GlobalFrameHandle;
NullGlobalFrame: GlobalFrameHandle = ControlDefs.NullGlobalFrame;
UnNewConfig: PUBLIC PROCEDURE [frame: GlobalFrameHandle] =
BEGIN OPEN LoadStateDefs;
config: ConfigIndex;
rel: Relocation;
bcdseg: SegmentDefs.FileSegmentHandle;
bcd: BcdBase;
FindOriginal: PROCEDURE [f: GlobalFrameHandle] RETURNS [BOOLEAN] =
BEGIN
IF f # frame THEN
BEGIN
IF SameCode[frame, f] = identical AND ~f.copied THEN
BEGIN frame ← f; RETURN[TRUE] END;
END;
RETURN[FALSE];
END;
IF frame.copied THEN [] ← FrameDefs.EnumerateGlobalFrames[FindOriginal];
[] ← InputLoadState[];
[config: config] ← MapRealToConfig[frame.gfi];
bcdseg ← BcdSegFromLoadState[config];
bcd ← LoaderBcdUtilDefs.SetUpBcd[bcdseg];
rel ← InitializeRelocation[config];
UnBindConfig[config, bcd, rel];
CleanupFrames[rel];
CleanupGFT[rel];
RemoveConfig[rel, config];
ReleaseRelocation[rel];
ReleaseLoadState[];
LoaderBcdUtilDefs.ReleaseBcdSeg[bcdseg];
RETURN
END;
CodeMatch: TYPE = {identical, same, different};
SameCode: PROCEDURE [f1, f2: GlobalFrameHandle] RETURNS [CodeMatch] =
BEGIN
o1, o2: CARDINAL;
fcb: ControlDefs.FrameCodeBase;
seg1: SegmentDefs.FileSegmentHandle ← CodeDefs.CodeHandle[f1];
seg2: SegmentDefs.FileSegmentHandle ← CodeDefs.CodeHandle[f2];
IF seg1 # seg2 THEN RETURN[different];
IF seg1.swappedin THEN
BEGIN
SegmentDefs.SwapIn[seg1];
o1 ← LOOPHOLE[f1, GlobalFrameDefs.GlobalFrameHandle].code.shortCodebase -
XMesaDefs.LowHalfPtr[XMesaDefs.XFileSegmentAddress[seg1]];
SegmentDefs.Unlock[seg1];
END
ELSE
BEGIN
fcb ← f1.code;
fcb.swappedout ← FALSE;
o1 ← fcb.offset;
END;
IF seg2.swappedin THEN
BEGIN
SegmentDefs.SwapIn[seg2];
o2 ← LOOPHOLE[f2, GlobalFrameDefs.GlobalFrameHandle].code.shortCodebase -
XMesaDefs.LowHalfPtr[XMesaDefs.XFileSegmentAddress[seg2]];
SegmentDefs.Unlock[seg2];
END
ELSE
BEGIN
fcb ← f2.code;
fcb.swappedout ← FALSE;
o2 ← fcb.offset;
END;
RETURN[IF o1 = o2 THEN identical ELSE same];
END;
CleanupFrames: PROCEDURE [rel: Relocation] =
BEGIN
frame: GlobalFrameHandle;
i, ep: CARDINAL;
nlinks: [0..256);
alloced: BOOLEAN ← FALSE;
DestroyCopy: PROCEDURE [f: GlobalFrameHandle] RETURNS [BOOLEAN] =
BEGIN
FrameDefs.UnNew[f];
RETURN[FALSE];
END;
FOR i IN [1..LENGTH[rel]) DO
[frame: frame, epbase: ep] ← ControlDefs.GFT[rel[i]];
IF frame = NullGlobalFrame OR ep # 0 THEN LOOP;
IF frame.alloced THEN
BEGIN
FrameDefs.LockCode[frame];
nlinks ← frame.code.prefix.nlinks;
FrameDefs.UnlockCode[frame];
END;
IF ~EnumerateCopies[frame, DestroyCopy].shared THEN
SegmentDefs.DeleteFileSegment[CodeDefs.CodeHandle[frame] !
SegmentDefs.SwapError => CONTINUE];
IF frame.alloced THEN
BEGIN
Align: PROCEDURE [POINTER, WORD] RETURNS [POINTER] =
LOOPHOLE[InlineDefs.BITAND];
IF frame.codelinks THEN ControlDefs.Free[frame]
ELSE ControlDefs.Free[Align[frame - nlinks, 177774B]];
alloced ← TRUE;
END;
ENDLOOP;
IF ~alloced THEN SystemDefs.FreeSegment[frame];
RETURN
END;
NextMultipleOfFour: PROCEDURE [n: UNSPECIFIED] RETURNS [UNSPECIFIED] =
BEGIN
RETURN[n+InlineDefs.BITAND[-n, 3B]]
END;
UnBindConfig: PROCEDURE [config: ConfigIndex, bcd: BcdBase, rel: Relocation] =
BEGIN OPEN LoadStateDefs;
bindeeRel: Relocation;
nowUnresolved: BOOLEAN;
UnBind: PROCEDURE [c: ConfigIndex, b: BcdAddress] RETURNS [BOOLEAN] =
BEGIN
bcdseg: SegmentDefs.FileSegmentHandle;
bindee: BcdBase;
IF c = config THEN RETURN[FALSE];
bcdseg ← BcdSegFromLoadState[c];
bindee ← LoaderBcdUtilDefs.SetUpBcd[bcdseg];
IF bindee.nImports # 0 THEN
BEGIN
bindeeRel ← InitializeRelocation[c];
nowUnresolved ← FALSE;
[] ← LoaderBcdUtilDefs.EnumerateModuleTable[bindee, AdjustLinks];
SetUnresolvedImports[c, nowUnresolved];
ReleaseRelocation[bindeeRel];
END;
LoaderBcdUtilDefs.ReleaseBcdSeg[bcdseg];
RETURN[FALSE]
END;
AdjustLinks: PROCEDURE [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex]
RETURNS [BOOLEAN] =
BEGIN
frame: GlobalFrameHandle = ControlDefs.GFT[bindeeRel[mth.gfi]].frame;
nlinks: CARDINAL = mth.frame.length;
changed: BOOLEAN;
AdjustCopies: PROCEDURE [f: GlobalFrameHandle] RETURNS [BOOLEAN] =
BEGIN
[] ← AdjustFrame[f, mth.code.offset, nlinks];
RETURN[FALSE];
END;
IF frame = NullGlobalFrame OR nlinks = 0 THEN RETURN[FALSE];
changed ← AdjustFrame[frame, mth.code.offset, nlinks];
IF changed AND frame.shared AND ~frame.codelinks THEN
[] ← EnumerateCopies[frame, AdjustCopies];
IF changed THEN nowUnresolved ← TRUE;
RETURN[FALSE]
END;
AdjustFrame: PROCEDURE [frame: GlobalFrameHandle, offset, nlinks: CARDINAL]
RETURNS [changed: BOOLEAN] =
BEGIN
seg: SegmentDefs.FileSegmentHandle = CodeDefs.CodeHandle[frame];
linkbase: LONG POINTER TO ControlDefs.ControlLink;
i: CARDINAL;
changed ← FALSE;
IF frame.codelinks THEN
BEGIN OPEN SegmentDefs;
SwapIn[seg];
linkbase ← XMesaDefs.XFileSegmentAddress[seg] + offset;
END
ELSE linkbase ← LONG[LOOPHOLE[frame, POINTER TO ControlDefs.ControlLink]];
FOR i IN [1..nlinks] DO
BEGIN OPEN ControlDefs;
link: ControlLink;
XMesaDefs.XCOPY[to: LONG[@link], from: linkbase-i, nwords: SIZE[ControlLink]];
IF BoundHere[link] THEN
BEGIN
tlink: ControlLink ← (SELECT link.tag FROM
frame => TrapLink, ENDCASE => BcdDefs.UnboundLink);
XMesaDefs.XCOPY[from: LONG[@tlink], to: linkbase-i, nwords: SIZE[ControlLink]];
changed ← TRUE;
END;
END;
ENDLOOP;
IF frame.codelinks THEN
BEGIN OPEN SegmentDefs;
IF changed THEN
BEGIN seg.write ← TRUE; SwapUp[seg]; seg.write ← FALSE; END;
Unlock[seg];
END;
RETURN
END;
BoundHere: PROCEDURE [link: ControlDefs.ControlLink] RETURNS [BOOLEAN] =
BEGIN
i: CARDINAL;
gfi: ControlDefs.GFTIndex;
SELECT link.tag FROM
unbound => RETURN[FALSE];
ENDCASE => gfi ← FrameDefs.GlobalFrame[link].gfi;
FOR i IN [0..LENGTH[rel]) DO
IF rel[i] = gfi THEN RETURN[TRUE];
ENDLOOP;
RETURN[FALSE];
END;
IF bcd.nExports = 0 AND bcd.nModules # 1 THEN RETURN;
[] ← EnumerateLoadStateBcds[recentfirst, UnBind];
RETURN
END;
CleanupGFT: PROCEDURE [rel: Relocation] =
BEGIN OPEN ControlDefs;
i: CARDINAL;
FOR i IN [1..LENGTH[rel]) DO
GFT[rel[i]] ← GFTItem[NullGlobalFrame, 0];
ENDLOOP;
END;
EnumerateCopies: PROCEDURE [frame: GlobalFrameHandle,
proc: PROCEDURE [GlobalFrameHandle] RETURNS [BOOLEAN]]
RETURNS [result: GlobalFrameHandle, shared: BOOLEAN] =
BEGIN
FindCopies: PROCEDURE [f: GlobalFrameHandle] RETURNS [BOOLEAN] =
BEGIN
IF f = frame THEN RETURN[FALSE];
SELECT SameCode[frame, f] FROM
identical =>
BEGIN
shared ← TRUE;
IF f.copied AND proc[f] THEN RETURN[TRUE];
END;
same => shared ← TRUE;
ENDCASE;
RETURN[FALSE];
END;
shared ← FALSE;
RETURN[FrameDefs.EnumerateGlobalFrames[FindCopies], shared];
END;
END...