-- IncludesSymTablesImpl.Mesa
-- Last modified by Sandman on July 8, 1980  9:16 AM
-- Last modified by Lewis on 10-Apr-81 12:22:117
-- Last modified by Paul Rovner on June 16, 1982 3:21 pm

DIRECTORY
  Environment USING [PageCount, PageNumber],
  IncludesSymTables USING [],
  Segments USING [
    DeleteSegment, FHandle, NewSegment, Read, SegmentAddress, 
    SHandle, SwapIn, Unlock],
  SymbolSegment USING [BlockDescriptor, STHeader, VersionID],
  Symbols USING [HTIndex, HTRecord, MDIndex],
  IncludeCheckerTable USING [Base];

IncludesSymTablesImpl: PROGRAM
    IMPORTS Segments
    EXPORTS IncludesSymTables =
  BEGIN
  
  ObsoleteSymbolTable: PUBLIC ERROR = CODE;
  
  mdb: PUBLIC IncludeCheckerTable.Base;
  mdLimit: PUBLIC Symbols.MDIndex;
  ssb: PUBLIC LONG STRING; 
  ht: PUBLIC LONG DESCRIPTOR FOR ARRAY Symbols.HTIndex OF Symbols.HTRecord;
  
  
  symFileSeg: Segments.SHandle ← NIL;
  
  moduleTableDesc: SymbolSegment.BlockDescriptor;
  stringDesc:      SymbolSegment.BlockDescriptor;
  hashTableDesc:   SymbolSegment.BlockDescriptor;

  
  LoadSymTables: PUBLIC PROC [
      symFile: Segments.FHandle,
      symSegBase, symSegSize: Environment.PageNumber] =
    BEGIN
    header: LONG POINTER TO SymbolSegment.STHeader;
    IF symFileSeg # NIL THEN ReleaseSymTables[];
    symFileSeg ← Segments.NewSegment[
      file: symFile, base: symSegBase, pages: symSegSize, access: Segments.Read];
    Segments.SwapIn[symFileSeg];
    header ← Segments.SegmentAddress[symFileSeg];
    IF header.versionIdent # SymbolSegment.VersionID THEN
      ERROR ObsoleteSymbolTable[ ! UNWIND => ReleaseSymTables[]];
    moduleTableDesc ← header.mdBlock;
    stringDesc      ← header.ssBlock;
    hashTableDesc   ← header.htBlock;
    ht ← DESCRIPTOR[
      (Segments.SegmentAddress[symFileSeg] + hashTableDesc.offset),
      hashTableDesc.size/SIZE[Symbols.HTRecord]];
    ssb ← Segments.SegmentAddress[symFileSeg] + stringDesc.offset;
    mdb ← LOOPHOLE[Segments.SegmentAddress[symFileSeg], IncludeCheckerTable.Base] + moduleTableDesc.offset;
    mdLimit ← LOOPHOLE[moduleTableDesc.size];
    END;
    
  ReleaseSymTables: PUBLIC PROC = {
    IF symFileSeg # NIL THEN {
      Segments.Unlock[symFileSeg]; Segments.DeleteSegment[symFileSeg]; symFileSeg ← NIL}};
    
  END.