Node: File Routines, Next: String Operations, Up: Library Routines

#### File Routines

Extended Pascal treats files quite differently from Borland Pascal. GPC supports both forms, even in mixed ways, and provides many extensions.

@@ A lot missing here

- An example of getting the size of a file (though a `FileSize` function is already built-in).

                function FileSize (FileName : String) : LongInt;
                var
                  f: bindable file [0 .. MaxInt] of Char;
                  b: BindingType;
                begin
                  Unbind (f);
                  b := Binding (f);
                  b.Name := FileName;
                  Bind(f, b);
                  b := Binding(f);
                  SeekRead (f, 0);
                  if Empty (f) then
                    FileSize := 0
                  else
                    FileSize := LastPosition (f) + 1;
                  Unbind(f);
                end;

  Prospero's Extended Pascal has a bug in this case. Replace the MaxInt in the type definition of f by a sufficiently large integer. GNU Pascal works correct in this case.

- GPC implements lazy text file I/O, i.e. does a `Put` as soon as possible and a `Get` as late as possible. This should avoid most of the problems sometimes considered to be the most stupid feature of Pascal. When passing a file buffer as parameter the buffer is validated when the parameter is passed.
- GPC supports direct access files. E.g., declaring a type for a file that contains 100 integers.

                program DirectAccessFileDemo;
                type
                  DFile = file [1 .. 100] of Integer;
                var
                  F: DFile;
                  P, N: 1 .. 100;
                begin
                  Rewrite (F);
                  P := 42;
                  N := 17;
                  SeekWrite (F, P);
                  Write (F, N)
                end.

  The following direct access routines may be applied to a direct access file:

  `SeekRead (F, N); { Open file in inspection mode, seek to record N }`
  `SeekWrite (F, N); { Open file in generation mode, seek to record N }`
  `SeekUpdate (F, N); { Open file in update mode, seek to record N }`
  `Update (F); { Writes F^, position not changed. F^ kept. }`
  `p := Position (F); { Yield the current record number }`
  `p := LastPosition (F); { Yield the last record number in file }`

  If the file is open for inspection or update, `Get` may be applied. If the file is open for generation or update, `Put` may be applied.

- In BP, you can associate file variables with files using the `Assign` procedure which GPC supports.

                program AssignTextDemo;
                var
                  t: Text;
                  Line: String (4096);
                begin
                  Assign (t, 'mytext.txt');
                  Reset (t);
                  while not EOF (t) do
                    begin
                      ReadLn (t, Line);
                      WriteLn (Line)
                    end
                end.

- In Extended Pascal, files are considered entities external to your program. External entities, which don't need to be files, need to be bound to a variable your program. Any variable to which external entities can be bound needs to be declared `bindable`. Extended Pascal has the `Bind` function that binds a variable to an external entity as well as `Unbind` to undo a binding and the function `Binding` to get the current binding of a variable.

  GPC supports these routines when applied to files. The compiler will reject binding of other object types.

  Only the fields `Bound` and `Name` of the predefined record type `BindingType` are required by Extended Pascal. Additionally, GPC implements some extensions. For the full definition of `BindingType`, see BindingType.

  The following is an example of binding:

                program BindingDemo (Input, Output, f);

                var
                  f: bindable Text;
                  b: BindingType;

                procedure BindFile (var f: Text);
                var
                  b: BindingType;
                begin
                  Unbind (f);
                  b := Binding (f);
                  repeat
                    Write ('Enter a file name: ');
                    ReadLn (b.Name);
                    Bind (f, b);
                    b := Binding (f);
                    if not b.Bound then
                      WriteLn ('File not bound -- try again.')
                  until b.Bound
                end;

                begin
                  BindFile (f);
                  { Now the file f is bound to an external file. We can use the
                    implementation defined fields of BindingType to check if the
                    file exists and is readable, writable or executable. }
                  b := Binding (f);
                  Write ('The file ');
                  if b.Existing then
                    WriteLn ('exists.')
                  else
                    WriteLn ('does not exist.');
                  Write ('It is ');
                  if not b.Readable then Write ('not ');
                  Write ('readable, ');
                  if not b.Writable then Write ('not ');
                  Write ('writable and ');
                  if not b.Executable then Write ('not ');
                  WriteLn ('executable.')
                end.

Note that Prospero's Pascal defaults to creating the file if it does not exists! You need to use Prospero's local addition of setting `b.Existing` to `True` to work-around this. GPC does not behave like this.