Processing Variable Declarations
This procedure expects a list of identifiers followed by a colon and variable type and processes declaration of variables: global, local and absolute.
Procedure ProcessVariableDeclarations;
begin
GetNextToken;
Repeat
StoreCommaSeparatedIdentifiers;
ExpectTokenAndGetNext (Token_Colon);
GetVariableType;
If CheckAndGetNextToken (Token_ABSOLUTE) then
begin
CheckForDeclaredIdentifier;
If CheckAndGetNextToken (Token_VariableIdentifier) then
begin
GetTypeAndUnitIdentifierOffsets (CurrentIdentifierDataPtr, RecordTypeDefinitionOffset);
VariableData_Flags := [vfAbsoluteVar];
end else begin
RecordTypeDefinitionOffset.Segment := ExpectIntegerConstant;
ExpectTokenAndGetNext (Token_Colon);
RecordTypeDefinitionOffset.Offset := ExpectIntegerConstant;
VariableData_Flags := VariableAbsoluteAddress;
end;
end else begin
If CurrentProcedureIdentifier <> 0 then
begin
RecordTypeDefinitionOffset.UnitIdentifierData := CurrentProcedureIdentifier;
VariableData_Flags := [vf1];
end else begin
ForceCreationOfVariablesBlockRecord := True;
RecordTypeDefinitionOffset.UnitIdentifierData := SymbolTable [stVariablesBlocks].UsedSize;
VariableData_Flags := [];
end;
end;
CalculateVariableOffsets;
ExpectTokenAndGetNext (TOKEN_Semicolon);
until Token <> Token_Identifier;
CreateVariablesBlockRecord;
end;
Here are offsets of variables calculated. Their addresses will be determined later when the program will be linked.
Procedure CalculateVariableOffsets;
Var VarIdentifier: PIdentifier;
VariableIdentifierData: PVariableIdentifierData;
TempPtr: Pointer;
begin
VarIdentifier := Ptr (SymbolTable [stMain].Segment, FirstDeclaredVariableIdentifierOffset);
Repeat
VarIdentifier^.Token := TToken (PrivateFlagMask or Byte (Token_VariableIdentifier));
VariableIdentifierData := Ptr (Seg (VarIdentifier^), Ofs (VarIdentifier^) + VarIdentifier^.Name.Len + 4);
If VariableData_Flags = [] then
begin
If WordAlignment in ModuleCompilerSwitches then
If VariableDataSize <> 1 then
begin
If SizeOfVariablesInDataSegment = $FFFF then Error (TooManyVariables);
SizeOfVariablesInDataSegment := (SizeOfVariablesInDataSegment + 1) and $FFFE;
end;
If LongInt (SizeOfVariablesInDataSegment) + VariableDataSize > $FFFF then Error (TooManyVariables);
RecordTypeDefinitionOffset.Offset := SizeOfVariablesInDataSegment - LastSizeOfVariablesInDataSegment;
Inc (SizeOfVariablesInDataSegment, VariableDataSize);
end else
If VariableData_Flags = [vf1] then
begin
If LongInt (Integer (ProgramBlockMaxStackFrameOffset - 1)) - VariableDataSize < - LongInt ($FFFF)
then Error (TooManyVariables);
ProgramBlockMaxStackFrameOffset := ProgramBlockMaxStackFrameOffset - VariableDataSize;
If WordAlignment in ModuleCompilerSwitches then
If VariableDataSize <> 1 then ProgramBlockMaxStackFrameOffset := ProgramBlockMaxStackFrameOffset and $FFFE;
RecordTypeDefinitionOffset.Offset := ProgramBlockMaxStackFrameOffset;
end else
If Field in VariableData_Flags then
begin
TempPtr := Ptr (SymbolTable [stMain].Segment, OffsetToNextMemberOffset);
Word (TempPtr^) := Ofs (VarIdentifier^);
OffsetToNextMemberOffset := Ofs (VariableIdentifierData^.W5);
TempPtr := Ptr (SymbolTable [stMain].Segment, CurrentRecordOrObjectTypeDefinitionOffset + 2);
RecordTypeDefinitionOffset.Offset := Word (TempPtr^);
If LongInt (Word (TempPtr^)) + VariableDataSize > $FFFF then Error (StructureTooLarge);
Inc (Word (TempPtr^), VariableDataSize);
end;
With VariableIdentifierData^ do
begin
Flags := VariableData_Flags;
W1.Ofs := RecordTypeDefinitionOffset.TypeOffset;
W1.Seg := RecordTypeDefinitionOffset.UnitIdentifierData;
W5 := VariableData_NextMemberOffset;
UnitTypeOffsets := CurrentVarUnitTypeOffsets;
end;
VarIdentifier := Ptr (Seg (VariableIdentifierData^), Ofs (VariableIdentifierData^) + SizeOf (TVariableIdentifierData));
Dec (NumberOfDeclaredVariableIdentifiers);
until NumberOfDeclaredVariableIdentifiers = 0;
end;
For each Var
declaration Turbo Pascal creates a record in symbol table for variables.
Procedure CreateVariablesBlockRecord;
begin
If SizeOfVariablesInDataSegment = $FFFF then Error (TooManyVariables);
SizeOfVariablesInDataSegment := (SizeOfVariablesInDataSegment + 1) and $FFFE;
If (SizeOfVariablesInDataSegment <> LastSizeOfVariablesInDataSegment) or ForceCreationOfVariablesBlockRecord then
begin
ForceCreationOfVariablesBlockRecord := False;
With PVariablesBlockRecord (IncreaseSymbolTable (stVariablesBlocks, SizeOf (TVariablesBlockRecord)))^ do
begin
Offset := 0;
VariablesSize := SizeOfVariablesInDataSegment - LastSizeOfVariablesInDataSegment;
ReferencesSize := 0;
vrW6 := 0;
end;
LastSizeOfVariablesInDataSegment := SizeOfVariablesInDataSegment;
end;
end;
Var
declarations are using processing of non-object types.
Function GetVariableType: PTypeDefinition;
Var UnitTypeOffsets: PTypeDefinition;
begin
UnitTypeOffsets := ProcessVariableTypeDeclaration;
VariableDataSize := UnitTypeOffsets^.Size;
VariableData_NextMemberOffset := 0;
GetVariableType := UnitTypeOffsets;
GetTypeAndUnitIdentifierOffsets (UnitTypeOffsets, CurrentVarUnitTypeOffsets);
end;
Function ProcessVariableTypeDeclaration: PTypeDefinition;
begin
LastPointerToTypeDefinitionOffset := 0;
ProcessVariableTypeDeclaration := ProcessNonObjectTypeDeclaration;
CheckIfDirecive (_ABSOLUTE, Token_ABSOLUTE);
ResolvePointerToTypeDefinitions;
end;