Version 1.1 of ais/ai-00001.txt

Unformatted version of ais/ai-00001.txt version 1.1
Other versions for file ais/ai-00001.txt

!standard A.12.1 (29)          96-07-23 AI95-00001/05
!standard 13.13.01(08)
!standard 13.13.01(09)
!editor Norman Cohen
!class binding interpretation 95-06-25
!status WG9 approved (8-0-0) 97-07-04
!status ARG approved (by letter ballot) 10-0-1 96-06-10
!status work item (letter ballot was 9-1-1) 96-06-05
!status ARG approved (subject to letter ballot) 7-0-3 95-11-01
!status received 95-06-25
!subject Ada.Streams.Stream_IO.Stream can raise Status_Error
!summary 96-04-30
Ada.Streams.Stream_IO.Stream raises Status_Error if its parameter is not an open file. If the file passed to Stream is closed or ceases to exist after the call on Stream and the Root_Stream_Type'Class object designated by the function result is subsequently passed as the first parameter to Ada.Streams.Read or Ada.Streams.Write, execution is erroneous.
!question 95-06-25
If the function Ada.Streams.Stream_IO.Stream is called with a closed file, does the call raise Status_Error?
If the function call does not raise Status_Error, does an attempt to read from or write to the stream pointed to by the resulting access value, before the file is opened, raise Status_Error?
!recommendation 96-04-30
The result of Ada.Streams.Stream_IO.Stream is associated with a specific opening of the file passed as a parameter.
A call on Stream raises Status_Error if its parameter is not an open file.
If the file passed to Stream is closed after the call on Stream and the Root_Stream_Type'Class object designated by the function result is subsequently passed as the first parameter to Ada.Streams.Read or Ada.Streams.Write, execution is erroneous, even if the file was opened again after it was closed. (Such calls on Read or Write may arise indirectly from calls on the subprograms denoted by the stream-oriented attributes.) Similarly, if the file passed to Stream ceases to exist after the call on Stream (e.g., upon exit from the scope in which the File_Type object was declared) and the object designated by the function result is subsequently passed to Read or Write, execution is erroneous.
It follows from A.12.2(5) that the same rules apply to Ada.Text_IO.Text_Streams.Stream. It follows from A.12.3(5) that the same rules apply to Ada.Wide_Text_IO.Text_Streams.Stream .
!wording 95-06-25
!discussion 96-07-23
Open, Create, and Is_Open are the only subprograms in predefined program units that can be invoked with a closed file without raising Status_Error.
The rules stipulating when use of the result of Stream is erroneous are analogous to the rules in A.10.3(22) and A.10.3(23) for the result of the Current_Input, Current_Output, and Current_Error functions. These rules make it possible to represent a File_Type value or a file stream-value as a pointer, with a null pointer corresponding to a closed file. (By a file-stream value, we mean a value belonging to some descendant of Root_Stream_Type and representing a stream associated with a file.)
The risk of erroneous execution can be minimized by using the Stream function only as an actual parameter to Ada.Streams.Read, Ada.Streams.Write, or a stream-oriented attribute.
An alternative approach would be to allow the result of Stream to correspond to a closed file, but to raise Status_Error upon an attempt to use a file-stream value associated with a closed or no longer existent file. Then a file-stream value would have to reflect the fact that its corresponding internal file had been closed or had ceased to exist. This would rule out an implementation in which closing a file simply sets a File_Type value to a null pointer. Finalization of both File_Type objects and file-stream objects would be complicated. (One possible implementation would be for both File_Type objects and file-stream objects to be controlled objects pointing to an object that includes both a reference count and an is-opened flag. Such an object would be allocated upon creation of a File_Type object, but would continue to exist beyond the lifetime of the File_Type object if there were still unfinalized file-stream objects pointing to it.)
!appendix

!section A.12.1(26)
!section A.12.2(3)
!section A.12.3(3)
!subject Stream I/O and Status_Error
!reference RM9X-A.12.1(26)
!reference RM9X-A.12.2(3)
!reference RM9X-A.12.3(3)
!from Norman Cohen
!reference as: 94-5012.a Norman H. Cohen 94-11-23>>
!discussion

None of the sections describing streams for I/O mention the raising of
Status_Error.  Is it okay to call the Stream function with a file that is
closed, as long as the file is opened before I/O is performed, or does a
call on Stream raise Status_Error in this case?  If Stream can be called
with a closed file, does an attempt to read from or write to the stream
pointed to by the resulting access value raise Status_Error?

****************************************************************

!section A.12.1(26)
!section A.12.2(3)
!section A.12.3(3)
!subject Stream I/O and Status_Error
!reference RM9X-A.12.1(26)
!reference RM9X-A.12.2(3)
!reference RM9X-A.12.3(3)
!reference 94-5012.a Norman H. Cohen 94-11-23
!from Bob Duff
!reference as: 94-5017.a Bob Duff 94-11-28>>
!discussion

Note that now, having sent the final version to ISO for publication, I'm
now in "interpreting" mode, rather than "fixing" mode.  ;-)

> None of the sections describing streams for I/O mention the raising of
> Status_Error.  Is it okay to call the Stream function with a file that is
> closed, as long as the file is opened before I/O is performed, or does a
> call on Stream raise Status_Error in this case?

I think it's OK -- no Status_Error.

> ...If Stream can be called
> with a closed file, does an attempt to read from or write to the stream
> pointed to by the resulting access value raise Status_Error?

Yeah, I guess so.

****************************************************************

!section A.12.01(29)
!subject Ada.Streams.Read and Ada.Streams.Write can raise Status_Error
!reference RM95-A.12.01(29)
!reference RM95-13.13.01(08)
!reference RM95-13.13.01(09)
!reference AI95-00001
!from Pascal Leroy 95-10-09
!reference as: 95-5318.a Pascal Leroy 95-10-9>>
!discussion

AI95-00001 proposes that the creation of a Stream_Access value referring to a
closed file be allowed (i.e., do not raise an exception) on the grounds that
"it provides the programmer with more flexibility than forbidding it."

It seems to me that the creation of a Stream_Access value from a closed file
should be considered a programming error, and therefore should raise an
exception (Status_Error is clearly the appropriate exception in this
situation).  All operations on closed files in Ada raise exceptions (except of
course Is_Open).  It could have been argued for instance that closing a closed
file provides some flexibility to the programmer; still, the designers of the
language (both vintages) probably thought that it would be in most cases a
programming error, and decided to raise an exception.

We should stick to that philosophy, and require the function Stream to raise
Status_Error when given a closed file.  (Of course, as explained in the AI, we
still need a check on Read and Write to account for the fact that the file may
have been closed in the meantime.)


****************************************************************

!section A.12.1(01)
!subject Ada.Streams.Read and Ada.Streams.Write can raise Status_Error
!reference AI95-00001
!reference RM95-A.12.1(1,29)
!reference RM95-A.10.3(2-6)
!reference RM95-A.10.3(22,23)
!from Tucker Taft 95-10-30
!reference 95-5373.c Tucker Taft 95-10-30>>
!discussion

I don't support the recommendation that a closed file may
be passed to Ada.Streams.Stream_IO.Stream.  I believe this
creates an unnecessary implementation burden with little
benefit, and is inconsistent with the somewhat analogous routines
(from an implementation point of view) Set_Input, Set_Output, and
Set_Error.

In many implementations, it is convenient to represent a File_Type
as a pointer, which is null when closed.  The rules for Set_Input,
Set_Output, and Set_Error given in A.10.3(22,23), which relate
to usage of a default file after the corresponding internal file
object has closed or gone out of scope, seem designed to support
such an implementation approach.

However, if we require that a stream returned by Stream_IO.Stream
automatically "track" a Stream_IO.File_Type as it is closed
and reopened, then clearly an implementation using a simple pointer
for the File_Type, which is set to null on Close, is no longer possible.

I would suggest that having a stream referring to the "same" file
as a Stream_IO.File_Type is analogous to having "Current_Input"
or "Current_Output" referring to the "same" file as a Text_IO.File_Type,
and that analogous rules should apply.  In particular, Status_Error
should be raised if File is not open when Stream(File) is called,
and if File is subsequently closed, then a result returned
from an earlier call on Stream(File) is no longer meaningful.
The anticipated use of Stream(File) was a parameter to 'Read or 'Write.
There was no expectation that the result of Stream(File) would be saved in
a separate variable, and then have File manipulated directly via
Close and Open.

If we require the behavior suggested in this AI, then there is
effectively no way to recover the stream object associated with
a Stream_IO.File_Type, since there may be any number of values
returned by Stream(File) laying around.

It is somewhat uncomfortable to consider it erroneous to use
such access values after a File is closed, or its scope
is left, but the language already specifies similar behavior
for Current_Input and Current_Output, which are presumably much
more commonly used.  Furthermore, if we presume the normal
pattern of use of the Stream function is directly as a parameter
to 'Read or 'Write, then the erroneous situation should never
arise.

Of course a friendly implementation could presumably
detect the "late" use of such access values (though not without
leaving around some amount of junk to detect the late uses), but requiring
this detection might add significantly to the overhead of using Stream_IO
(or Text_Streams), with marginal benefit in the normal pattern of use.

****************************************************************

!section 13.13.01(08)
!subject question on Stream function for Stream_IO
!reference RM95-13.13.01(08)
!reference AI-00001
!from Bob Duff
!reference 96-5473.a Robert A Duff 96-4-12>>
!discussion

At the last ARG meeting Norman Cohen volunteered to re-write AI-1.
(Norm, I know you weren't there, but you got "volunteered". :-)
If you don't have time, please let me know so I can do it
myself.)

According to my notes, the ARG disagreed with the current version of
AI-1, which says:

  A call on Ada.Streams.Stream_IO.Stream returns a Stream_Access value
  even if the file passed as a parameter is closed.  If a stream file is
  closed and its stream is passed to Ada.Streams.Read or
  Ada.Streams.Write, the call raises Ada.IO_Exceptions.Status_Error.

Instead, Status_Error should be raised on the Stream call.  In addition,
Text_IO.Text_Streams, and the Wide_Text_IO version, also need to be
addressed.  I guess Read and Write still need to do a check, though.
In private e-mail, Robert Dewar sent me the following, which should
be taken into account:

> It seems clear that the file must be open to take its Stream value.
>
> What is not obvious from the RM (and was not obvious to the writers of one
> of the ACVC tests) is that if a file is closed, the corresponding Stream
> value is no longer usable, even if the same file is reopened.
>
> This is obviously a requirement from an implementation point of view, but
> I can't find a specific RM rule that applies here. Possibly the same
> consideration applies to Text_Streams, I did not check.

- Bob

****************************************************************

Questions? Ask the ACAA Technical Agent