-- File: ModuleNameImpl.mesa
-- last edited by Levin:  10-Mar-81 15:06:03
-- edited by Brotz, April 2, 1981  9:14 AM

DIRECTORY
  BcdDefs USING [MTIndex],
  BcdOps USING [BcdBase, MTHandle, NameString, ProcessModules],
  ControlDefs USING [
    ControlLink, FrameCodeBase, GFT, GFTIndex, GFTItem, GlobalFrameHandle,
    NullGlobalFrame],
  FrameDefs USING [GlobalFrame, InvalidGlobalFrame, SwapInCode],
  FrameOps USING [CodeHandle],
  LoadStateOps USING [
    AcquireBcd, ConfigIndex, InputLoadState, MapRealToConfig, NullConfig, ReleaseBcd,
    ReleaseLoadState],
  ModuleName USING [],
  SDDefs USING [SD, sGFTLength],
  SegmentDefs USING [FileSegmentHandle, Unlock],
  String USING [AppendChar, AppendOctal, AppendSubString, SubStringDescriptor];

ModuleNameImpl: PROGRAM
  IMPORTS BcdOps, FrameDefs, FrameOps, LoadStateOps, SegmentDefs, String
  EXPORTS ModuleName =

  BEGIN OPEN ControlDefs;
  

  ControlLinkToModuleName: PUBLIC PROCEDURE [link: ControlLink, s: STRING] =
    BEGIN OPEN FrameDefs;
    s.length ← 0;
    GlobalFrameToModuleName
      [GlobalFrame[link ! InvalidGlobalFrame => CONTINUE], s
        ! ANY => CONTINUE];
    END;

  GlobalFrameToModuleName: PUBLIC PROCEDURE [f: GlobalFrameHandle, s: STRING] =
    BEGIN
    s.length ← 0;
    FrameToName[f, s ! ANY => CONTINUE];
    IF s.length = 0 THEN {String.AppendChar[s, '?]; AppendBracketed[s, f]};
    END;

  FrameToName: PROCEDURE [f: GlobalFrameHandle, s: STRING] =
    BEGIN OPEN BcdDefs, BcdOps, LoadStateOps;
    cgfi: GFTIndex;
    config: ConfigIndex;
    ssb: NameString;
    bcd: BcdBase;
    FindModuleString: PROCEDURE [mth: MTHandle, mti: MTIndex] RETURNS [BOOLEAN] =
      BEGIN
      ssd: String.SubStringDescriptor;
      IF cgfi IN [mth.gfi..mth.gfi+mth.ngfi) THEN
	BEGIN OPEN String;
	ssd ← [base: @ssb.string, offset: mth.name, length: ssb.size[mth.name]];
	AppendSubString[s, @ssd];
	IF f.copied THEN AppendBracketed[s, f.gfi];
	RETURN[TRUE]
	END;
      RETURN[FALSE];
      END;
    [] ← InputLoadState[];
    [cgfi, config] ← MapRealToConfig[(IF f.copied THEN FindOriginal[f] ELSE f).gfi];
    IF config = NullConfig THEN {ReleaseLoadState[]; RETURN};
    bcd ← AcquireBcd[config];
    ssb ← LOOPHOLE[bcd + bcd.ssOffset];
    [] ← ProcessModules[bcd, FindModuleString];
    ReleaseBcd[bcd];
    ReleaseLoadState[];
    END;

  AppendBracketed: PROCEDURE [s: STRING, value: UNSPECIFIED] =
    {OPEN String; AppendChar[s, '[]; AppendOctal[s, value]; AppendChar[s, ']]};

  FindOriginal: PROCEDURE [copy: GlobalFrameHandle] RETURNS [GlobalFrameHandle] =
    BEGIN
    Original: PROCEDURE [f: GlobalFrameHandle] RETURNS [BOOLEAN] =
      {RETURN[f ~= copy AND ~f.copied AND SameModule[copy, f]]};
    RETURN[ReverseEnumerateGFT[Original]]
    END;

  SameModule: PROCEDURE [f1, f2: GlobalFrameHandle] RETURNS [same: BOOLEAN] =
    BEGIN
    o1, o2: BOOLEAN;
    seg1, seg2: SegmentDefs.FileSegmentHandle;
    fcb1, fcb2: FrameCodeBase;
    seg1 ← FrameOps.CodeHandle[f1];
    seg2 ← FrameOps.CodeHandle[f2];
    IF seg1 ~= seg2 THEN RETURN[FALSE];
    fcb1 ← f1.code; fcb2 ← f2.code;
    IF (o1 ← f1.code.out) AND (o2 ← f2.code.out) THEN RETURN[f1.code = f2.code];
    FrameDefs.SwapInCode[f1];
    FrameDefs.SwapInCode[f2];
    same ← f1.code = f2.code;
    SegmentDefs.Unlock[seg1];
    SegmentDefs.Unlock[seg2];
    IF ~f1.started THEN f1.code ← fcb1;
    IF ~f2.started THEN f2.code ← fcb2;
    END;

  ReverseEnumerateGFT: PROCEDURE [proc: PROCEDURE [GlobalFrameHandle] RETURNS [BOOLEAN]]
    RETURNS [frame: GlobalFrameHandle] =
    BEGIN
    gft: POINTER TO ARRAY [0..0) OF GFTItem ← GFT;
    FOR i: GFTIndex DECREASING IN [0..SDDefs.SD[SDDefs.sGFTLength]) DO
      frame ← gft[i].frame;
      IF frame ~= NullGlobalFrame AND gft[i].epbase = 0 AND proc[frame] THEN RETURN;
      ENDLOOP;
    RETURN[NullGlobalFrame]
    END;

  END.