Press enter to see results or esc to cancel.

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;