Press enter to see results or esc to cancel.

Symbol Table Management

Each identifier symbol table must be created before it can be used. Turbo Pascal uses diferent parameters (number of linked lists) for different identifier symbol tables.

Procedure CreateSymbolTable (Size: Word);
Var List: PIdentifierList;
  List := IncreaseSymbolTable (stMain, 2 * Size + 2);
  List^.Mask := (Size - 1) * 2;
  FillChar (List^.Offset, 2 * Size, 0);

During compilation process data is stored into symbol tables and they need to be increased. Turbo Pascal maintains for each symbol table a simple data structure which contains address of the symbol table (defined by Segment), data table Size, actual UsedSize and default compiler error is the size of data table exceeds 64 KB (size of one segment in x86). UsedSize is also offset to the next free location in the data table.

    TSymbolTableData = Record
                         Case Byte of
                           0: (UsedSize: Word; Segment: Word; Size: Word; Error: TCompilerError);
                           1: (NextRecordOffset, Seg: Word; BSize: Word; Err: TCompilerError);
                           2: (Ptr: Pointer; BlockSize: Word; ErrorWord: Word);

When the compiler needs to insert a symbol into the table it needs to increase its size for the exact amount as the size of the symbol (including associated data). IncreaseSymbolTable take care for this function. Since each increase of the table space needs to move following symbol tables this function tries to minimize such movements. It increases the size of symbol table is blocks according to the table size.

Function IncreaseSymbolTable (SymbolTableIndex: TSymbolTable; AdditionalSize: Word): Pointer;
Var NewUsedSize: Longint;
    NewBlockSize: Longint;
    FreeParagraphs, NewBlockParagraphSize: Word;
    LastSymbolTableIndex: TSymbolTable;
  NewUsedSize := Longint (SymbolTable [SymbolTableIndex].UsedSize) + AdditionalSize;
  If NewUsedSize > $FFFF then Error (SymbolTable [SymbolTableIndex].Error);
  IncreaseSymbolTable := SymbolTable [SymbolTableIndex].Ptr;
  SymbolTable [SymbolTableIndex].UsedSize := NewUsedSize;
  If NewUsedSize > SymbolTable [SymbolTableIndex].Size then
    begin                                                 { Make additional space }
      If NewUsedSize > $FFF0 then Error (SymbolTable [SymbolTableIndex].Error);
      NewUsedSize := (NewUsedSize + $000F) and $FFF0;
      NewBlockSize := NewUsedSize;
      If not CreateExactSymbolTableSize then
          NewBlockSize := $0200;    { 512 }
          While NewBlockSize <= SymbolTable [SymbolTableIndex].UsedSize do
              NewBlockSize := NewBlockSize shl 1;
              If NewBlockSize < $2000 then Continue;
              While NewBlockSize <= SymbolTable [SymbolTableIndex].UsedSize do
                  Inc (NewBlockSize, $2000);
                  If NewBlockSize < $10000 then Continue;
                  NewBlockSize := $FFF0;
      Dec (NewBlockSize, SymbolTable [SymbolTableIndex].Size);
      NewBlockParagraphSize := NewBlockSize shr 4;
      FreeParagraphs := HeapEndRec.Seg - HeapPtrRec.Seg;
      If NewBlockParagraphSize > FreeParagraphs then
          NewBlockSize := FreeParagraphs shl 4 + SymbolTable [SymbolTableIndex].Size;
          If NewBlockSize < SymbolTable [SymbolTableIndex].UsedSize then Error (OutOfMemory);
          NewBlockParagraphSize := FreeParagraphs;
      HeapPtrRec.Seg := HeapPtrRec.Seg + NewBlockParagraphSize;
      Inc (SymbolTable [SymbolTableIndex].Size, NewBlockParagraphSize shl 4);
      LastSymbolTableIndex := High (TSymbolTable);
      While LastSymbolTableIndex <> SymbolTableIndex do
          If SymbolTable [LastSymbolTableIndex].Size <> 0 then
            MoveForward (Ptr (SymbolTable [LastSymbolTableIndex].Segment, 0)^,
                         Ptr (SymbolTable [LastSymbolTableIndex].Segment + NewBlockParagraphSize, 0)^,
                         SymbolTable [LastSymbolTableIndex].UsedSize);
          Inc (SymbolTable [LastSymbolTableIndex].Segment, NewBlockParagraphSize);
          Dec (LastSymbolTableIndex);