-- SymsCold.Mesa  Edited by:
  -- Bruce September 4, 1980  5:43 PM
  -- Sandman July 17, 1980  11:10 AM
  -- Johnsson July 16, 1980  9:26 AM

DIRECTORY
  ComData USING [bodyRoot, definitionsOnly],
  CompilerUtil USING [PassIndex, PrefillSymbols],
  Copier USING [CopierInit, CopierReset, CreateFileTable, EnterFileSegment, FileInit, FileReset, FindExternalCtx, Outer],
  DebugOps USING [StringExpToOctal],
  DI USING [ResetLongs],
  Strings USING [SubString, SubStringDescriptor],
  DSymOps USING [
    AttachSyms, GetRegion, Head, myVersion, SymHandle, SymRec,
    SymbolSegForFrame, SymsHot],
  DSyms USING [Item, ItemObject],
  Frames,
  Gf USING [Check, Shared],
  LiteralOps USING [Initialize],
  MachineDefs USING [FSHandle, GFHandle, PageSize],
  Segments USING [AddModifyProc, FHandle],
  Storage USING [Free, Node],
  String USING [AppendString],
  SymbolOps USING [EnterString, Initialize, Reset],
  SymbolPack,
  Symbols USING [BTIndex, HTIndex, IncludedCTXNull, MDIndex, mdType, RootBti],
  SymbolSegment USING [Tables],
  SymbolTable USING [Base, Missing],
  Table USING [Base, Bounds, Create, Selector, Trim],
  TreeOps USING [Initialize];

SymsCold: MONITOR LOCKS SymbolLock
  IMPORTS data: ComData, CompilerUtil, Copier,
    DSymOps, DebugOps, DI, Frames, Gf, LiteralOps,
    Segments, Storage, String, SymbolOps, SymbolPack, SymbolTable, Table, TreeOps
  EXPORTS CompilerUtil, Copier, DSyms, DSymOps =
  BEGIN OPEN DSymOps, DSyms, MachineDefs;

  SymbolLock: PUBLIC MONITORLOCK;
  NoFGT: PUBLIC ERROR = CODE;
  CantAttach: ERROR = CODE;
  SymbolTableProblem: ERROR = CODE;

  AddItem: PUBLIC PROC [hti: Symbols.HTIndex, gf: GFHandle]
      RETURNS [syms: Item] = 
    BEGIN
    rec: SymRec ← [hti: hti, gf: gf];
    DSymOps.SymbolSegForFrame[@rec];
    syms ← CacheItem[@rec];
    END;

  CacheItem: PUBLIC ENTRY PROC [h: SymHandle] RETURNS [syms: Item] = 
    BEGIN ENABLE UNWIND => NULL;
    mdi: Symbols.MDIndex;
    syms ← Storage.Node[SIZE[ItemObject]];
    IF h.seg = NIL THEN
      BEGIN
      syms↑ ← [link: Head, gf: h.gf, fgtAvailable: h.fgt,
      symbol: hash[h.hti], outerCtx: Symbols.IncludedCTXNull,
      directoryCtx: Symbols.IncludedCTXNull, sourceOk: FALSE,
      shared: IF h.gf = NIL THEN FALSE ELSE Gf.Shared[h.gf],
      importCtx: Symbols.IncludedCTXNull, crossJumped: h.jumped, stopping:];
      Head ← syms;
      ERROR SymbolTable.Missing[NIL];
      END
    ELSE
      BEGIN
      mdi ← Copier.EnterFileSegment[h.hti,h.version,h.seg];
      syms↑ ← [link: Head, gf: h.gf, fgtAvailable:h.fgt,
      symbol: mod[mdi], outerCtx: Symbols.IncludedCTXNull,
      directoryCtx: Symbols.IncludedCTXNull, sourceOk: FALSE,
      shared: IF h.gf = NIL THEN FALSE ELSE Gf.Shared[h.gf],
      importCtx: Symbols.IncludedCTXNull, crossJumped:h.jumped, stopping:];
      Head ← syms;
      END;
    Copier.Outer[mdi,EnterContexts];
    Table.Bounds[Symbols.mdType].base[mdi].shared ← TRUE;
    syms.outerCtx ← Copier.FindExternalCtx[mdi,syms.outerCtx];
    syms.directoryCtx ← Copier.FindExternalCtx[mdi,syms.directoryCtx];
    syms.importCtx ← Copier.FindExternalCtx[mdi,syms.importCtx];
    RETURN
    END;
  
  EnterContexts: PROC [base: SymbolTable.Base] =
    BEGIN
    Head.outerCtx ← base.mainCtx;
    Head.directoryCtx ← base.stHandle.directoryCtx;
    Head.importCtx ← base.stHandle.importCtx;
    Head.stopping ← base.bb[Symbols.RootBti].stopping;
    END;

  MakeSwappable: PUBLIC PROC[module:PROGRAM, pass:CompilerUtil.PassIndex]={};

  FreeItems: PUBLIC ENTRY PROCEDURE =
    BEGIN ENABLE UNWIND => NULL;
    syms, next: Item;
    FOR syms ← Head, next UNTIL syms = NIL DO
      next ← syms.link;
      Storage.Free[syms];
      ENDLOOP;
    Copier.CopierReset[];
    Copier.FileReset[];
    Copier.FileInit["XDebug"L, myVersion];
    Copier.CopierInit[FALSE];
    Copier.CreateFileTable[16];
    Head ← NIL;
    END;
  
  DeleteItem: PUBLIC PROCEDURE [i: Item] =
    BEGIN
    next, prev: Item;
    prev ← NIL;
    FOR syms: Item ← Head, next UNTIL syms = NIL DO
      next ← syms.link;
      IF syms = i THEN {
	IF prev = NIL THEN Head ← next ELSE prev.link ← next;
	Storage.Free[syms];
	RETURN};
      prev ← syms;
      ENDLOOP;
    END;

  PurgeMdi: PUBLIC PROC [mdi: Symbols.MDIndex] = {
    next, prev: Item;
    prev ← NIL;
    FOR syms: Item ← Head, next UNTIL syms = NIL DO
      next ← syms.link;
      WITH s: syms SELECT FROM
	mod => IF s.mdi = mdi THEN {
	  IF prev = NIL THEN Head ← next ELSE prev.link ← next;
	  Storage.Free[syms];
	  LOOP};
	ENDCASE;
      prev ← syms;
      ENDLOOP};

  FreeHashes: PROC [name: STRING, file: Segments.FHandle] RETURNS [ok: BOOLEAN] = {
    Clean[]; RETURN[TRUE]};

  Clean: PUBLIC PROC = {
    next, prev: Item;
    prev ← NIL;
    FOR syms: Item ← Head, next UNTIL syms = NIL DO
      next ← syms.link;
      WITH syms SELECT FROM
	hash => {
	  IF prev = NIL THEN Head ← next ELSE prev.link ← next;
	  Storage.Free[syms]};
	ENDCASE => prev ← syms;
      ENDLOOP};

  ModuleToHti: PUBLIC PROC [s: STRING] RETURNS [hti: Symbols.HTIndex] =
    BEGIN 
    mod: STRING ← [40];
    desc: Strings.SubStringDescriptor;
    String.AppendString[mod,s]; StripExtension[mod];
    desc ← [base: mod, offset: 0, length: mod.length];
    RETURN[SymbolOps.EnterString[@desc]];
    END;

  StripExtension: PUBLIC PROCEDURE [name: STRING] =
    BEGIN
    i: CARDINAL;
    FOR i DECREASING IN [1..name.length) DO
      IF name[i] = '. THEN {name.length ← i; RETURN};
      ENDLOOP;
    END;
  
  AttachSymbols: PUBLIC PROC [frame, file: STRING] = {
    gf: GFHandle = LOOPHOLE[DebugOps.StringExpToOctal[frame]];
    Gf.Check[gf];
    AttachSyms[gf,file]};
  
  SymbolTablePages: CARDINAL = 20;
  SymbolTableSize: CARDINAL = SymbolTablePages*MachineDefs.PageSize;

  bounds: ARRAY SymbolSegment.Tables OF CARDINAL;

  Initialize: PUBLIC PROCEDURE =
    BEGIN
    i: Table.Selector;
    weights: ARRAY SymbolSegment.Tables OF CARDINAL ← ALL[1];
    Table.Create[DSymOps.GetRegion[], DESCRIPTOR[weights]];
    START SymbolPack;
    START SymsHot;
    data.bodyRoot ← FIRST[Symbols.BTIndex];
    data.definitionsOnly ← FALSE;
    SymbolOps.Initialize[];
    LiteralOps.Initialize[];
    TreeOps.Initialize[];
    CompilerUtil.PrefillSymbols[];
    Copier.FileInit["XDebug"L, myVersion];
    Copier.CopierInit[FALSE];
    Copier.CreateFileTable[16];
    FOR i IN SymbolSegment.Tables DO
      bounds[i] ← Table.Bounds[i].size;
      ENDLOOP;
    END;

  Prune: PUBLIC PROCEDURE =
    BEGIN
    i: Table.Selector;
    DI.ResetLongs[];
    FOR i IN SymbolSegment.Tables DO
      Table.Trim[i, bounds[i]];
      ENDLOOP;
    SymbolOps.Reset[];
    END;
  
  Segments.AddModifyProc[FreeHashes];

  END...