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.