  { SKELSYMS:  Symbol table handling for skeleton files. }
  { Copyright (C) 1984 by QCAD Systems Inc., All Rights Reserved. }

  {*******************}
  function HASHIT(FSYM: symbol): int;
  begin
    hashit := (128*(ord(fsym[1])+ord(fsym[3])) +
               ord(fsym[2])+ord(fsym[4]))
              mod hashsize;
  end;

  {*****************}
  function FINDSYM(FSYM: symbol): symtabp;
    { Finds a symbol, returning NIL if not there.  Use this for
      variable references, calling error if it returns NIL. }
    var SP: symtabp;
  begin
    findsym := nil;
    sp := symtab[hashit(fsym)];
    while sp <> nil do begin
      with sp^ do begin
        if sym <> fsym then
          sp := next
        else begin
          findsym := sp;
          sp := nil
        end
      end
    end
  end;

  {**********************}
  function MAKESYM(FSYM: symbol;  SYT: symtype;  LEV: int):  symtabp;
    { this returns a symbol entry if there; makes a new one if not.
      Useful for FORTRAN-style variable declaration -- declare name
      on first appearance, whether in a declaration or not. }
    var SP: symtabp;
        HX: int;
  begin
    sp := findsym(fsym);
    if sp = nil then begin
      new(sp);  { need a new one if here }
      with sp^ do begin
        { put at the head of the hash list}
        sym := fsym;
        symt := syt;
        hx := hashit(fsym);
        next := symtab[hx];
        symtab[hx] := sp;
        level := lev;
      end
    end;
    makesym := sp
  end;

  {**********************}
  function FORCESYM(FSYM: symbol;  SYT: symtype;  LEV: int):  symtabp;
    { This forces a new symbol entry.  Use this for declarations
      to cover a previous declaration with the same name. }
    var SP: symtabp;
        HX: int;
  begin
    hx := hashit(fsym);
    new(sp);
    with sp^ do begin
      { put at the head of the hash list. }
      sym := fsym;
      symt := syt;
      next := symtab[hx];
      symtab[hx] := sp;
      level := lev;
    end;
    forcesym := sp;
  end;

  {********************}
  procedure CLEARSYM(CLEVEL: int);
    { Sets the symbol table pointers to remove references to
      everything at level >= CLEVEL, assuming that level numbers
      are monotonic.  Prepares for a RELEASE of memory. }
    var HX: int;
        SP, KEEP: symtabp;
  begin
    { Don't clear the reserved words -- check, just in case }
    if clevel<0 then clevel := 0;
    for hx := 0 to hlimit do begin
      sp := symtab[hx];  keep := nil;
      while sp <> nil do begin
        if sp^.level >= clevel then
          sp := sp^.next
        else begin
          keep := sp;
          sp := nil
        end
      end;
      symtab[hx] := keep
    end
  end;

