Friday, August 16, 2013

Automatic new line at program exit for Ada.Text_IO output.

For these two simple programs:

with Ada.Text_IO; use Ada.Text_IO;

procedure Hello is
begin
    Put("Hello");
    Put(" ");
    Put("World!");
end Hello;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Text_IO.Text_Streams; use Ada.Text_IO.Text_Streams;

procedure hello_stream is
    std_out   : Stream_Access;
begin
    std_out := Stream (Standard_Output);

    String'Write (std_out, "Hello");
    String'Write (std_out, " ");
    String'Write (std_out, "World!");
end hello_stream;

When executing the two program, you would have two different result, for hello program:

# ./hello
Hello World!
#

For hello_stream program:

# ./hello_stream
Hello World!# 

I have known this problem for some time, but did not dig into the root cause of it.  Recently I asked this question in comp.lang.ada group for a root cause of it. And Jeffrey gave me the answer.

The related references in ARM are A.7(6) and A.10.1(86).

For gnat compiler File_Type is defined at a-textio.ads:

...
type Text_AFCB;
type File_Type is access all Text_AFCB;

type Text_AFCB is new FCB.AFCB with record
...
end record
...
procedure AFCB_Close (File : not null access Text_AFCB);
Where FCB.AFCB is a tagged type defined in s-ficobl.ads.

In AFCB_Close() procedure, it calls Terminate_Line(), which will try to insert a new line if not terminate properly.

It seems, when program exit, gnat doing the finalization for Standard_Output call AFCB_Close(), which insert the new line if necessary.

p.s. This is tested under Slackware64 Linux with GCC gnat compiler.