So, the following program kinda sorta looks like a naive implementation of the simplest concept of the Unix cat program:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Streams, Ada.Text_IO.Text_Streams;
procedure Not_Really_Cat is
Input_Stream : access Ada.Streams.Root_Stream_Type'Class :=
Ada.Text_IO.Text_Streams.Stream (File => Ada.Text_IO.Current_Input);
Output_Stream : access Ada.Streams.Root_Stream_Type'Class :=
Ada.Text_IO.Text_Streams.Stream (File => Ada.Text_IO.Current_Output);
C : Character;
begin
while not End_Of_File loop
Character'Read (Input_Stream, C);
Character'Write (Output_Stream, C);
end loop;
end Not_Really_Cat;
But it is not!
If you do
printf 'Hello!\n' | ./cat | od -c
you get
0000000 H e l l o !
0000006
Notice that there is no newline at the end, even though there was a newline in the input.
Looking at this a little closer, it turns out that this happens because the End_Of_File
function in use there is from Ada.Text_IO
, and it behaves differently from the End_Of_File
function that is used on Stream files, as declared in Ada.Streams.Stream_IO
.
Here’s another program, that uses Ada.Streams.Stream_IO
:
with Ada.Streams, Ada.Text_IO.Text_Streams;
with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO;
with Ada.Command_Line; use Ada.Command_Line;
procedure Try_Streams is
Input_File : File_Type;
Input_Stream : access Ada.Streams.Root_Stream_Type'Class;
Output_Stream : access Ada.Streams.Root_Stream_Type'Class :=
Ada.Text_IO.Text_Streams.Stream (File => Ada.Text_IO.Current_Output);
C : Character;
begin
Open (Input_File, In_File, Argument (1)); -- "../data/try_streams.dat"
Input_Stream := Stream (Input_File);
while not End_Of_File (Input_File) loop
Character'Read (Input_Stream, C);
Character'Write (Output_Stream, C);
end loop;
end Try_Streams;
If I pass the name of a file that contains just Hello!\n
to this program, it works properly and outputs the final newline.
But as the File_Type from Ada.Text_IO and the File_Type from Ada.Streams.Stream_IO are not compatible, I can’t see any way to use the End_Of_File from Ada.Streams.Streams_IO with a Stream created from Ada.Text_IO.Current_Input by way of the function Ada.Text_IO.Text_Streams.Stream
.
Is my understanding correct?
Is there any way to portably obtain a value of Ada.Streams.Stream_IO.File_Type
that is associated with the standard input, so that it may be used with Ada.Streams.Stream_IO.End_Of_File
?