-- SymsHot.Mesa  Edited by:
  -- Bruce September 11, 1980  11:23 AM
  -- Sandman July 18, 1980  8:50 AM

DIRECTORY
  DSymOps USING [AddItem, AttachSyms],
  DSyms USING [GFHandle, HTIndex, Item, MDIndex, NoFGT],
  Frames,
  Gf USING [Check, Frame],
  Lookup USING [Fail, HTIndex, HtiToString],
  MachineDefs USING [GFHandle],
  Symbols USING [HTIndex, HTNull, MDIndex, MDNull, MDRecord, mdType, OwnMdi],
  SymbolTable USING [Missing],
  Table USING [Base, Bounds];

SymsHot: PROGRAM
  IMPORTS DSymOps, DSyms, Frames, Gf, Lookup, SymbolTable, Table
  EXPORTS DSymOps, DSyms =
  BEGIN OPEN DSymOps, DSyms, MachineDefs;

  Shared: PUBLIC SIGNAL = CODE;
  Head: PUBLIC Item ← NIL;
  ZeroMdi: ERROR = CODE;
  SymbolTableProblem: ERROR = CODE;

  Enumerate: PUBLIC PROC [proc: PROCEDURE [Item] RETURNS [BOOLEAN]]
      RETURNS [syms: Item] =
    BEGIN
    last: Item;
    FOR syms ← Head, syms.link UNTIL syms = NIL DO
      IF proc[syms] THEN
	BEGIN
	IF syms = Head THEN RETURN;
	last.link ← syms.link; syms.link ← Head; Head ← syms;
	RETURN
	END;
      last ← syms;
      ENDLOOP;
    END;
  
  FindMod: PUBLIC PROC [name: HTIndex] RETURNS [Item] =
    BEGIN OPEN Symbols;
    mdb: Table.Base;
    length: CARDINAL;
    mdi: MDIndex;
    [mdb,length] ← Table.Bounds[Symbols.mdType];
    FOR mdi ← OwnMdi, mdi+SIZE[MDRecord] UNTIL
    LOOPHOLE[mdi,CARDINAL] = length DO
      IF mdb[mdi].moduleId = name THEN RETURN[FindMdi[mdi]];
      ENDLOOP;
    RETURN[NIL];
    END;

  FindMdi: PUBLIC PROC [mdi: MDIndex] RETURNS [Item] =
    BEGIN
    Find: PROC [d: Item] RETURNS[BOOLEAN] = 
      BEGIN
      WITH sym: d SELECT FROM
	hash => RETURN[FALSE];
	mod =>
	  IF mdi # sym.mdi THEN RETURN[FALSE]
	  ELSE {IF sym.shared THEN ERROR Shared; RETURN[TRUE]};
	ENDCASE => ERROR;
      END;
    RETURN[Enumerate[Find]];
    END;

  FindFrame: PUBLIC PROC [gf: MachineDefs.GFHandle] RETURNS [i: Item] =
    BEGIN
    Find: PROC [d: Item] RETURNS[BOOLEAN] = {RETURN[gf = d.gf]};
    RETURN[Enumerate[Find]];
    END;

  ModuleMdi: PUBLIC PROC [hti: HTIndex, fgt: BOOLEAN ← FALSE]
    RETURNS [MDIndex] =
    BEGIN
    syms: Item;
    gf: GFHandle ← NIL;
    mod: STRING ← [40];
    Lookup.HtiToString[hti,mod];
    gf ← Gf.Frame[mod ! Lookup.Fail => CONTINUE];
    IF (syms ← FindMod[hti]) = NIL THEN
      BEGIN
      IF gf = NIL THEN {AttachSyms[gf,mod]; syms ← FindMod[hti]}
      ELSE syms ← AddItem[hti,gf];
      END;
    SetSegment[syms,fgt];
    WITH syms SELECT FROM
      mod => IF mdi = LOOPHOLE[0] THEN ERROR ZeroMdi ELSE RETURN[mdi];
      ENDCASE => ERROR SymbolTable.Missing[NIL];
    END;

  SetUp: PROC [gf: GFHandle, fgt: BOOLEAN ← FALSE] RETURNS [syms: Item] =
    BEGIN
    Gf.Check[gf];
    IF (syms ← FindFrame[gf]) = NIL THEN syms ← AddItem[Symbols.HTNull,gf];
    SetSegment[syms,fgt];
    END;

  GFrameMdi: PUBLIC PROC [gf: GFHandle, fgt: BOOLEAN ← FALSE] RETURNS [MDIndex] =
    BEGIN
    syms: Item = SetUp[gf,fgt];
    WITH syms SELECT FROM
      mod => IF mdi = LOOPHOLE[0] THEN ERROR ZeroMdi ELSE RETURN[mdi];
      ENDCASE => ERROR SymbolTable.Missing[NIL];
    END;

  Stopping: PUBLIC PROC [gf: GFHandle, fgt: BOOLEAN ← FALSE] RETURNS [BOOLEAN] =
    BEGIN
    syms: Item = SetUp[gf,fgt];
    RETURN[syms.stopping];
    END;

  CrossJumped: PUBLIC PROC [gf: GFHandle, fgt: BOOLEAN ← FALSE] RETURNS [BOOLEAN] =
    BEGIN
    syms: Item = SetUp[gf,fgt];
    RETURN[syms.crossJumped];
    END;

  GFrameHti: PUBLIC PROC [gf: GFHandle, fgt: BOOLEAN ← FALSE]
    RETURNS [HTIndex] =
    BEGIN
    mdi: MDIndex ← Symbols.MDNull;
    i: Item;
    mdi ← GFrameMdi[gf,fgt !SymbolTable.Missing => CONTINUE];
    IF mdi # Symbols.MDNull THEN
      RETURN[Table.Bounds[Symbols.mdType].base[mdi].moduleId];
    i ← FindFrame[gf];
    WITH i SELECT FROM
      hash => RETURN[hti];
      ENDCASE => ERROR SymbolTableProblem;
    END;

  SetSegment: PUBLIC PROC [syms: Item, fgt: BOOLEAN] =
    BEGIN
    IF ~fgt OR syms.fgtAvailable THEN RETURN;
    WITH syms SELECT FROM
      hash => ERROR SymbolTable.Missing[NIL];
      mod => ERROR NoFGT;
      ENDCASE;
    END;

  END.