[comp.lang.fortran] Backspacing across an EOF

jerry@violet.berkeley.edu ( Jerry Berkman ) (12/21/88)

How many records should be in the file created by:

      do 10 i=1,10
         write(12,8010) i
8010     format(' record ',i5, '.' )
10    continue
      rewind 12
      call skptoend( 12 )
      write(12,8000)
8000  format(' new record at end')
      end

      subroutine skptoend( lunit )
100   continue
      read ( lunit, '()', end=200 )
      go to 100

200   backspace lunit
      end

On our VAX UNIX, Sun UNIX, and IBM CMS systems, the file looks like:

 record     1.
 record     2.
 record     3.
 record     4.
 record     5.
 record     6.
 record     7.
 record     8.
 record     9.
 record    10.
 new record at end

However, on our Cray UNICOS system and a VMS system I tested,
the record "record    10." is missing from the final output.

As I read the standard, section 12.10.4.1 (Backspace):
	"... if the preceding record is an endfile record, the file
	 becomes positioned before the endfile record"
and section 12.6:
	"[if] An endfile record is encountered during [reading]
	the file is positioned after the endfile record."

Does anyone know DEC's or Cray's position on this?
	- Jerry Berkman, U.C. Berkeley
	  jerry@violet.berkeley.edu, (415)642-4804

hirchert@uxe.cso.uiuc.edu (12/28/88)

Jerry Berkman (jerry@violet.berkeley.edu) asks
>How many records should be in the file created by:
>
>      do 10 i=1,10
>         write(12,8010) i
>8010     format(' record ',i5, '.' )
>10    continue
>      rewind 12
>      call skptoend( 12 )
>      write(12,8000)
>8000  format(' new record at end')
>      end
>
>      subroutine skptoend( lunit )
>100   continue
>      read ( lunit, '()', end=200 )
>      go to 100
>
>200   backspace lunit
>      end

Alas, this program is not standard conforming (in FORTRAN 77), so the answer
is processor dependent.  In FORTRAN 77, the END= clause is guaranteed to work
only if the file contains an endfile record, and the file is guaranteed to
contain an endfile record only if you execute an ENDFILE statement.  Since
you are trying to read past the last record you wrote (which is _not_ an
endfile record), you are violating the rules in the standard and the results
are processor dependent.  In fact, every vendor I know of has extended their
FORTRAN processor to support this case, but you get different results depending
on how they did it:

On most processors, there is no physical representation of the endfile record
(it is simply the end of the file), and a flag in the library is used to keep
track of whether the file is positioned before or after that endfile record.
In effect, on such processors all files have endfile records.  Thus in your
example, the BACKSPACE command backspaces over the endfile record and you
are positioned to add an 11th formatted record.

On a few processors (and I believe Cray's is one of them), there is a physical
end of file character that is the endfile record and END= is triggered by
either an endfile record or by reaching the end of the file.  On such 
processors, positioning with respect to the endfile record is handled exactly
like the positioning for all other records.  Thus in your example, the END=
branch leaves you positioned at the end of file (immediately after the 10th
record, since no endfile record was written), the BACKSPACE command backspaces
over the 10th record, and you are positioned to replace the 10th formatted
record.

By the way, it might be interesting to rerun your example using unformatted
I/O, as some processors that have no physical endfile record for formatted I/O
do have a physical endfile record for unformatted I/O.  Thus, you may see
different results between formatted and unformatted I/O on the same processor.

Since this behaviour is typically a function of the run-time library, not the
hardware or compiler, you should be careful about reporting this.  For example,
were your "Cray" results on COS, CTSS using fortlib, CTSS using cftlib,
UNICOS for a Cray 2, or UNICOS for a Cray 1, X-MP, or Y-MP.  Each of these
libraries is separately maintained and may produce different results.  (Some
of them aren't even maintained by Cray!)

For what its worth, the Fortran 8x draft, in effect, requires all sequential
files written by a Fortran program to end with an endfile record.  (They
are to be produced autotmatically in cases where the user does not execute
ENDFILE explicitly.)  Thus, your example program would be standard conforming
on a Fortran 8x processor and would always produce 11 formatted records
followed by an endfile record.

Kurt W. Hirchert     hirchert@ncsa.uiuc.edu
National Center for Supercomputing Applications