Turbo Pascal constants can be of two types: ordinary constants which are only stored to the symbol table and typed constants which are also embedded into the program.
Therefore typed constant values are stored into separate symbol table.
Procedure ProcessConstantDeclarations;
Var TypePtr: PTypeDefinition;
Variable: PVariableIdentifierData;
Constant: PConstantIdentifierData absolute Variable;
ConstantIdentifier: PIdentifier;
Expression: TExpression;
DataPtr, AddData: Pointer;
Size: Word;
UnitTypeOffsets: TUnitOffsets;
Procedure GetTypedConstantInitialValue;
Var VarData: Pointer;
Size: Word;
begin
Size := TypePtr^.Size;
VarData := IncreaseSymbolTable (stTypedConstants, Size);
CurrentTypedConstantValueOffset := Ofs (VarData^);
FillChar (VarData^, Size, 0);
TypedConstantsOffsetBeforeConstantValueProcessing := Ofs (VarData^) + Size;
ProcessTypedConstant (TypePtr);
TypedConstantsOffsetBeforeConstantValueProcessing := LastTypedConstantsSize;
end;
begin
GetNextToken;
Repeat
ConstantIdentifier := ExpectAndStoreIdentifier (0, AddData);
If CheckAndGetNextToken (Token_Colon) then
begin { Typed constant }
Variable := IncreaseSymbolTable (stMain, SizeOf (TVariableIdentifierData));
TokenForEqual := Token_EqualAsSeparator;
TypePtr := GetVariableType;
TokenForEqual := Token_Equal;
If (WordAlignment in ModuleCompilerSwitches) and (TypePtr^.Size <> 1) then WordAlignAddressForTypedConstants;
ForceCreationOfTypedConstantsBlockRecord := True;
VariableData_Flags := TypedConstant;
RecordTypeDefinitionOffset.TypedConstantOffset :=
SymbolTable [stTypedConstants].NextRecordOffset - LastTypedConstantsSize;
RecordTypeDefinitionOffset.TypedConstantsBlockRecordOffset := SymbolTable [stTypedConstantsBlocks].NextRecordOffset;
ExpectTokenAndGetNext (Token_EqualAsSeparator);
GetTypedConstantInitialValue;
ConstantIdentifier^.Token := Token_VariableIdentifier;
With Variable^ do
begin
Flags := VariableData_Flags;
W1.Ofs := RecordTypeDefinitionOffset.TypedConstantOffset;
W1.Seg := RecordTypeDefinitionOffset.TypedConstantsBlockRecordOffset;
W5 := VariableData_NextMemberOffset;
UnitTypeOffsets := CurrentVarUnitTypeOffsets;
end;
end else
begin
ExpectTokenAndGetNext (Token_Equal);
Expression.ExpectConstantExpression;
ConstantIdentifier^.Token := Token_ConstantIdentifier;
DataPtr := @Expression.Value;
TypePtr := Expression.TypeDefPtr;
Size := 4;
If TypePtr^.BaseType < btInteger then
Case TypePtr^.BaseType of
btPointer: Size := 4;
btExtended: Size := 10;
else begin
DataPtr := Ptr (DSeg, Expression.Value.Word);
If TypePtr^.BaseType = btSet then Size := 32
else Size := Byte (DataPtr^) + 1;
end;
end;
GetTypeAndUnitIdentifierOffsets (TypePtr, UnitTypeOffsets);
Constant := IncreaseSymbolTable (stMain, SizeOf (TUnitOffsets) + Size);
Constant^.UnitTypeOffsets := UnitTypeOffsets;
Move (DataPtr^, Constant^.Value, Size);
end;
ExpectTokenAndGetNext (TOKEN_Semicolon);
until Token <> Token_Identifier;
CreateTypedConstantsBlockRecord;
end;
For each Const declaration Turbo Pascal creates a record in symbol table for typed constants (if they are declared). Procedure CreateTypedConstantsBlockRecord;
begin
WordAlignAddressForTypedConstants;
If (SymbolTable [stTypedConstants].UsedSize <> LastTypedConstantsSize) or ForceCreationOfTypedConstantsBlockRecord then
begin
ForceCreationOfTypedConstantsBlockRecord := False;
With PTypedConstantsBlockRecord (IncreaseSymbolTable (stTypedConstantsBlocks, SizeOf (TTypedConstantsBlockRecord)))^ do
begin
Offset := 0;
ConstantsSize := SymbolTable [stTypedConstants].UsedSize - LastTypedConstantsSize;
ReferencesSize := SymbolTable [stTypedConstantsReferences].UsedSize - LastTypedConstantsReferencesSize;
tcrW6 := CurrentRecordOrObjectTypeDefinitionOffset;
end;
LastTypedConstantsSize := SymbolTable [stTypedConstants].UsedSize;
TypedConstantsOffsetBeforeConstantValueProcessing := SymbolTable [stTypedConstants].NextRecordOffset;
LastTypedConstantsReferencesSize := SymbolTable [stTypedConstantsReferences].UsedSize;
end;
end;
|