[comp.lang.ada] Exceptions raised by I/O operations

jbg@sei.cmu.edu (John Goodenough) (01/05/89)

Robert Firth said in a recent post:

>>   5.  The error cannot be deferred to the actual use of NAME because
>>   NAME is not defined as being able to raise any exception except
>>   STATUS_ERROR and it may only do that if the file is not open.

>No: the fact that it is required to raise an exception does not imply
>(here or elsewhere) that it is forbidden to raise any otehr exception.

This remark was questioned by Stephe Leake who said:

>  This sounds dangerous to me; I have always assumed that the
>  pre-defined packages behaved _precisely_ as specified in the LRM,
>  _including_ which exceptions may be raised. Thus, if the LRM does not
>  state that a particular routine may raise an exception, it should not
>  do so. This is critical in writting exception handlers; we have to
>  know which exceptions a routine may raise in order to handle them all.

and John Stafford, who asked:

>  I also am not "Ada knowledgeable" enough to know that it is OK for
>  routines which the RM defines as able to raise some exceptions to
>  raise others as well.  I would genuinely appreciate references to why
>  this is OK (at first glance it would seem to me to make an
>  implementation of Ada non-conformant if use of NAME could raise
>  NAME_ERROR).

Robert is literally correct, but his remark is subject to misinterpretation.
14.1(11) says:

	The exceptions that can be raised by a call of an input-output
	subprogram are all defined in the package IO_EXCEPTIONS; the
	situations in which they can be raised are described, either following
	the description of the subprogram (and in section 14.4), or in
	Appendix F in the case of error situations that are
	implementation-dependent. 

This paragraph does not exclude the possibility that other exceptions can be
raised as well, and in fact, this is possible:

	NEW_LINE(-1);

will raise CONSTRAINT_ERROR because the argument does not belong to the formal
parameter's subtype.  NUMERIC_ERROR, TASKING_ERROR, PROGRAM_ERROR, or
STORAGE_ERROR could similarly be raised as a result of evaluating the argument
to an I/O subprogram.  PROGRAM_ERROR and STORAGE_ERROR might be raised by the
body of an I/O subprogram.  (PROGRAM_ERROR could be raised by an attempt to
PUT an uninitialized array variable, for example.)  AI-00279 addresses this
situation by saying:

	After execution of the body of an input-output subprogram has started,
	the only exceptions that can be propagated to the caller are the
	exceptions defined in the package IO_EXCEPTIONS and the exceptions
	PROGRAM_ERROR and STORAGE_ERROR.

This means the evaluation of an argument can raise any exception, but the
subprogram itself is limited in what it can raise.

Although the wording is still not completely precise, it seems clear to me
that the intent is that NAME not raise NAME_ERROR in any case.  If a name
cannot be determined because a parent directory can't be opened, I would say
that USE_ERROR should be raised.

John B. Goodenough					Goodenough@sei.cmu.edu
Software Engineering Institute				412-268-6391

jws@hpcljws.HP.COM (John Stafford) (01/06/89)

The information that is accumulating is all useful, but as usual, it
seems that the more I learn the more questions I have.

John Goodenough indicates that his interpretation is that NAME should
not raise NAME_ERROR and if the name cannot be determined that USE_ERROR
be raised.  I'm sorry that it isn't clear to me whether he means that
the OPEN/CREATE call should raise USE_ERROR if it determines that the
NAME will not be determinable or that NAME should raise USE_ERROR.

If OPEN/CREATE should raise USE_ERROR it seems to unfairly penalize the
user, who may not ever want or need the name, but who can open and use
the file.  If NAME should raise USE_ERROR then I can't find strong
objection to it raising NAME_ERROR either, as STATUS_ERROR is the only
exception that it is specified as being able to raise (granted neither
USE_ERROR nor NAME_ERROR really indicates what is wrong and perhaps
USE_ERROR is a "closer" error than NAME_ERROR and hence is to be
preferred).  In either case, I suspect that Appendix F should indicate
that whatever exception is raised can be due to an inability to
determine the name even though the file may be perfectly accessible to
the user.

Thanks to John Goodenough for pointing out 14.1(11) which actually makes
these waters slightly muddier as well.  One could interpret "the
situations in which they can be raised are described, ..., or in
Appendix F in the case of error situations that are
implementation-dependent" as indicating that any I/O call could raise
any I/O exception in an "implementation dependent error situation".  Is
that a potentially reasonable interpretation?

--
John Stafford -- Hewlett Packard California Language Lab
{allegra,decvax,ihnp4,ucbvax}!hplabs!hpda!jws
{fortune,sun,thirdi,ucbvax}  !hpda  !jws

jbg@sei.cmu.edu (John Goodenough) (01/07/89)

John Stafford writes:

> John Goodenough indicates that his interpretation is that NAME should
> not raise NAME_ERROR and if the name cannot be determined that USE_ERROR
> be raised.  I'm sorry that it isn't clear to me whether he means that
> the OPEN/CREATE call should raise USE_ERROR if it determines that the
> NAME will not be determinable or that NAME should raise USE_ERROR.
> If OPEN/CREATE should raise USE_ERROR it seems to unfairly penalize the
> user, who may not ever want or need the name, but who can open and use
> the file.  

My intention was that NAME should raise USE_ERROR if it can't return a result.
I don't see any justification for OPEN/CREATE to raise any exception based on
whether NAME can return a result, and in fact, AI-00046 notes that CREATE for
a temporary file is expected to succeed even when NAME cannot return any
result because the file has no usable name.

> If NAME should raise USE_ERROR then I can't find strong
> objection to it raising NAME_ERROR either, ...

The reason NAME can't raise NAME_ERROR is that 14.4(4) indicates that the only
operations allowed to raise NAME_ERROR are OPEN and CREATE.  14.4(5) says
USE_ERROR can be raised by any operation, so it can be raised by NAME.  Moreover,
AI-00046 points out that "the NAME function is allowed to raise USE_ERROR if
its argument is associated with an external file that has no name, in
particular, a temporary file" might have no name in some operating systems.


> ... 14.1(11) ... actually makes
> these waters slightly muddier as well.  One could interpret "the
> situations in which they can be raised are described, ..., or in
> Appendix F in the case of error situations that are
> implementation-dependent" as indicating that any I/O call could raise
> any I/O exception in an "implementation dependent error situation".  Is
> that a potentially reasonable interpretation?

No.  The implementation-dependent situations referred to in 14.1(11) are those
that complete the definitions given in 14.4, e.g., the situtations under which
NAME_ERROR will be raised by CREATE or OPEN, the situations when USE_ERROR is
raised by any operation, etc.  "Implementation-dependent" should not be read
as saying any exception can be raised by any operation -- 14.4 says what
exceptions can be raised by the operations, but is necessarily non-specific
about all the implementation-dependent situations that satisfy the conditions
described there.  14.1(11) means Appendix F should give the additional details.

John B. Goodenough					Goodenough@sei.cmu.edu
Software Engineering Institute				412-268-6391