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;
begin
List := IncreaseSymbolTable (stMain, 2 * Size + 2);
List^.Mask := (Size - 1) * 2;
FillChar (List^.Offset, 2 * Size, 0);
end;
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.
Type
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);
end;
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;
begin
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
begin
NewBlockSize := $0200; { 512 }
While NewBlockSize <= SymbolTable [SymbolTableIndex].UsedSize do
begin
NewBlockSize := NewBlockSize shl 1;
If NewBlockSize < $2000 then Continue;
While NewBlockSize <= SymbolTable [SymbolTableIndex].UsedSize do
begin
Inc (NewBlockSize, $2000);
If NewBlockSize < $10000 then Continue;
NewBlockSize := $FFF0;
Break;
end;
end;
end;
Dec (NewBlockSize, SymbolTable [SymbolTableIndex].Size);
NewBlockParagraphSize := NewBlockSize shr 4;
FreeParagraphs := HeapEndRec.Seg - HeapPtrRec.Seg;
If NewBlockParagraphSize > FreeParagraphs then
begin
NewBlockSize := FreeParagraphs shl 4 + SymbolTable [SymbolTableIndex].Size;
If NewBlockSize < SymbolTable [SymbolTableIndex].UsedSize then Error (OutOfMemory);
NewBlockParagraphSize := FreeParagraphs;
end;
HeapPtrRec.Seg := HeapPtrRec.Seg + NewBlockParagraphSize;
Inc (SymbolTable [SymbolTableIndex].Size, NewBlockParagraphSize shl 4);
LastSymbolTableIndex := High (TSymbolTable);
While LastSymbolTableIndex <> SymbolTableIndex do
begin
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);
end;
end;
end;