-- 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...