[comp.lang.pascal] IO error to StdOut - bug ?

ZCCBJSB%EB0UB011.BITNET@cunyvm.cuny.edu (Josep Sau B.) (05/15/91)

rfh3273@galileo.rtn.ca.boeing.com (Dick Harrigill) writes:

>I've just experienced a strange error with TP6.  I'm using a function
>that I've successfully used for years to check the existance of a file:

> FUNCTION this_file_exists (VAR s:string) : boolean;
> VAR f:file;
> BEGIN
>  {$I-}
>  assign(f,s); reset(f);
>  this_file_exists:=(IOError=0);
>  close(f);
>  {$I+}
> END;

>This week, for the first time, passing a bad file name to this file
>somehow closed standard output when the close(f) statement was run.
>A successive statement such as  writeln('Hi')  yeilds a runtime error
>103 - file not open.   I have gotten around the problem by placing an
>IF test in the function and not doing the close if the file was not
>properly opened.  I am, however, intrigued by this phenomenon.  The
>close(f) function should simply (with $I-) give an IOErorr, not
>screw other things up.   Can anyone give some insight?


Normally, when IO checking is enabled, an IO result generates
an obnoxious run time error and the program dies...

If you disable IO checking with $I- directive, IO errors
are by passed, by...

- Any following IO operation is ignored while IO checking
  remains disabled, but may alter the value stored in InOutRes
  as other errors get by.
- Any following IO operation with IO checking reenabled
  generates again the nasty run time error that should
  have arised before.

This is because the IO error code is stored in System.InOutRes,
and you SHOULD call the standard System.IOResult function
to reset the variable InOutRes, prior to do safely any other
IO operation.

This is NOT a bug.
If you disable the IO checking it is your responsability to get
tracking manually of possible IO errors produced.
If you consider an operation susceptible of producing an
error of this kind you should immediately call IOResult afterwards.
If not to handle it, at least to reset that error flag.

This program shows this behavior:

{$I+}
var f : text;
begin
  {$I-}
  assign(f,'foo');
  {$I-}
  reset(f);
  (* here an IO error 2 will arise *)
  writeln('This line won''t get written');
  close(f)
  {$I+}
  (* here a run time error 103 will halt this clumsy program *)
  writeln('This line won''t get written');
end.

Assuming 'FOO' is a NOT existing file, the RESET
will generate an IO error 2, and this value will get stored
in InOutRes (you can trace this variable in the integrated
environment).
The next writeln will produce no output at all.
The last writeln will produce a fatal IO error 103: file not open,
that is the error generated by the last IO operation with
IO checking disabled, close().
If you remove the close() statement, then the error generated
will be 2:file not found, produced by the reset().

If you insert a call to IOResult just after {$I+} directive,
the InOutRes variable is reset to 0, no errors are generated,
and the last line gets written.
For example:
  IF IOResult = 0 THEN;

All this stuff is explained in the manual under IOResult and
$I directive sections, but I learnt it the hard way two weeks
ago, when I met a simmilar problem.

--Josep Sau