{ NOTICE OF COPYRIGHT AND OWNERSHIP OF SOFTWARE:

  Copyright 1980, 1981, 1982 by Oregon Software, Inc.
  All Rights Reserved.

  Whether this program is copied in whole or in part and whether this
  program is copied in original or in modified form, ALL COPIES OF THIS
  PROGRAM MUST DISPLAY THIS NOTICE OF COPYRIGHT AND OWNERSHIP IN FULL.

  Symbol Table Declarations for PB
  Release version: 2.1A  Level: 2  Date: 10-Jul-1983 20:17:48
  Processor: ALL
  System: ALL
}

{ SYMDCL, Symbol Table Manager (declarations section); release 1.5

  The Symbol Table consists of an array, the hash table (HashTable), and
  two files, the node file (NodeFile) and the string file (StringFile).
  Symbols are located using the hash table, which contains pointers into the
  node file (symbols that hash to the same location are chained together).
  A node file entry contains the attributes of a single symbol; string
  attributes are pointers into the string file.

  The node and string files are accessed through buffer caches in order to
  keep access times within tolerable limits.  A least-recently-used
  algorithm is used to choose buffers for reuse, so the last several nodes
  and strings accessed are guaranteed to be valid.

  The type MagicCookie is used as a pointer to a node or string.  It con-
  tains two fields, num and idx.  Once AccessNode has been called, a node
  may be referenced by:
      NodeTable[Cookie.num]^.blk[Cookie.idx]
  A string is referenced in a similar fashion; its length is:
      ord(StringTable[Cookie.num]^.blk[Cookie.idx])
  and the following array elements contain its text.

  The Symbol Table Manager defines:
  
      NodeBlockIndex      type    Index in node block
      StringBlockIndex    type    Index in string block
      MagicCookie         type    Pointer to node or string
      NodeType            type    Symbol Table node; of the form:
				    record
				      lab, next: MagicCookie;
                                      key: KeyType;
				      ...
				    end;
				  where lab is the symbol name string.
      NodeBlock           type    ...
      StringBlock         type    ...
  
      NodeTable           var     Array of pointers to node file buffers
      StringTable         var     Array of pointers to string file buffers
  
      SetNilCookie        proc    Initialize NIL MagicCookie
      IsNilCookie         proc    Check for NIL MagicCookie
      IniSymbol           proc    Initialize Symbol Table
      LocSymbol           proc    Locate/create a Symbol Table entry
      ChkSymbol           proc    Locate a Symbol Table entry
      NewNode             proc    Allocate and initialize a node
      NewString           proc    Allocate and initialize a string
      AccNode             proc    Set up a node up for access
      AccString           proc    Set up a string for access
      WrtString           proc    Write a string
  
  The Symbol Table Manager references the following:
  
      MaxNodeCache        const   Maximum number of node buffers
      MaxStringCache      const   Maximum number of string buffers

      KeyType             type    Node Types; enumerated type, one value
                                  must be `OtherKey'.
  
  Additional fields may be added to Symbol Table nodes by patching this
  module in the place marked by the comment line:
    declare additional NodeType fields
}

const
  DirectAccess = 'symbol.tmp/temp/seek';

  MaxBlockIndex = 255;
  MaxNodeBlockIndex = MaxBlockIndex;
  MaxStringBlockIndex = MaxBlockIndex;
  { note: MaxNodeBlockIndex, MaxStringBlockIndex <= MaxBlockIndex }

  MaxBufferAge = 65535;

  HashSize = 503;

type
  BlockIndex = 0..MaxBlockIndex;
  BlockNumber = 0..255;
  MagicCookie = packed record
    num: BlockNumber;
    idx: BlockIndex
  end;
  NodeType = record
    lab, next: MagicCookie;
    key: KeyType;
       tok: TokenType;          { symbol token type }
       alt: MagicCookie;        { symbol label string (with capitalization) }
  end;

  BufferAge = 0..MaxBufferAge;
  AccessType = (ReadAccess, ReadWriteAccess, WriteAccess);
  { note: the order of AccessType values is significant. }

  NodeBlockIndex = 0..MaxNodeBlockIndex;
  NodeBlock = array[NodeBlockIndex] of NodeType;
  NodeBuffer = record
    age: BufferAge;             { age of last access }
    dirty: boolean;             { must be written before reuse }
    num: BlockNumber;           { block number of contents }
    blk: NodeBlock
  end;
  NodeBufferPointer = ^NodeBuffer;
  NodeCacheIndex = 0..MaxNodeCache;

  StringBlockIndex = 0..MaxStringBlockIndex;
  StringBlock = packed array[StringBlockIndex] of char;
  StringBuffer = record
    age: BufferAge;             { age of last access }
    dirty: boolean;             { must be written before reuse }
    num: BlockNumber;           { block number of contents }
    blk: StringBlock
  end;
  StringBufferPointer = ^StringBuffer;
  StringCacheIndex = 0..MaxStringCache;

  HashIndex = 0..502 { = HashSize - 1 };
  HashTable = array[HashIndex] of MagicCookie;

var
  HashTab: HashTable;

  NodeTable: array[BlockNumber] of NodeBufferPointer;
  NodeCache: array[1..MaxNodeCache] of NodeBufferPointer;
  NodeFile: file of NodeBlock;
  CurNodeBlockIndex: NodeBlockIndex;
  CurNodeBlockNum: BlockNumber;
  CurNodeCacheIndex: NodeCacheIndex;
  CurNodeAge: BufferAge;

  StringTable: array[BlockNumber] of StringBufferPointer;
  StringCache: array[1..MaxStringCache] of StringBufferPointer;
  StringFile: file of StringBlock;
  CurStringBlockIndex: StringBlockIndex;
  CurStringBlockNum: BlockNumber;
  CurStringCacheIndex: StringCacheIndex;
  CurStringAge: BufferAge;

  procedure SetNilCookie(var ptr: MagicCookie);
    external;
  function IsNilCookie(ptr: MagicCookie): boolean;
    external;
  procedure AccNode(ptr: MagicCookie; how: AccessType);
    external;
  procedure AccString(ptr: MagicCookie; how: AccessType);
    external;
  procedure NewNode(var ptr: MagicCookie);
    external;
  procedure NewString(var str: StringBlock; var ptr: MagicCookie);
    external;
  procedure WrtString(var f: text; ptr: MagicCookie);
    external;
  procedure IniSymbol;
    external;
  procedure LocSymbol(var sym: StringBlock; k: KeyType;
                      var ptr: MagicCookie);
    external;
  procedure ChkSymbol(var sym: StringBlock; k: KeyType;
                      var ptr: MagicCookie);
    external;
                                                                                                