Processor-dependent iostat and iomsg values for file-open failures
0 reputation · 27 Jun 2021, 17:02 UTC
0 reputation · 27 Jun 2021, 17:02 UTC
Portable Fortran code that handles file-open failures faces an unresolved portability problem when using the iostat= and iomsg= specifiers. The standard guarantees only that iostat is zero on success, negative for end-of-file or end-of-record, and positive for other errors. The exact positive integer and the explanatory text assigned to iomsg are processor-dependent.
Because GNU Fortran, Intel Fortran, and NVIDIA Fortran assign distinct positive integers to the same logical condition—such as opening a nonexistent file—source code that branches on a specific numeric code or parses the message string may misclassify the failure on another toolchain. The iomsg= specifier was introduced in Fortran 2003 to supply human-readable diagnostics, but its content remains compiler-specific and can change across compiler versions.
What standard-conforming techniques can classify I/O errors portably without relying on implementation-defined iostat values or iomsg text? Is there a documented way to map processor-dependent codes to logical error categories within the language standard? How should portable applications structure error branches when the same missing-file condition produces different diagnostics across compilers?
35275 reputation · 27 Jun 2021, 21:29 UTC
Portable Fortran programs can only rely on the sign of the iostat variable and the two named constants IOSTAT_END and IOSTAT_EOR from the intrinsic module ISO_FORTRAN_ENV. A successful open yields iostat == 0. An end‑of‑file or end‑of‑record condition yields a negative value that matches one of those constants. Any other error (including a missing file) yields a positive value that is processor‑dependent and has no standard name.
IOSTAT_END and IOSTAT_EOR as the negative iostat values for end‑of‑file and end‑of‑record.iostat constants are defined in the standard; all positive values are implementation‑defined.iomsg= specifier returns a processor‑dependent explanatory string whose content and format are not standardized.OPEN (or any I/O) statement that includes IOSTAT=ios and optionally IOMSG=msg, test ios.ios == 0 treat the operation as successful.ios < 0, compare against the constants from ISO_FORTRAN_ENV:
if (ios == IOSTAT_END) … for end‑of‑file.if (ios == IOSTAT_EOR) … for end‑of‑record.ios > 0 treat the outcome as a generic error; do not attempt to interpret the numeric value or parse msg for portability.If the application must differentiate, for example, “file not found” from “permission denied”, the standard provides no portable mechanism. One must resort to compiler‑specific extensions (e.g., checking against known values from GFORTRAN_IOSTAT or IFORT_IOSTAT modules) or to external error handling such as examining the system errno after the call. Such approaches are non‑portable and should be isolated in implementation‑specific modules.
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 27 Jun 2021, 22:41 UTC
Fortran guarantees only the sign of the iostat value: zero on success, negative for end‑of‑file/record, and positive for any I/O error. The exact positive value and the iomsg text are implementation‑defined, so branching on a specific numeric code or parsing the message string is non‑portable.
The err=<label> specifier is available on all I/O statements (OPEN, READ, WRITE, etc.) and causes control to jump to the specified label whenever the statement fails, regardless of the compiler. This gives a single entry point for error handling that does not depend on iostat or iomsg.
A lightweight, fully portable pattern is therefore:
open(unit=10, file='data.txt', iostat=ios, iomsg=msg, err=io_err)
...
io_err:
write(*,*) 'I/O error: ', trim(msg)
stop 1
When you need a generic test without the err= label, simply check ios>0:
open(unit=10, file='data.txt', iostat=ios, iomsg=msg)
if (ios > 0) then
write(*,*) 'I/O error: ', trim(msg)
stop 1
end if
Both approaches avoid any reliance on processor‑specific codes or message text. If finer distinctions (e.g., “file not found” vs. “permission denied”) are required, you must maintain a compiler‑specific lookup table or use a third‑party normalising library.