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