-- UnNewConfig.mesa; edited by Johnsson on October 27, 1980 2:08 PM -- Copyright Xerox Corporation 1979, 1980 DIRECTORY BcdDefs USING [Base, MTIndex], BcdOps USING [BcdBase, MTHandle, ProcessModules], ControlDefs USING [ ControlLink, FrameCodeBase, GFT, GFTIndex, GFTItem, GFTNull, GlobalFrameHandle, NullGlobalFrame, PrefixHandle, PrefixInfo, TrapLink, UnboundLink], FrameDefs USING [EnumerateGlobalFrames, GlobalFrame, SwapInCode, UnNew], FrameOps USING [CodeHandle, Free], InlineDefs USING [BITAND], LoaderOps USING [CloseLinkSpace, OpenLinkSpace, ReadLink, WriteLink], LoadStateFormat USING [ModuleInfo], LoadStateOps USING [ AcquireBcd, ConfigIndex, EnterModule, EnumerateBcds, GetMap, GetModule, InputLoadState, MapRealToConfig, ReleaseBcd, ReleaseLoadState, ReleaseMap, Map, RemoveConfig], Mopcodes USING [zRBL], SegmentDefs USING [ DataSegmentAddress, DeleteFileSegment, FileSegmentHandle, SwapError, Unlock, VMtoDataSegment], SystemDefs USING [FreeSegment, SegmentSize]; UnNewConfig: PROGRAM IMPORTS BcdOps, FrameDefs, FrameOps, InlineDefs, LoaderOps, LoadStateOps, SegmentDefs, SystemDefs EXPORTS FrameDefs = BEGIN OPEN ControlDefs; ConfigIndex: TYPE = LoadStateOps.ConfigIndex; Map: TYPE = LoadStateOps.Map; BcdBase: TYPE = BcdOps.BcdBase; GlobalFrameHandle: TYPE = ControlDefs.GlobalFrameHandle; NullGlobalFrame: GlobalFrameHandle = ControlDefs.NullGlobalFrame; FileSegmentHandle: TYPE = SegmentDefs.FileSegmentHandle; UnNewConfig: PUBLIC PROCEDURE [link: UNSPECIFIED] = BEGIN OPEN LoadStateOps; config: ConfigIndex; map: Map; bcd: BcdBase; frame: GlobalFrameHandle _ FrameDefs.GlobalFrame[link]; 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]; bcd _ AcquireBcd[config]; map _ GetMap[config]; UnBindConfig[config, bcd, map]; CleanupFrames[map]; CleanupGFT[map]; RemoveConfig[map, config]; ReleaseMap[map]; ReleaseBcd[bcd]; ReleaseLoadState[]; RETURN END; CodeMatch: TYPE = {identical, same, different}; SameCode: PROCEDURE [f1, f2: GlobalFrameHandle] RETURNS [cm: CodeMatch] = BEGIN o1, o2: BOOLEAN; seg1, seg2: FileSegmentHandle; fcb1, fcb2: ControlDefs.FrameCodeBase; seg1 _ FrameOps.CodeHandle[f1]; seg2 _ FrameOps.CodeHandle[f2]; fcb1 _ f1.code; fcb2 _ f2.code; IF seg1 = NIL AND seg2 = NIL THEN BEGIN fcb1.out _ fcb2.out _ FALSE; RETURN[IF fcb1 = fcb2 THEN identical ELSE different]; END; IF seg1 # seg2 THEN RETURN[different]; IF (o1 _ f1.code.out) AND (o2 _ f2.code.out) THEN RETURN[IF f1.code = f2.code THEN identical ELSE same]; FrameDefs.SwapInCode[f1]; FrameDefs.SwapInCode[f2]; cm _ IF f1.code = f2.code THEN identical ELSE same; SegmentDefs.Unlock[seg1]; SegmentDefs.Unlock[seg2]; IF ~f1.started THEN f1.code _ fcb1; IF ~f2.started THEN f2.code _ fcb2; RETURN END; DestroyCopy: PROCEDURE [f: GlobalFrameHandle] RETURNS [BOOLEAN] = BEGIN FrameDefs.UnNew[f]; RETURN[FALSE]; END; CleanupFrames: PROCEDURE [map: Map] = BEGIN seg: FileSegmentHandle; frameSegment: POINTER _ NIL; frame: GlobalFrameHandle; i, ep: CARDINAL; nlinks: [0..256); FOR i IN [1..LENGTH[map]) DO deleteSeg: BOOLEAN _ FALSE; [frame: frame, epbase: ep] _ ControlDefs.GFT[map[i]]; IF frame = NullGlobalFrame OR ep # 0 THEN LOOP; seg _ FrameOps.CodeHandle[frame]; IF ~EnumerateCopies[frame, DestroyCopy].shared AND seg # NIL THEN deleteSeg _ TRUE; IF frame.alloced THEN BEGIN Align: PROCEDURE [POINTER, WORD] RETURNS [POINTER] = LOOPHOLE[InlineDefs.BITAND]; IF frame.codelinks THEN FrameOps.Free[frame] ELSE BEGIN nlinks _ FindNLinks[frame, seg]; FrameOps.Free[Align[frame - nlinks, 177774B]]; END; END ELSE frameSegment _ frame; IF deleteSeg THEN SegmentDefs.DeleteFileSegment[seg ! SegmentDefs.SwapError => CONTINUE]; ENDLOOP; IF frameSegment # NIL THEN SystemDefs.FreeSegment[frameSegment]; RETURN END; FindNLinks: PROCEDURE [frame: GlobalFrameHandle, seg: FileSegmentHandle] RETURNS [nlinks: CARDINAL] = BEGIN FrameDefs.SwapInCode[frame]; IF frame.code.highByte = 0 THEN BEGIN GetPrefixInfo: PROCEDURE [LONG POINTER] RETURNS [PrefixInfo] = MACHINE CODE BEGIN Mopcodes.zRBL, 1 END; prefix: PrefixInfo _ GetPrefixInfo[frame.code.longbase]; nlinks _ prefix.nlinks; END ELSE nlinks _ LOOPHOLE[frame.code.shortbase, PrefixHandle].header.info.nlinks; SegmentDefs.Unlock[seg]; RETURN; END; NextMultipleOfFour: PROCEDURE [n: UNSPECIFIED] RETURNS [UNSPECIFIED] = BEGIN RETURN[n + InlineDefs.BITAND[-n, 3B]] END; OP: TYPE = ORDERED POINTER; UnBindConfig: PROCEDURE [config: ConfigIndex, bcd: BcdBase, map: Map] = BEGIN OPEN LoadStateOps; bmap: Map; frameStart, frameEnd: OP; UnBind: PROCEDURE [c: ConfigIndex] RETURNS [BOOLEAN] = BEGIN bindee: BcdBase; IF c = config THEN RETURN[FALSE]; bindee _ AcquireBcd[c]; IF bindee.nImports # 0 THEN BEGIN bmap _ GetMap[c]; [] _ BcdOps.ProcessModules[bindee, AdjustLinks]; ReleaseMap[bmap]; END; ReleaseBcd[bindee]; RETURN[FALSE] END; AdjustLinks: PROCEDURE [mth: BcdOps.MTHandle, mti: BcdDefs.MTIndex] RETURNS [BOOLEAN] = BEGIN gfi: ControlDefs.GFTIndex = bmap[mth.gfi]; frame: GlobalFrameHandle = ControlDefs.GFT[gfi].frame; changed: BOOLEAN; AdjustCopies: PROCEDURE [f: GlobalFrameHandle] RETURNS [BOOLEAN] = BEGIN [] _ AdjustFrame[f, mth]; RETURN[FALSE]; END; IF frame = NullGlobalFrame OR mth.frame.length = 0 THEN RETURN[FALSE]; changed _ AdjustFrame[frame, mth]; IF changed AND frame.shared AND ~frame.codelinks THEN [] _ EnumerateCopies[frame, AdjustCopies]; IF changed THEN BEGIN info: LoadStateFormat.ModuleInfo _ GetModule[gfi]; info.resolved _ FALSE; EnterModule[rgfi: gfi, module: info]; END; RETURN[FALSE] END; AdjustFrame: PROCEDURE [frame: GlobalFrameHandle, mth: BcdOps.MTHandle] RETURNS [changed: BOOLEAN] = BEGIN i: CARDINAL; link: ControlDefs.ControlLink; changed _ FALSE; LoaderOps.OpenLinkSpace[frame, mth]; FOR i IN [0..mth.frame.length) DO link _ LoaderOps.ReadLink[i]; IF BoundHere[link, mth.frame.frag[i].vtag = var] THEN BEGIN link _ (SELECT link.tag FROM frame => TrapLink, ENDCASE => UnboundLink); LoaderOps.WriteLink[i, link]; changed _ TRUE; END; ENDLOOP; LoaderOps.CloseLinkSpace[frame]; RETURN END; BoundHere: PROCEDURE [link: ControlLink, var: BOOLEAN] RETURNS [BOOLEAN] = BEGIN OPEN FrameDefs; i: CARDINAL; gfi: GFTIndex _ GFTNull; IF var THEN RETURN[LOOPHOLE[link, OP] IN [frameStart..frameEnd)]; SELECT link.tag FROM procedure => gfi _ link.gfi; ENDCASE => RETURN[FALSE]; FOR i IN [1..LENGTH[map]) DO IF map[i] = gfi THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; END; IF bcd.nExports = 0 AND bcd.nModules # 1 THEN RETURN; frameStart _ LOOPHOLE[GFT[map[1]].frame]; IF bcd.nModules = 1 THEN BEGIN OPEN BcdDefs; mth: BcdOps.MTHandle = @LOOPHOLE[bcd + bcd.mtOffset, Base][FIRST[MTIndex]]; frameEnd _ LOOPHOLE[frameStart + mth.framesize] END ELSE BEGIN OPEN SegmentDefs; frameStart _ LOOPHOLE[DataSegmentAddress[VMtoDataSegment[frameStart]]]; frameEnd _ LOOPHOLE[frameStart + SystemDefs.SegmentSize[frameStart]]; END; [] _ EnumerateBcds[recentfirst, UnBind]; RETURN END; CleanupGFT: PROCEDURE [map: Map] = BEGIN OPEN ControlDefs; i: CARDINAL; FOR i IN [1..LENGTH[map]) DO GFT[map[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; IF ~frame.shared THEN RETURN[NIL, FALSE]; RETURN[FrameDefs.EnumerateGlobalFrames[FindCopies], shared]; END; END...