Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

redirecting the standard output

823 views
Skip to first unread message

Martin Dowie

unread,
Apr 10, 2001, 10:32:58 AM4/10/01
to
This time with a subject... :-)

Target System: PowerPC, AdaMULTI v1.8.9b, VxWorks 5.4

How do I redirect the standard output? I'd like to redirect it to device
"/null"

Attempts:
Open (DevNull, Append_File, "/null");
Open (DevNull, "/null", "/null");

just cause Status_Error, i.e. the device is already "open". So how can
I then "Set_Output (DevNull);" without having the device object in
File_Type form?..

Frank

unread,
Apr 10, 2001, 11:01:16 AM4/10/01
to
Hi!

I hope you don't mind that I add a question here :-)
It is about the same subject:

Is it possible to say that one task shall have one std output and another
task a different std output?
Eg. that two task (in the same Ada-program) can have std output to different
Xterm windows in Linux.

Frank


Mark Biggar

unread,
Apr 10, 2001, 12:17:28 PM4/10/01
to
Frank wrote:
> Is it possible to say that one task shall have one std output and another
> task a different std output?
> Eg. that two task (in the same Ada-program) can have std output to different
> Xterm windows in Linux.

No, the Ada Io packages are not task save, or aware. You can't even
reliably write form two tasks to the same file with out imposing
your own explicit locking protocol, such as using a protected
object or a handler task.

--
mark.a...@home.com

Stephen Leake

unread,
Apr 10, 2001, 12:08:25 PM4/10/01
to
"Martin Dowie" <martin...@gecm.com> writes:

> This time with a subject... :-)
>
> Target System: PowerPC, AdaMULTI v1.8.9b, VxWorks 5.4
>
> How do I redirect the standard output? I'd like to redirect it to device
> "/null"

Normally this is done from the command line, when you launch your
executable. What OS are you on?


> Attempts: Open (DevNull, Append_File, "/null"); Open (DevNull,
> "/null", "/null");
>
> just cause Status_Error, i.e. the device is already "open". So how can
> I then "Set_Output (DevNull);" without having the device object in
> File_Type form?..

You can use Ada.Text_IO.Set_Output to set the _current_ output to some
file. But it has to be an open file, and you haven't gotten there yet.

Backing up a bit, why do you want to do this? I can guess that you
want to turn off some debugging output. It is _far_ better to define a
Debug_IO package, with a Boolean or Integer debug enabled variable.
Then have a style guide that says "Ada.Text_IO is _forbidden_ in
delivered code; use Debug_IO if you need debug output".

--
-- Stephe

Stephen Leake

unread,
Apr 10, 2001, 12:46:15 PM4/10/01
to
Stephen Leake <stephen....@gsfc.nasa.gov> writes:

> "Martin Dowie" <martin...@gecm.com> writes:
>
> > This time with a subject... :-)
> >
> > Target System: PowerPC, AdaMULTI v1.8.9b, VxWorks 5.4
> >
> > How do I redirect the standard output? I'd like to redirect it to device
> > "/null"
>
> Normally this is done from the command line, when you launch your
> executable. What OS are you on?

Duh; VxWorks! My brain is _not_ in high-power mode.

Anyway, I don't know how to redirect in VxWorks, but I _think_ it uses
the Posix shell redirection:

adacode > /dev/nul

>
>
>
> > Attempts: Open (DevNull, Append_File, "/null"); Open (DevNull,
> > "/null", "/null");
> >
> > just cause Status_Error, i.e. the device is already "open". So how can
> > I then "Set_Output (DevNull);" without having the device object in
> > File_Type form?..
>
> You can use Ada.Text_IO.Set_Output to set the _current_ output to some
> file. But it has to be an open file, and you haven't gotten there yet.
>
> Backing up a bit, why do you want to do this? I can guess that you
> want to turn off some debugging output. It is _far_ better to define a
> Debug_IO package, with a Boolean or Integer debug enabled variable.
> Then have a style guide that says "Ada.Text_IO is _forbidden_ in
> delivered code; use Debug_IO if you need debug output".
>
> --
> -- Stephe

--
-- Stephe

James Rogers

unread,
Apr 10, 2001, 4:38:14 PM4/10/01
to

On the other hand, it is possible to open each device (Xterm) as a
separate file, and write to that file in only one task. If this does
not meet your needs then consider creating one or more tasks whose
role is to output data. You could design those tasks to take their
input data either from an entry using the classical Ada rendezvous,
or using a protected object as a communication buffer. Tasks
requiring output would simply call the entry on the task or the
protected object to "output" their data. The task actually writing
to the Xterm would respond to the data and perform the required
actions.

Jim Rogers
Colorado Springs, Colorado USA

Jeff Creem

unread,
Apr 10, 2001, 8:04:48 PM4/10/01
to
Even if you some hope open the file (try just simple Out_File for the mode)
you may
run into problems.

On older vxWorks at least, writes to a file descriptor tied to the null
device always return
an error status so my compiler was seeing that and raising an exception on
all output.

I ended up having to create a null device driver that always returned good
status for writes.

"Martin Dowie" <martin...@gecm.com> wrote in message
news:3ad31759$1...@pull.gecm.com...

Ted Dennison

unread,
Apr 10, 2001, 5:00:36 PM4/10/01
to
In article <upuekp...@gsfc.nasa.gov>, Stephen Leake says...

>
>Backing up a bit, why do you want to do this? I can guess that you
>want to turn off some debugging output. It is _far_ better to define a
>Debug_IO package, with a Boolean or Integer debug enabled variable.
>Then have a style guide that says "Ada.Text_IO is _forbidden_ in
>delivered code; use Debug_IO if you need debug output".

We did something rather similar to this with our vxWorks program. We wrote a
"Log" package that takes in messages in a task-safe manner (using a queue to
prevent priority inversions), slaps a time stamp and severity level on them,
then outputs them to standard IO and to a log file. The standard IO part can be
turned off at runtime by tweaking a global variable (in vxWorks all exported
globals can be modified at the command line). Individual developers and
*strongly* discuraged from using Text_IO directly.

When using a RTOS, I'd expect everyone to develop something along these lines.
You can't deal with the random crashes and priority inversions that would be
caused by unrestrained IO calls in a real-time application.

---
T.E.D. homepage - http://www.telepath.com/dennison/Ted/TED.html
home email - mailto:denn...@telepath.com

Smark

unread,
Apr 10, 2001, 12:46:16 PM4/10/01
to
"Martin Dowie" <martin...@gecm.com> wrote in message
news:3ad31759$1...@pull.gecm.com...

I have also had problems redirecting Ada.Text_Io on the same platform.
When I use the applicable VxWorks calls, ioGlobalStdSet or ioTaskStdSet,
my printf's from C programs are redirected, but Ada.Text_Io seems to
be unaffected. In my case, I'm trying to redirect IO to an open
socket.

The solution I'm toying with is making an Ada interface to printf.
Is there a better way to get Ada IO to respond to calls to the
above VxWorks functions?

One thing you might try, Martin, is to re-direct to "/null/0".

Cheers,
Mark

Smark

unread,
Apr 10, 2001, 1:13:33 PM4/10/01
to
"Stephen Leake" <stephen....@gsfc.nasa.gov> wrote in message
news:uitkcp...@gsfc.nasa.gov...

> Stephen Leake <stephen....@gsfc.nasa.gov> writes:
>
> > "Martin Dowie" <martin...@gecm.com> writes:
> >
> > > This time with a subject... :-)
> > >
> > > Target System: PowerPC, AdaMULTI v1.8.9b, VxWorks 5.4
> > >
> > > How do I redirect the standard output? I'd like to redirect it to device
> > > "/null"
> >
> > Normally this is done from the command line, when you launch your
> > executable. What OS are you on?
>
> Duh; VxWorks! My brain is _not_ in high-power mode.
>
> Anyway, I don't know how to redirect in VxWorks, but I _think_ it uses
> the Posix shell redirection:
>
> adacode > /dev/nul

No, while VxWorks is based on Unix, it does not have a similar shell.
The general way to redirect IO in VxWorks is with ioGlobalStdSet (or
ioTaskStdSet for task-specific IO redirection).

Mark

Martin Dowie

unread,
Apr 11, 2001, 3:32:25 AM4/11/01
to
> Backing up a bit, why do you want to do this? I can guess that you
> want to turn off some debugging output. It is _far_ better to define a
> Debug_IO package, with a Boolean or Integer debug enabled variable.
> Then have a style guide that says "Ada.Text_IO is _forbidden_ in
> delivered code; use Debug_IO if you need debug output".

In our 'real' development code this is exactly what will be done (we have
a Project.Text_IO package which is the same for all projects, and we
slap on whatever the OS provides in the way of 'Simple_IO' via the body,
or 'null'ed for production)

This is for testing and timing purposes.

So far, from what simple tests we've run each character seems to be
taking about 10ms to display via serial and 0.03ms via ethernet - does this
sound reasonable to everyone?.. :-)

Graham Baxter

unread,
Apr 11, 2001, 5:48:17 AM4/11/01
to

--
Try:

int fd = open("/null",O_RDWR,0);
if(fd != ERROR)
{
ioGlobalStdSet(STD_IN,fd);
ioGlobalStdSet(STD_OUT,fd);
ioGlobalStdSet(STD_ERR,fd);
}

Regards,


Graham Baxter
Freelance Software Engineer
gba...@NOSPAM.bcs.org.uk

Stephen Leake

unread,
Apr 11, 2001, 8:04:07 AM4/11/01
to
"Martin Dowie" <martin...@nospam.baesystems.com> writes:

> > Backing up a bit, why do you want to do this? I can guess that you
> > want to turn off some debugging output. It is _far_ better to define a
> > Debug_IO package, with a Boolean or Integer debug enabled variable.
> > Then have a style guide that says "Ada.Text_IO is _forbidden_ in
> > delivered code; use Debug_IO if you need debug output".
>
> In our 'real' development code this is exactly what will be done (we have
> a Project.Text_IO package which is the same for all projects, and we
> slap on whatever the OS provides in the way of 'Simple_IO' via the body,
> or 'null'ed for production)
>
> This is for testing and timing purposes.

Hmm, another requirement I use is "test and time what you fly". It is
easier to use Project.Text_IO from the start, than to change to it
later.

Also, packages should be testable without editing; use child packages to
get access to private stuff.

> So far, from what simple tests we've run each character seems to be
> taking about 10ms to display via serial and 0.03ms via ethernet -
> does this sound reasonable to everyone?.. :-)

Hmm. Assuming 9600 baud serial link, 9 bits per character (with
parity), that's about 1 ms per character. So you seem to have a
significant tasking overhead in the serial implementation.

--
-- Stephe

Stephen Leake

unread,
Apr 11, 2001, 8:06:26 AM4/11/01
to
"Smark" <not.pr...@all.com> writes:

I don't know precisely, but you should definitely ask your Ada vendor
how to do it. If you are using GNAT, look at the source for Text_IO
and see what they are doing.

Interfacing to printf is _not_ easy. 'puts' is a better C function to
call, if you have to resort to that.

--
-- Stephe

Martin Dowie

unread,
Apr 11, 2001, 10:11:59 AM4/11/01
to
> Interfacing to printf is _not_ easy. 'puts' is a better C function to
> call, if you have to resort to that.

we tried a version which imported printf - and it was exactly the same
throughput...


Martin Dowie

unread,
Apr 11, 2001, 10:15:34 AM4/11/01
to
> Hmm, another requirement I use is "test and time what you fly". It is
> easier to use Project.Text_IO from the start, than to change to it
> later.

we use the nulled version for debugging only when it hits the target (if
the bug can be spotted appropiately using it) and the non-nulled
version primarily for host work.

All formal integration/system tests are done using the null-ed version.

> Also, packages should be testable without editing; use child packages to
> get access to private stuff.

absolutely, hence our use of a "Project.Text_IO" which can be null-ed.

> Hmm. Assuming 9600 baud serial link, 9 bits per character (with
> parity), that's about 1 ms per character. So you seem to have a
> significant tasking overhead in the serial implementation.

yup :-(


Martin Dowie

unread,
Apr 12, 2001, 8:23:26 AM4/12/01
to
Cheers Graham! That's done the trick!

And in return to the community here is the Ada equivilant we will
be using (feel free to add your own comments :-)


-- vxworks.ads
--------------
with Interfaces.C;

package VxWorks is

subtype A_Status is Interfaces.C.Int;

use type A_Status;

Ok : constant A_Status := 0;
Error : constant A_Status := -1;

end VxWorks;

-- vxworks-iolib.ads
--------------------
with Interfaces.C;
with Interfaces.C.Strings;

package VxWorks.ioLib is

O_RDONLY : constant := 16#0000#;
O_WRONLY : constant := 16#0001#;
O_RDWR : constant := 16#0002#;
O_CREAT : constant := 16#0200#;

subtype A_File is Interfaces.C.Int;

function Open (Name : Interfaces.C.Strings.Chars_Ptr;
Flags : Interfaces.C.Int;
Mode : Interfaces.C.Int) return A_File;

function Close (File : A_File) return A_Status;

STD_IN : constant A_File := 0;
STD_OUT : constant A_File := 1;
STD_ERR : constant A_File := 2;

function ioGlobalStdGet (StdFd : A_File) return A_File;

procedure ioGlobalStdSet (StdFd : A_File;
NewFd : A_File);

function ioTaskStdGet (TaskId : Interfaces.C.Int := 0;
StdFd : A_File) return A_File;

procedure ioTaskStdSet (TaskId : Interfaces.C.Int := 0;
StdFd : A_File;
NewFd : A_File);

private

pragma Import (C, Open, "open");
pragma Import (C, Close, "close");
pragma Import (C, ioGlobalStdGet, "ioGlobalStdGet");
pragma Import (C, ioGlobalStdSet, "ioGlobalStdSet");
pragma Import (C, ioTaskStdGet, "ioTaskStdGet");
pragma Import (C, ioTaskStdSet, "ioTaskStdSet");

end VxWorks.ioLib;


-- text.ads
------------
package Text is

procedure Send_Outputs_To_Null_Device;

procedure Return_Outputs_To_Standard_Devices;

end Text;


-- text.adb
------------
with Interfaces.C.Strings;
with VxWorks;
with VxWorks.ioLib;

package body Text is

Null_Device,
Standard_Output,
Standard_Error : VxWorks.ioLib.A_File;


procedure Send_Outputs_To_Null_Device is

use type VxWorks.ioLib.A_File;

begin

Null_Device := VxWorks.ioLib.Open (Name =>
Interfaces.C.Strings.New_String ("/null"),
Flags => VxWorks.ioLib.O_RDWR,
Mode => 0);

if Null_Device = VxWorks.Error then
return;
end if;

Standard_Output := VxWorks.ioLib.ioGlobalStdGet (StdFd =>
VxWorks.ioLib.STD_OUT);
Standard_Error := VxWorks.ioLib.ioGlobalStdGet (StdFd =>
VxWorks.ioLib.STD_ERR);

VxWorks.ioLib.ioGlobalStdSet (StdFd => VxWorks.ioLib.STD_OUT,
NewFd => Null_Device);

VxWorks.ioLib.ioGlobalStdSet (StdFd => VxWorks.ioLib.STD_ERR,
NewFd => Null_Device);

end Send_Outputs_To_Null_Device;


procedure Return_Outputs_To_Standard_Devices is

Status : VxWorks.A_Status;

begin

VxWorks.ioLib.ioGlobalStdSet (StdFd => VxWorks.ioLib.STD_OUT,
NewFd => Standard_Output);

VxWorks.ioLib.ioGlobalStdSet (StdFd => VxWorks.ioLib.STD_ERR,
NewFd => Standard_Error);

Status := VxWorks.ioLib.Close (File => Null_Device);

end Return_Outputs_To_Standard_Devices;

end Text;


-- test.adb
-----------
with Ada.Real_Time; use Ada.Real_Time;
with Ada.Text_IO; use Ada.Text_IO;
with Text;

procedure Test is

procedure Display (Item : String; Result : out Duration) is

Start_Time,
End_Time : Time;

begin

Start_Time := Clock;

for I in 1 .. 10_000 loop

Put (Item => Item);

end loop;

End_Time := Clock;

Result := To_Duration (TS => End_Time - Start_Time);

end Display;

Times : array (Natural range 1 .. 10) of Duration;

Test_String : constant String := "1234567890";

begin

Text.Send_Outputs_To_Null_Device;

for Index in Times'Range loop

Test (Item => Test_String (1 .. Index),
Result => Times (Index));

end loop;

Text.Return_Outputs_To_Standard_Devices;

for Index in Times'Range loop

Put_Line (Integer'Image (Index) & " Time =" & Duration'Image (Times
(Index)));

end loop;

end Display;

"Graham Baxter" <gba...@NOSPAM.bcs.org.uk> wrote in message
news:3AD42861...@NOSPAM.bcs.org.uk...

Smark

unread,
Apr 12, 2001, 10:01:24 AM4/12/01
to
So the trick was to use VxWorks' "open" and "ioGlobalStdSet" rather than
Ada.Text_Io's "Open" and "Set_Output" ... interesting.

Mark


"Martin Dowie" <martin...@gecm.com> wrote in message

news:3ad59c42$1...@pull.gecm.com...

martin.m.dowie

unread,
Apr 12, 2001, 3:52:49 PM4/12/01
to
yes, the other 'trick' I had to do was get the std_in/std_out constants the right
way round (which managed to throw me for an hour!) ;-)

Tucker Taft

unread,
Apr 13, 2001, 12:23:30 PM4/13/01
to

You can't set the "default" Text_IO output file to
two different files at the same time. However, you
could use the "Task Attribute" feature of Ada 95 to
give each task a File_Access attribute, and do all your
output through that. Then each task could have its own,
without having to explicitly pass it to every routine
under the sun.

>
> Frank

--
-Tucker Taft s...@avercom.net http://www.averstar.com/~stt/
Chief Technology Officer, AverCom Corporation (A Titan Company)
Burlington, MA USA (AverCom was formerly the Commercial Division of AverStar:
http://www.averstar.com/services/ebusiness_applications.html)

0 new messages