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; |