Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29253 Discussions

I/O statements and implied go to branching

WSinc
New Contributor I
1,042 Views
As you know, whenwe invoke an I/O statement, we can have an ERR= or END= branch.

That has the same effect as putting GO TO statements in the code.

Bearing in mind that the new standards are trying to do away with those, is there a way around this?

Here is a short example:

Read(2,Err=20,End=30)list
! here if normal
! do stuff with I/O items
etc etc etc
go to 40
20 print *,"error"
go to 40
30 print *,"EOF"
40 etc. etc. etc.

It can get pretty messy.
0 Kudos
8 Replies
Steven_L_Intel1
Employee
1,042 Views
IOSTAT is the suggested method of detecting errors and end-of-file. But there's nothing wrong with END= and ERR= if used in a reasonable fashion. I tend to prefer using IOSTAT and then EXIT a loop if an EOF condition is reached.
0 Kudos
Arjen_Markus
Honored Contributor II
1,042 Views
When you have a number of read statements, then checking the status may become as messy as
using ERR= and END= in an undisciplined fashion.

read( 10, *, iostat = ierr) a
if ( ierr /= 0 ) then
write(*,*) 'Problem reading a'
stop
endif

read( 10, *, iostat = ierr ) b
if ( ierr /= 0 ) then
write(*,*) 'Problem reading b'
stop
endif
...

for instance.

read( 10, *, iostat = ierr, err = 100 ) a
read( 10, *, iostat = ierr, err = 100 ) b
...

... ordinary handling
return

! Error handling
100 continue
write(*,*) 'Oops, something went wrong'
stop

may be more concise and still fairly disciplined. It simply combines both methods.

(But in most cases, I prefer to keep the error handling close to theread statement)

Regards,

Arjen

0 Kudos
WSinc
New Contributor I
1,042 Views
Do you think that a CASE construct with IOSTAT would be
a clean way of doing this?

I guess it depends upon the CASE substructures being mutually exclusive,
which I believe they are for I/O statements.

Or maybe IF-THEN- ELSE would work just as well (?)

I was also thinking about something like:

read(2,IOSTAT=ios)list
If (IOS.ne.0)call errprint(ios)


Where errprint would just print out error messages for unexexpected
conditions, and that little routine would be used everywhere in the code.

IOS has a special value for EOF conditions I believe.
0 Kudos
Steven_L_Intel1
Employee
1,042 Views
The special value is defined by the constant IOSTAT_END in intrinsic module ISO_FORTRAN_ENV.
0 Kudos
mecej4
Honored Contributor III
1,042 Views
I think that you are making too much of a legacy feature. As Dr. Fortran has noted, the IOSTAT= argument can be used instead of the older ERR= and END= features. It is really up to you to select a set of features of the language that you are comfortable with.

Even in code that contain ERR=, note that you are not required to use any GOTO statements.

There are a few situations where using a sparingly few GOTO statements may be the best solution, and resorting to contortions in order to avoid them results in code whose awkwardness is painfully obvious.

In other words, make up your own style of programming, but don't let your self-imposed rules suffocate you.
0 Kudos
WSinc
New Contributor I
1,042 Views
The issue I mostly consider is:
How easy is it to DEBUG?

Something with lots of GO TO branching is much
harder to mange, so I like the IOSTAT approach.
But I realize there are situations where a GOTO
has to be used.

I just ordered several books about this, so
it'll be interesting to see what they have to say.
0 Kudos
mecej4
Honored Contributor III
1,042 Views
Code with lots of branching, whether controlled by GOTOs and statement labels, or by IF...THEN...ELSE...ENDIF or other branching constructs, is inherently difficult to debug.

Here is an example:

dimension k(5)
...
do i=1,5
if (i .gt. 1 .and. k(i - 1) .lt. 7) then
...
endif
enddo

No GOTO statements or statement labels here. If your compiler is not set to check for out of range subscripts and uninitialized array elements, you may find such a bug difficult to detect.
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,042 Views
Consider:

With FPP

ierrLine = __LINE__
read( 10, *, iostat = ierr, err = 100 ) a
ierrLine = __LINE__
read( 10, *, iostat = ierr, err = 100 ) b

Without FPP

integer, pragma ierr_Read_a = 1
integer, pragma ierr_Read_b = 2

ierrCode = ierr_Read_a
read( 10, *, iostat = ierr, err = 100 ) a
ierrCode = ierr_Read_b
read( 10, *, iostat = ierr, err = 100 ) b

And in both cases remember to place a break point at the err=nnn line(s) or in a generalized error message printout

100 call errMessage(ierrCode)
... corrective measure for error dispatches reaching here

subroutine errMessage(ierrCode)
integer :: ierrCode
write(*,*) ErrorMessage(i) ! break here
end subroutine errMessage

Jim Dempsey
0 Kudos
Reply