Ada: flexible Text_IO File_Type for redirecting output with SET_OUTPUT?

Viewed 284

I've inherited a project that has two output modes, console and plain-text file. The project uses Ada.Text_IO.SET_OUTPUT to select one or the other.

I want to create a third SET_OUTPUT option, one that can easily re-direct output to a variety of formats other than stdout or a disk file. I'd like the output to be some sort of in-RAM object or "file" so that it can be quickly read by multiple clients. I also need to keep the code portable, so ideally the solution would stick to the standard libraries.

I've tried instantiations of Sequential_IO, but the code base is too large and inconsistent (wrt overloadings and renamings of Text_IO's procedures and whether Text_IO is called by full dot notation) to quickly and reliably replace calls.

I must be uncreative (and I'm certainly new to Ada), but the solution I keep coming to seems overly complex and convoluted--creating a container of Text_IO's File_Type in a memory pool managed at a low level; then SET_OUTPUT to that in-RAM file, from where it can be pushed or pulled to clients.

I hope I'm missing something, and that someone can help me find an simpler way. Thanks in advance.

3 Answers

Text_IO is specifically for files, so there's no portable way to use it to write to memory. The normal way to allow writing to files, memory, or anything else you can define, is to use streams, but that would require replacing most uses of Text_IO to use streams instead. If that's acceptable, then Ada.Text_IO.Text_Streams allows writing to Current_Output as a stream.

If you’re not going to change all the Text_IO calls, you’re going to be stuck with textual output to your chosen in-memory (for example) storage, which will probably mean textual content (unless your historical developers have adhered rigorously to parsable format standards!)

Assuming GNAT, the way IO deals with files is described in the GNAT Reference Manual; particularly, there’s no requirement for a file to be a regular disk file, so long as it’s accessible via C system calls, e.g. fopen(). So you could pipe to a log storage manager.

On the other hand you could just use a shared file (see the FORM strings section of the GNAT RM).

Does the system have just one possible text file output? That would make things easier ...

I'd give a try with something like this:

  type Extended_File_Type is record
    Is_Normal : Boolean;
    File      : Ada.Text_IO.File_Type;
    Special   : Integer;  --  <- Dummy, replace by your fancy in-RAM object.
  end record;

  procedure Put_Line (EFile : Extended_File_Type; S : String) is
  begin
    if EFile.Is_Normal then
      Ada.Text_IO.Put_Line (Efile.File, S);
    else
      null;  --  Output to your special object.
    end if;
  end;
Related