FORTRAN tty input/output bug

derry.birse@ind.alstom.com derry.birse@ind.alstom.com
Fri Apr 23 09:02:00 GMT 1999


The following bug was discovered when porting a mixture of C and FORTRAN
software from a Solaris 2 system using the Sun Workshop compilers to a Linux box
kited out with egcs 1.0.3 release, and gcc 2.7.2.3.

The problem occurs when utilising the stream mode character writing/reading
intrinsics with a FORTRAN logical unit opened on a TTY device. I have included a
small code sample which demonstrates the problem(s).  This is compiled and run
with the following commands (after puting the FORTRAN code in file fort.f and
the C code in file c.c).

cc -g -c c.c
f77 -g -w -fcase-preserve fort.f
f77 -o test fort.o c.o
./test

Firstly, use of the perror intrinsic after a READ or WRITE to a unit opened on a
TTY device results in an error "Illegal seek", this I did not expect. This is
not the main problem, which is as follows. If the first operation on a unit
opened on a TTY device is a  read operation (either READ or fgetc), any
subsequent stream based write operation fails with a "Bad file descriptor"
error. Conversely if the first operation on the unit is a write operation (WRITE
or fputc), any subsequent stream based read operation fails with a "Bad file
descriptor" error.  Further to this, if you require to use the lower level file
descriptor based functions, read or write, in a C routine called from FORTRAN
and passed the file descriptor (obtained from fnum) you must perform an
appropriate type of i/o on the unit from the FORTRAN i/o routines (READ, WRITE,
fputc or fgetc), and again subsequent use of the opposite type of i/o operation
results in the "Bad file descriptor" error. The following code also demonstrates
this additional phenomenon.


regards

Derry Birse
derry.birse@alstom.ind.com


      INTEGER FD
      CHARACTER*1 C
      CHARACTER*50 ARRAY
      CHARACTER*255 ERROR,NAME,ttynam

      NAME=ttynam(6)
      L=len_trim(NAME)
      OPEN(1,FILE=NAME(1:L),IOSTAT=IERRNO)
      C='*'
      CALL clearerr()
 5    FORMAT(A)
      WRITE(1,5)'Hello'
      CALL perror('WRITE')
      CALL clearerr()
      READ(1,5)ARRAY
      CALL perror('READ')
      CALL clearerr()
      WRITE(1,5)ARRAY
      CALL perror('WRITE')
      CALL clearerr()
      MK = fputc(1,'A')
      CALL perror('fputc')
      CALL flush(1)
      CALL clearerr()
      MK = fgetc(1,C)
      CALL perror('fgetc')
      CALL clearerr()
      MK = fputc(1,C)
      CALL perror('fputc')
      FD=fnum(1)
      CALL clearerr()
      CALL readwrite(FD)
      WRITE(1,*)'The End'
      CALL flush(1)
      CALL exit(0)
      END

The following C code provides the access to the low level read/write functions.

#include <stdio.h>
#include <errno.h>

void clearerr_()
{
  errno=0;
}

void readwrite_(fd)
     long *fd;
{
  int mk;
  char c;
  do {
    mk = read(*fd, &c, 1);
  } while (mk < 0 && errno == EINTR);
  if (mk < 0) {
    fprintf(stderr,"readwrite: terminated with read error %d\n",errno);
    exit(8);
  }
  mk = write(*fd, &c, 1);
  if (mk < 0) {
    fprintf(stderr,"readwrite: terminated with write error %d\n",errno);
    exit(8);
  }

}





More information about the Gcc-bugs mailing list