Dealing With Source Files
For each source file Turbo Pascal keeps a record with essential data like file handle, file name, current line number, current position, conditional compilation If
level, etc.This way it can always reurn to the right position in previous source file (when include files are used). After the source file has changed Turbo Pascal displays compilation progress showing current module name and source line number.
Type PFileStructure = ^TFileStructure;
TFileStructure = Record
CurrentPosition: Word; { 00 }
CurrentLineNumber: Word; { 02 }
FilePosition: Longint; { 04 }
Handle: Word; { 08 }
CurrentLineLength: Word; { 0A }
FileRecordOffset: Word; { 0C }
LineCounter: Word; { 0E }
IF_Level: Word; { 10 }
Name: Str64Rec; { 12 13..XX, Len + NameChars + #0, Len = Length (+ NameChars + #0) }
end;
Procedure OpenSourceFile (UsedFilesRecord: PUsedFilesBlockRecord; FileName: PChar);
Var NewFileStructure: PFileStructure;
NameLength: Byte;
begin
If ProgramBlockCompilation then Error (IncludeFilesAreNotAllowedHere);
NameLength := StrLen (FileName) + 1;
NewFileStructure := Ptr (Seg (CurrentSourceFile^), Ofs (CurrentSourceFile^) - NameLength - 19);
If Ofs (NewFileStructure^) < Ofs (StartOfSourceFileStructures^) then Error (TooManyFiles);
NewFileStructure^.FileRecordOffset := Ofs (UsedFilesRecord^);
NewFileStructure^.Name.Len := NameLength;
StrCopy (@NewFileStructure^.Name.Chr, FileName);
If FileRec (SourceFile).Handle <> 0 then Close (SourceFile);
OpenFile (SourceFile, FileName);
NewFileStructure^.Handle := FileRec (SourceFile).Handle;
NewFileStructure^.CurrentPosition := Ofs (CurrentLine^);
ErrorSourcePosition := CurrentLine;
NewFileStructure^.CurrentLineNumber := 1;
NewFileStructure^.FilePosition := 0;
NewFileStructure^.CurrentLineLength := 0;
NewFileStructure^.IF_Level := 0;
CurrentLine^ := #0;
FileBufferPtr := nil;
FileBufferEnd := nil;
CurrentSourceFile := NewFileStructure;
WriteCompilationProgress (CurrentSourceFile);
end;
Procedure ReturnToPreviousSourceFile;
Var SavedLastLinePosition: Word;
begin
If ProgramBlockCompilation or (CurrentSourceFile = FirstSourceFile) then Error (UnexpectedEndOfFile);
If CurrentSourceFile^.IF_Level <> 0 then Error (ENDIF_directiveMissing);
WritelnModuleNameWithCurrentLineNumber (CurrentSourceFile);
Close (SourceFile);
Inc (PChar (CurrentSourceFile), CurrentSourceFile^.Name.Len + 19);
If CurrentSourceFile <> @EndOfFileStructure then
With CurrentSourceFile^ do
begin
SavedLastLinePosition := CurrentPosition;
CurrentPosition := Ofs (CurrentLine^);
ErrorSourcePosition := CurrentLine;
CurrentLine^ := #0;
FileBufferPtr := nil;
FileBufferEnd := nil;
OpenFile (SourceFile, @Name.Chr);
Handle := FileRec (SourceFile).Handle;
Seek (SourceFile, FilePosition);
If ReadNextLine <> CurrentLineLength then Error (UnexpectedEndOfFile);
CurrentPosition := SavedLastLinePosition;
ErrorSourcePosition := PChar (Ptr (Seg (ErrorSourcePosition^), SavedLastLinePosition));
end;
WriteCompilationProgress (CurrentSourceFile);
end;