comp.lang.ada
 help / color / mirror / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* Re: Is it possible to redirect text output to a String or Unbounded_String?
    2021-06-10  6:50  5% ` Simon Wright
@ 2021-06-10 21:12  6% ` Shark8
  1 sibling, 0 replies; 115+ results
From: Shark8 @ 2021-06-10 21:12 UTC (permalink / raw)


On Wednesday, June 9, 2021 at 8:17:20 PM UTC-6, Jerry wrote:
> Is it possible to redirect text output to a String or Unbounded_String rather than to a file? 
> 
> I know there are versions of Put that take a string as a first argument but I don't want to have to write a special-purpose version of a stretch of code just for this purpose, since I want to keep the ability to also output text to a terminal. 
> 
> I suppose I could redirect text to a file and then somehow read it back in as one string but that seems like a kludge. 
> 
> Jerry
Well...
------------------------------------
    Generic
        Type FILE_TYPE(<>) is limited private;
        Type FILE_MODE     is (<>);
        Type Stream_Access is access all Ada.Streams.Root_Stream_Type'Class;
        with Procedure Indirect_Put_Line(Item : String);
        -- put all the subprograms you need here; prefix with Indirect_
        Object : in out FILE_TYPE;
        Stream : in Stream_Access;
    Package Duplicating_IO is
        -- Declare all the subprograms used above w/o Indirect_
        Procedure Put_Line(Item : String);
    End Duplicating_IO;
------------------------------------
    Package Body Duplicating_IO is
        -- Implementations; if there's a lot consider generics+renames.
        Procedure Put_Line(Item : String) is
        Begin
            String'Output( Stream, Item );
            Indirect_Put_Line( Item );
        End Put_Line;
    End Duplicating_IO;
------------------------------------    
    OBJ : Ada.Text_IO.File_Type:= Ada.Text_IO.Standard_Output;
    STR : Ada.Text_IO.Text_Streams.Stream_Access renames
      Ada.Text_IO.Text_Streams.Stream( OBJ );
------------------------------------
    Package Split_IO is new Duplicating_IO
      (
       File_Type         => File_Type,
       File_Mode         => File_Mode,
       Stream_Access     => Ada.Text_IO.Text_Streams.Stream_Access,
       Indirect_Put_Line => Put_Line,
        Object           => OBJ,
        Stream           => STR
      );

^ permalink raw reply	[relevance 6%]

* Re: Is it possible to redirect text output to a String or Unbounded_String?
  @ 2021-06-10  6:50  5% ` Simon Wright
  2021-06-10 21:12  6% ` Shark8
  1 sibling, 0 replies; 115+ results
From: Simon Wright @ 2021-06-10  6:50 UTC (permalink / raw)


Jerry <list_email@icloud.com> writes:

> Is it possible to redirect text output to a String or Unbounded_String
> rather than to a file?

I think you could use Ada.Text_IO.Text_Streams, except it's the wrong
way round (treat a file as a stream). If you could treat a stream as a
file you could use Text_IO to write to the file view and suck the stream
view out into whatever format you wanted. Maybe.

^ permalink raw reply	[relevance 5%]

* Re: Better way to fill Storage_IO?
  2021-05-18 20:39  0%     ` Simon Wright
@ 2021-05-19  6:24  0%       ` Dmitry A. Kazakov
  0 siblings, 0 replies; 115+ results
From: Dmitry A. Kazakov @ 2021-05-19  6:24 UTC (permalink / raw)


On 2021-05-18 22:39, Simon Wright wrote:
> Michael Hardeman <mhardeman25@gmail.com> writes:
> 
>> I was kind of hoping there would be an interface like
>> Ada.Text_IO.Text_Streams, where you could just directly stream from
>> the variable's address or access without having to write the variable
>> into the stream first. I'm not sure, but the writing part seems a bit
>> like an extra step.
> [...]
>> I was kind of trying to show you could move through the stream like a
>> parser instead of just consuming the whole thing. i.e. like if you
>> wanted to parse the hex into an array of Unsigned_32 or Unsigned_64
>> for some algorithm.
> 
> I don't understand the scenario.
> 
>    Source   >>   Stream   >>   Destination
> 
> If Source and Destination are in the same process, there's no need to
> involve streams at all.

The picture actually is:

    Producer -> Output stream = Input Stream -> Consumer

The producer could be a code generator, the consumer could be a parser.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

^ permalink raw reply	[relevance 0%]

* Re: Better way to fill Storage_IO?
  2021-05-17 19:23  4%   ` Michael Hardeman
@ 2021-05-18 20:39  0%     ` Simon Wright
  2021-05-19  6:24  0%       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 115+ results
From: Simon Wright @ 2021-05-18 20:39 UTC (permalink / raw)


Michael Hardeman <mhardeman25@gmail.com> writes:

> I was kind of hoping there would be an interface like
> Ada.Text_IO.Text_Streams, where you could just directly stream from
> the variable's address or access without having to write the variable
> into the stream first. I'm not sure, but the writing part seems a bit
> like an extra step.
[...]
> I was kind of trying to show you could move through the stream like a
> parser instead of just consuming the whole thing. i.e. like if you
> wanted to parse the hex into an array of Unsigned_32 or Unsigned_64
> for some algorithm.

I don't understand the scenario.

  Source   >>   Stream   >>   Destination

If Source and Destination are in the same process, there's no need to
involve streams at all.

If Source and Destination are separated - different processes on the
same computer, different computers (possibly with different endianness),
different times - we have to agree on a protocol as to what's sent over
the stream. For a String Z, perhaps the first 4 bytes are the
little-endian Z'First, the next are Z'Last, then the actual bytes of Z.

That's what streams are for (and that's what String'Output does).

Once you have the stream, you can go through it in any way you need to;
you must know what to expect so as to make sense of it. In your example,
you have to know that the bytes in the stream are hex characters.

==========

As to creating the stream: I suppose there could be something like
'Image, where the attribute could originally only be applied to a type:
you used to have to say

   Integer'Image (An_Integer)

whereas now you can say just

   An_Integer'Image

so as well as the current ARM 13.13.2(4), for subtype S of type T

   procedure S'Write(
      Stream : not null access Ada.Streams.Root_Stream_Type'Class;
      Item : in T)

one could have for an object O

   procedure O'Write(
      Stream : not null access Ada.Streams.Root_Stream_Type'Class)

but we don't, not even in Ada 202x.

^ permalink raw reply	[relevance 0%]

* Re: Better way to fill Storage_IO?
  @ 2021-05-17 19:23  4%   ` Michael Hardeman
  2021-05-18 20:39  0%     ` Simon Wright
  0 siblings, 1 reply; 115+ results
From: Michael Hardeman @ 2021-05-17 19:23 UTC (permalink / raw)


On Monday, May 17, 2021 at 3:14:43 PM UTC-4, Simon Wright wrote:
> 
> 'Output writes the discriminants of the object, if any, then the object; 
> 'Input uses them to reconstruct the object, so in this case that means 
> the bounds, and hence the length.
> > I was wondering if we could find a better way to fill the stream other 
> > than writing the variables into it? Can anyone figure out a good way 
> > to just stream a variable's bytes directly?
> This *is* the way to just stream the variable's bytes directly. What 
> sort of syntax were you hoping for?

I was kind of hoping there would be an interface like Ada.Text_IO.Text_Streams, where you could just directly stream from the variable's address or access without having to write the variable into the stream first. I'm not sure, but the writing part seems a bit like an extra step.

This would be my version: 
> 
> with Ada.Text_IO; use Ada.Text_IO; 
> with Ada.Streams.Storage.Unbounded; 
> 
> procedure Test is 
> Test : constant String := "040b2cec765b4bbbdb29d83b6dcaf776"; 
> Test_Stream : aliased Ada.Streams.Storage.Unbounded.Stream_Type; 
> begin 
> String'Output (Test_Stream'Access, Test); 
> declare 
> S : constant String := String'Input (Test_Stream'Access); 
> begin 
> Put_Line (S); 
> end; 
> end Test; 

I was kind of trying to show you could move through the stream like a parser instead of just consuming the whole thing. i.e. like if you wanted to parse the hex into an array of Unsigned_32 or Unsigned_64 for some algorithm.

^ permalink raw reply	[relevance 4%]

* Re: Ada.Text_IO.File_Type object with user defined Get and Put subprograms.
  @ 2020-08-01 17:23  6%     ` Shark8
  0 siblings, 0 replies; 115+ results
From: Shark8 @ 2020-08-01 17:23 UTC (permalink / raw)


On Saturday, August 1, 2020 at 1:46:24 AM UTC-6, Blady wrote:
> Le 31/07/2020 à 20:19, Shark8 a écrit :
> > On Thursday, July 30, 2020 at 2:21:10 PM UTC-6, Blady wrote:
> >> Hello,
> >>
> >> Given a legacy code calling many Put_Line from Ada.Text_IO which works
> >> nice in a Terminal, I want to add a mode which sends these outputs to
> >> another process without changing the legacy code too much.
> >> And I want to keep the Terminal mode.
> >>
> >> Is there a way to create a File_Type object (from Ada.Text_IO) which
> >> would have user defined Get and Put subprograms instead of the
> >> predefined ones of the file system?
> > 
> > Kind of; I have a generic interface-package that I use for dealing with text-io and its permutations.
> > 
> > I just published it on github: https://github.com/OneWingedShark/EVIL/tree/master/src
> > It's part of what's intended to be a verified, general purpose library -- though I'm still teaching myself SPARK -- and so I've only published the file-interfacing utility portion.
> 
> Have you an example of how to use it?

with
--Ada.Wide_Wide_Text_IO.Text_Streams;
Ada.Text_IO.Text_Streams;

use
--Ada.Wide_Wide_Text_IO;
Ada.Text_IO;

Package Example is
   -- Bring in the Text-stream namespace.
   Use Ada.Text_IO.Text_Streams;
   
   -- Instantiate EVIL.Util.Files.
   Package Uniform_IO is New EVIL.Util.Files
      (
        Character	=> Character,
        String		=> String,
	File_Type	=> Ada.Text_IO.File_Type,
	File_Mode	=> Ada.Text_IO.File_Mode,
	Stream_Access	=> Ada.Text_IO.Text_Streams.Stream_Access
      );
  File : Uniform_IO.File:= Uniform_IO.Create( "Test.tmp", Ada.Text_IO.Out_File );
Begin

   Declare
      Test_String : Constant String := "-TESTING!!-";
   Begin
      String'Write( Test_File.Stream, Test_String );
   End;

End Example;

I don't have it implemented yet, but I plan on doing a "stream splitter" so you could say, use one stream to write to both the file and Standard_IO.

> >> Thus in my case, I will create a custom File_Type object My_Output with
> >> the user define Put which will send the lines to the other process and
> >> then I will call "Set_Output (My_Ouput);" before the legacy code.
> > 
> > It might be a better idea to have them as TASKs and in a single program, selecting and/or creating/executing the proper task ass needed. (If you have access to the legacy-program sources, you could wrap them or their interfaces in the TASK.)
> 
> Yes, I'll try in that way.

It'll probably save you some headache; I've found tasks really good at timed/cyclic events.

^ permalink raw reply	[relevance 6%]

* Re: How to transfer Class-Wide object to a Task ?
  2019-10-14 21:57  4%   ` Shark8
@ 2019-10-15  5:43  0%     ` William FRANCK
  0 siblings, 0 replies; 115+ results
From: William FRANCK @ 2019-10-15  5:43 UTC (permalink / raw)


Thank you Shark,
I'll give it a try too :-)

And send you all a more complete source code of my use case.

William


On 2019-10-14 21:57:57 +0000, Shark8 said:


> On Monday, October 14, 2019 at 2:21:50 PM UTC-6, William FRANCK wrote:
>> On 2019-10-14 19:41:53 +0000, William FRANCK said:
>> 
> Maybe something like this:
> 
>     procedure Example is
>         Package Types is
>             Subtype Params is Ada.Streams.Root_Stream_Type'Class;
>             Type Root   is abstract tagged null record;
>             Function Create (Parameters : not null access Params) 
> return Root is abstract;
> 
>             Type Circle is new Root with record
>                 Radius : Float;
>             end record;
> 
>             Type Square is new Root with record
>                 Side : Integer;
>             end record;
>         Private
> 
>             Function Create (Parameters : not null access Params) 
> return Square;
>             Function Create (Parameters : not null access Params) 
> return Circle;
>         End Types;
> 
> 
>         Use Types;
>         Package Class_Holder is new 
> Ada.Containers.Indefinite_Holders(Root'Class);
>         Task Type Producer( Stream : not null access 
> Ada.Streams.Root_Stream_Type'Class ) is
>             Entry Get( Object: out Class_Holder.Holder );
>         End Producer;
> 
>         Task body Producer is
>             Function MAKE is new Ada.Tags.Generic_Dispatching_Constructor(
>                T           => Types.Root,
>                Parameters  => Ada.Streams.Root_Stream_Type'Class,
>                Constructor => Types.Create
>               );
> 
>             Function To_Tag return Ada.Tags.Tag is
>             Begin
>                 Return Square'Tag;
> --                  (if    Ch = 'C' then Circle'Tag
> --                   elsif Ch = 'S' then Square'Tag
> --                   else raise Constraint_Error with "Tag '"&Ch&"' is 
> invalid.");
>             End;
> 
>         Begin
>             accept Get (Object : out Class_Holder.Holder) do
>                 Object:=
>                   Class_Holder.To_Holder( MAKE(To_Tag, Stream) );
>             end Get;
>         end Producer;
> 
>         Function Get(P : Producer) return Root'Class is
>             H : Class_Holder.Holder;
>         Begin
>             P.Get(H);
>             Return H.Element;
>         End Get;
> 
> 
> 
>         Package Body Types is
>             Function Create(Parameters : not null access Params) return 
> Square is
>             Begin
>                 Return (Side => 3);
>             End;
> 
>             Function Create(Parameters : not null access Params) return 
> Circle is
>             Begin
>                 Return (Radius => 2.2);
>             End;
>         End Types;
> 
>     begin
>         Ada.Text_IO.Put_Line( "START EXAMPLE." );
>         declare
>             I : Ada.Text_IO.File_Type renames Ada.Text_IO.Standard_Input;
>             P : Producer( Ada.Text_IO.Text_Streams.Stream(I) );
>             O : Root'Class := Get(P);
>         begin
>             Ada.Text_IO.Put_Line( "Tag: " & Ada.Tags.Expanded_Name(O'Tag) );
>         end;
>         Ada.Text_IO.Put_Line( "STOP EXAMPLE." );
>     end Example;


^ permalink raw reply	[relevance 0%]

* Re: How to transfer Class-Wide object to a Task ?
  @ 2019-10-14 21:57  4%   ` Shark8
  2019-10-15  5:43  0%     ` William FRANCK
  0 siblings, 1 reply; 115+ results
From: Shark8 @ 2019-10-14 21:57 UTC (permalink / raw)


On Monday, October 14, 2019 at 2:21:50 PM UTC-6, William FRANCK wrote:
> On 2019-10-14 19:41:53 +0000, William FRANCK said:
> 
Maybe something like this:

    procedure Example is
        Package Types is
            Subtype Params is Ada.Streams.Root_Stream_Type'Class;
            Type Root   is abstract tagged null record;
            Function Create (Parameters : not null access Params) return Root is abstract;
            
            Type Circle is new Root with record
                Radius : Float;
            end record;
            
            Type Square is new Root with record
                Side : Integer;
            end record;
        Private
            
            Function Create (Parameters : not null access Params) return Square;
            Function Create (Parameters : not null access Params) return Circle;
        End Types;
        
        
        Use Types;
        Package Class_Holder is new Ada.Containers.Indefinite_Holders(Root'Class);
        Task Type Producer( Stream : not null access Ada.Streams.Root_Stream_Type'Class ) is
            Entry Get( Object: out Class_Holder.Holder );
        End Producer;
        
        Task body Producer is
            Function MAKE is new Ada.Tags.Generic_Dispatching_Constructor(
               T           => Types.Root,
               Parameters  => Ada.Streams.Root_Stream_Type'Class,
               Constructor => Types.Create
              );

            Function To_Tag return Ada.Tags.Tag is
            Begin
                Return Square'Tag;
--                  (if    Ch = 'C' then Circle'Tag
--                   elsif Ch = 'S' then Square'Tag
--                   else raise Constraint_Error with "Tag '"&Ch&"' is invalid.");
            End;
            
        Begin
            accept Get (Object : out Class_Holder.Holder) do
                Object:=
                  Class_Holder.To_Holder( MAKE(To_Tag, Stream) );
            end Get;
        end Producer;
        
        Function Get(P : Producer) return Root'Class is
            H : Class_Holder.Holder;
        Begin
            P.Get(H);
            Return H.Element;
        End Get;
        
        
        
        Package Body Types is
            Function Create(Parameters : not null access Params) return Square is
            Begin
                Return (Side => 3);
            End;
            
            Function Create(Parameters : not null access Params) return Circle is
            Begin
                Return (Radius => 2.2);
            End;
        End Types;
        
    begin
        Ada.Text_IO.Put_Line( "START EXAMPLE." );
        declare
            I : Ada.Text_IO.File_Type renames Ada.Text_IO.Standard_Input;
            P : Producer( Ada.Text_IO.Text_Streams.Stream(I) );
            O : Root'Class := Get(P);
        begin
            Ada.Text_IO.Put_Line( "Tag: " & Ada.Tags.Expanded_Name(O'Tag) );
        end;
        Ada.Text_IO.Put_Line( "STOP EXAMPLE." );
    end Example;

^ permalink raw reply	[relevance 4%]

* Re: How to use read-only variables?
  @ 2015-01-04  2:55  4% ` Shark8
  0 siblings, 0 replies; 115+ results
From: Shark8 @ 2015-01-04  2:55 UTC (permalink / raw)


On 03-Jan-15 17:58, hreba wrote:
>
>     type R is abstract tagged limited record
>        n:    access constant Integer;
>     end record;
>
>     type Rv is new R with private;
>
> private
>
>     type Rv is new R with record
>        nv:    aliased Integer;
>     end record;

Try it like this:

With
Ada.Text_IO.Text_Streams;

procedure Test is


    package tmp is

       type R is abstract tagged limited record
          n:    access constant Integer;
       end record;

       type Rv is new R with private;

       function Make( I : Integer ) return Rv;
       function Val( Item : Rv ) return Integer;

    private

       type Rv is new R with record
          -- The following referenced "this" as a particular
          -- instance for the default value by using the type-name
          -- (and 'access) as a self-reference. we have to convert
          -- the de-reference to the parent class, and then access
          -- the appropriate value.
          nv:    aliased Integer:= R(Rv'access.all).n.all;
       end record;

       -- Note that we let the default values take care of ensuring
       -- that the values are properly in-sync.
       function Make( I : Integer ) return Rv is
         ( n => new Integer'(I), others => <> );

       function Val( Item : Rv ) return Integer is
         ( Item.nv );

    end tmp;

    use Ada.Text_IO;
begin

    declare
       K : tmp.Rv:= tmp.make( 129 );
    begin
       Put_Line( "K.n:" & K.Val'Img );
    end;

    Put_Line( "Done." );
end Test;


^ permalink raw reply	[relevance 4%]

* Re: Your wish list for Ada 202X
  @ 2014-04-25  7:31  4%               ` Dmitry A. Kazakov
  0 siblings, 0 replies; 115+ results
From: Dmitry A. Kazakov @ 2014-04-25  7:31 UTC (permalink / raw)


On Thu, 24 Apr 2014 20:19:22 -0600, Shark8 wrote:

> On 24-Apr-14 19:22, Randy Brukardt wrote:
>>
>> If one supplies user-defined 'Image, we'd pretty much have to support
>> user-defined 'Value as well. (You wouldn't have to use it, of course). It's
>> rare that only one way I/O is needed. Of course, this ups the effort for
>> composition a lot. I don't think I could support user-defined 'Image without
>> user-defined 'Value -- it seems asymetric to me.
> 
> At that point it sounds like we're getting into the Stream attributes -- 
> though it would be nice to have a secondary IO channel. The distinction 
> is, of course, that user-defined 'Image/'Value would be more geared 
> towards text rather than the generality of streams.

Interestingly that it is already here (A.12.2):

   package Ada.Text_IO.Text_Streams   

Though, there is a big BUT. Since stream attributes rather emulate multiple
dispatch [*] than do full MD, we cannot have your second channel which
would make

   Integer'Output (S, X);

formatting X differently when S is a text file (or a string stream) from
when S is a socket.

-----------
* Stream attributes semantically do cascaded dispatch, first on the I/O
item type, then on the stream type. This precludes stream-dependent
formatting.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


^ permalink raw reply	[relevance 4%]

* What's the cause of extra new line with Text_IO when program exit
@ 2013-08-16  1:02  5% Zhu, Qun-Ying
  0 siblings, 0 replies; 115+ results
From: Zhu, Qun-Ying @ 2013-08-16  1:02 UTC (permalink / raw)


Hi,

I have known this problem for quite some time, but did not really know 
why it behave like this.

These two programs:
======================================================================
-- hello.adb
with Ada.Text_IO; use Ada.Text_IO;

procedure Hello is
begin
     Put("Hello");
     Put(" ");
     Put("World!");
end Hello;

-- hello_stream.adb
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, they have different behavior.

For hello, you have:
# ./hello
Hello World!
#

While for hello_stream, you got:
# ./hello_stream
Hello World!#

If change the last Put to Put_Line for hello, you got the same result.
I would like to know why it is like that.

^ permalink raw reply	[relevance 5%]

* Interresting, possibly buggy behavior in GNAT generics w/ expression function.
@ 2013-03-28 17:34  3% Shark8
  0 siblings, 0 replies; 115+ results
From: Shark8 @ 2013-03-28 17:34 UTC (permalink / raw)


Lately I've been interested in perhaps getting Ada as a script-tag language, much like JavaScript. I figured I'd need a DOM library or somesuch and was looking into XMLAda (which, oddly fails compile on DOTNET-Gnat and seems oblivious to --target=JVM) so I was tinkering with it in native-code hoping to be able to get to a point where I could seek-out and alter attributes [for a node] on a DOM-Document and was surprised to find there's no functionality for altering attributes via XMLAda DOM-package (at least nothing obvious).

So I decided to play around and see about my own DOM-library (which I would rather not do, as there are several DOM-ish Ada packages about) and found this interesting tidbit: behavior changes when the parameter of image is changed from positive to natural. {Actually it only happens when Attribute_Values is instantiated with Integer[-type].}
----------------------------------------------------------------------------
With Ada.Containers.Indefinite_Vectors, Ada.Strings.Fixed;
Use  Ada.Containers;

Generic
    Attribute_Name : String;
    Type Attribute_Values is (<>);

    With Function Img(Value : Attribute_Values) Return String is Attribute_Values'Image;
    With Package Units is New Indefinite_Vectors(
		Index_Type => Positive,
		Element_Type => String );

    Attribute_Units : Units.Vector:= Units.Empty_Vector;

Package Generic_Attribute_Set is

    Type Attribute(Has_Units : Boolean:= Attribute_Units.Length /= 0) is record
	Value : Attribute_Values;
	case Has_Units is
	When True  => Unit : Positive;
	When False => Null;
	end case;
    end record;

    -- The 'Image Attribute, when applied to numeric types, leaves a leading
    -- space for non-negative numbers (for uniform columnuar display); this is
    -- undesirable for our use, so we wrap it in a call to trim.
    Function Image(Value : Attribute_Values) Return String is
	( Ada.Strings.Fixed.Trim(Img(Value), Side => Ada.Strings.Left) );
    
    -- Getting the string stored in the position for out units-vector is a
    -- simple index into the proper position in the vector containing the units.
    Function Image(Value : Positive) Return String is
      ( --if Value not in positive then "" else 
        Units.Constant_Reference( Attribute_Units, Value ) );
    
    Function To_String( Attr : Attribute ) Return String is
      ( Attribute_Name & "=""" & 
	 Image(Attr.Value) & (if Attr.Has_Units then Image(Attr.Unit) else "") &
	 '"'
      );
    
End Generic_Attribute_Set;
----------------------------------------------------------------------------
With
Generic_Attribute_Set,
Ada.Streams,
Ada.Text_IO.Text_Streams,
Ada.Containers.Indefinite_Vectors;

Procedure Test is
    Package Units is New Ada.Containers.Indefinite_Vectors(
		Index_Type => Positive,
		Element_Type => String );

    Use Units;
    Screen : Units.Vector:= Vector'("en" & "ex") & Vector'("px" & "%");
    
    Type J is (Alpha, Beta, 'K', Fred);
    
    Package Margins is new Generic_Attribute_Set(
	Attribute_Name   => "margin-left",
	Attribute_Values => Integer,
	Units            => Units,
	Attribute_Units  => Screen);
Begin
    Declare
      Use Margins;
      K : Attribute;
    begin
	K.Value:= 88; --J'Succ(Beta);
	K.Unit:= 4;
	Ada.Text_IO.Put_Line( To_String(K) );
    end;
End Test;
----------------------------------------------------------------------------

As I understand it this shouldn't *ever* happen because in the generic there's supposed to be no knowledge of what the parameters are actually instantiated with.


^ permalink raw reply	[relevance 3%]

* Re: reading from a pipe
  @ 2013-02-27 19:22  7% ` Eryndlia Mavourneen
  0 siblings, 0 replies; 115+ results
From: Eryndlia Mavourneen @ 2013-02-27 19:22 UTC (permalink / raw)


On Wednesday, February 27, 2013 11:36:32 AM UTC-6, milouz wrote:
> Hi,
> 
> 
> 
> I'd like to know how to read some bytes from a pipe or some other non-regular file such as device. I had a look at streams_io, direct_io, etc. but was not able to code something working.
> 
> 
> 
> How do we do that in Ada ?

The following is a partial solution to the question, but gives the general idea:

-------------------------------

   with Ada.Text_IO, Ada.Text_IO.Text_Streams;
   use  Ada.Text_IO, Ada.Text_IO.Text_Streams;
   procedure Write_It is
      type My_Record_Type is ...;
      The_Record : My_Record_Type;
      Cmd_Stream : Text_Streams.Stream_Access := Stream (Standard_Output);
   begin
      My_Record_Type'Write (Cmd_Stream, The_Record);
   end Write_It;

--------------------------------

   with Ada.Text_IO, Ada.Text_IO.Text_Streams;
   use  Ada.Text_IO, Ada.Text_IO.Text_Streams;
   procedure Read_It is
      type My_Record_Type is ...;
      The_Record : My_Record_Type;
      Cmd_Stream : Text_Streams.Stream_Access := Stream (Standard_Input);
   begin
      My_Record_Type'Read (Cmd_Stream, The_Record);
   end Read_It;

--------------------------------

Build as two processes and invoke within .exe directory as:

   $ ./write_it | ./read_it

--------------------------------

  -- Eryndlia



^ permalink raw reply	[relevance 7%]

* Re: Algorithms Homework Help?!?!
  @ 2013-01-15 23:43  4% ` Shark8
  0 siblings, 0 replies; 115+ results
From: Shark8 @ 2013-01-15 23:43 UTC (permalink / raw)


Um, there's nothing there suggestive of a binary-search, or ANY search.
But here's an example of how to do the groupings.

Pragma Ada_2012;

With
Ada.Text_IO,
Ada.Text_IO.Text_Streams;

Procedure Test is

    Type Color is ( Red, Blue, Green, Yellow, Brown );

    Type MM_Array is Array(Color Range <>) of Natural;
    
    --------------------------
    -- Forward Declarations --
    --------------------------
    
    Function Maximum( Candy : MM_Array ) Return Natural
      with Pre => Candy'Length in Positive;
    
    Function Group( Group_Size : Positive; Candy : MM_Array ) Return Natural
      with Pre => Candy'Length in Positive AND Maximum(Candy) >= Group_Size;
    

    -----------------------
    --  Function Bodies  --
    -----------------------
    
    Function Maximum( Candy : MM_Array ) Return Natural is
    begin
	Return Result : Natural := Natural'First do
	    For Value of Candy loop
		Result:= Natural'Max( Result, Value );
	    End loop;
	End return;
    end Maximum;
    
    Function Group( Group_Size : Positive; Candy : MM_Array ) Return Natural is
    begin
	Return Result : Natural := 0 do
	    For Value of Candy loop
		Result:= Result + Value / Group_Size;
	    End loop;
	End return;
    end Group;
    
    Candies : MM_Array := (Red => 11, Blue => 9, Green => 5);
Begin
    Ada.Text_IO.New_Line;
    Ada.Text_IO.Put_Line( "Max:  " & Maximum(Candies)'Img  );
    Ada.Text_IO.Put_Line( "Group:" & Group(8, Candies)'Img  );
End Test;



^ permalink raw reply	[relevance 4%]

* Re: Reading the while standard input into a String
  2011-06-05 16:20  6% Reading the while standard input into a String Natasha Kerensikova
@ 2011-06-06  1:49  6% ` robin
  0 siblings, 0 replies; 115+ results
From: robin @ 2011-06-06  1:49 UTC (permalink / raw)


"Natasha Kerensikova" <lithiumcat@gmail.com> wrote in message news:slrniunb6n.i18.lithiumcat@sigil.instinctive.eu...
| Hello,
|
| I have encountered what was a very easily solved problem in C: dump the
| whole contents of the standard input into some place in memory, in order
| to process it afterwards.

It's also trivial in PL/I:

do forever;
    allocate line;
    get edit (line) (L);
end;

or read each line into an array element or whatever.

| I was quite unhappy with the preprocessing performed by Ada.Text_IO, so
| I went on using the text stream interface. However I still read
| character by character into a temporary buffer, and it feels ugly. Here
| is the code:
|
| with Ada.Strings.Unbounded;
| with Ada.Text_IO.Text_Streams;
|
|   Source : Ada.Text_IO.Text_Streams.Stream_Access
|     := Ada.Text_IO.Text_Streams.Stream (Ada.Text_IO.Standard_Input);
|
|   procedure Read_Chunk (To : out String; Last : out Natural) is
|   begin
|      Last := To'First - 1;
|      for J in To'Range loop
|         Character'Read (Source, To (J));
|         Last := J;
|      end loop;
|   exception
|      when Ada.Text_IO.End_Error => Null;
|   end Read_Chunk;
|
|
|   procedure The_Program is
|      -- some tuff
|      Input : Ada.Strings.Unbounded.Unbounded_String;
|   begin
|      declare
|         Chunk : String (1 .. 256);
|         Last : Natural;
|      begin
|         loop
|            Read_Chunk (Chunk, Last);
|            Ada.Strings.Unbounded.Append (Input, Chunk (1 .. Last));
|            exit when Last < Chunk'Last;
|         end loop;
|      end;
|
|      -- Process Input or To_String (Input);
|   end The_Program;
|
| Is there a better/smarter/less ugly way to achieve the same result? 





^ permalink raw reply	[relevance 6%]

* Reading the while standard input into a String
@ 2011-06-05 16:20  6% Natasha Kerensikova
  2011-06-06  1:49  6% ` robin
  0 siblings, 1 reply; 115+ results
From: Natasha Kerensikova @ 2011-06-05 16:20 UTC (permalink / raw)


Hello,

I have encountered what was a very easily solved problem in C: dump the
whole contents of the standard input into some place in memory, in order
to process it afterwards.

I was quite unhappy with the preprocessing performed by Ada.Text_IO, so
I went on using the text stream interface. However I still read
character by character into a temporary buffer, and it feels ugly. Here
is the code:

with Ada.Strings.Unbounded;
with Ada.Text_IO.Text_Streams;

   Source : Ada.Text_IO.Text_Streams.Stream_Access
     := Ada.Text_IO.Text_Streams.Stream (Ada.Text_IO.Standard_Input);

   procedure Read_Chunk (To : out String; Last : out Natural) is
   begin
      Last := To'First - 1;
      for J in To'Range loop
         Character'Read (Source, To (J));
         Last := J;
      end loop;
   exception
      when Ada.Text_IO.End_Error => Null;
   end Read_Chunk;


   procedure The_Program is
      -- some tuff
      Input : Ada.Strings.Unbounded.Unbounded_String;
   begin
      declare
         Chunk : String (1 .. 256);
         Last : Natural;
      begin
         loop
            Read_Chunk (Chunk, Last);
            Ada.Strings.Unbounded.Append (Input, Chunk (1 .. Last));
            exit when Last < Chunk'Last;
         end loop;
      end;

      -- Process Input or To_String (Input);
   end The_Program;

Is there a better/smarter/less ugly way to achieve the same result?


Thanks for your help,
Natasha



^ permalink raw reply	[relevance 6%]

* Re: Ann: Little tutorial about streams
  @ 2011-02-28 20:32  4% ` Ludovic Brenta
  0 siblings, 0 replies; 115+ results
From: Ludovic Brenta @ 2011-02-28 20:32 UTC (permalink / raw)


mockturtle writes:
> Dear.all,

> remembering my initial difficulties with streams (I self-taught Ada,
> using few tutorials and lots of experiments before landing to the RM),
> I decided to write a page (my first one, so be patient :-) of the
> Wikibook with a little stream tutorial
>
> http://en.wikibooks.org/w/index.php?title=Ada_Programming/Input_Output/Stream_Tutorial
>
> As said in the page, the goal is to give to the reader an intuitive
> idea about how streams work so, in order to not hide the forest with
> too many leaves, some of the finest details have been omitted.  A
> subpage of the above page has a fairly complex example that is not
> complete yet, but I plan to complete it soon.
>
> The page is not linked yet with the book body.  I was thinking to add
> a link to it in the "Input Output" page as soon as the subpage with
> the example is in a good state.
>
> Any feedback [especially positive one :-) :-) :-) :-)] is appreciated.

Your page is great.  How's that for positive criticism :)

I've made a couple edits which you are, of course, free to revert.  I
(think I) have generally improved the style of the prose but not changed
the basic structure of the tutorial.

Now I have specific suggestions for further improvement:

* Between the sections "Abstract streams" and "Serialization functions",
  it would be nice to have a section on "Predefined concrete streams"
  discussing, in particular Ada.Text_IO.Text_Stream, so that beginners
  can start writing to the console using streams.

* In the section about Ada.Text_IO.Text_Streams, explain that this is
  much faster than Ada.Text_IO and why (hint: ARM A.10.4, A.12.2(7))

* Your first example of a serialization function, procedure
  Example.Print, seems too complicated.  But that may be on purpose, so
  I have not changed it.  Here is a simpler implementation:

  package body Example is
     procedure Print (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
                      Item   : in  Int) 
     is
        -- Convert Item to String (with no trailing space)
        Value  : String := Trim(Int'Image(Item), Left);
        
        -- Convert Value'Length to String (with no trailing space)
        Len    : String := Trim(Integer'Image(Value'Length), Left);
     begin 
        String'Write (Stream, Len & 'i' & Value);
     end Print;
  end Example;

Thank you for taking the initiative writing this nice tutorial.  I think
it really helps lower the bar for novices.

-- 
Ludovic Brenta.



^ permalink raw reply	[relevance 4%]

* Re: How do I write directly to a memory address?
  @ 2011-02-08 20:52  4%                           ` Shark8
  0 siblings, 0 replies; 115+ results
From: Shark8 @ 2011-02-08 20:52 UTC (permalink / raw)


On Feb 8, 1:27 pm, Hyman Rosen <hyro...@mail.com> wrote:
> On 2/8/2011 3:11 PM, Shark8 wrote:> No, that's not it. What is 'it' is that the C programmers  treated
>
>  > Ada as if it were C and the result was, as expected, bad Ada.
>
> It is my understanding that Ada proponents believe that
> using Ada results in better programs than using C.

First off, I purposely did not say (or even imply) that using
Ada "automagically" makes one a better programmer, or
that it makes the programs themselves better.

Let me put it a different way: pneumatic tires are a pretty
good development; they can absorb shock to some
degree as well as allowing a measure of protection
from damage to the wheels {rim/hub} and in so doing
help minimize the cost of when you eventually run into
some road hazard.... but there is NOTHING preventing
you from going out and letting all the air out of your tires
and experiencing the same wheel-cost as the old
covered-wagons, no?

IOW, Ada could have all the most wonderful features and
helps possible but if one never uses them then they do
no good whatsoever to that person.

> But when presented with a program written in Ada that is not
> demonstrably better, that program is removed from the set
> of Ada programs under consideration by virtue of having
> been written by "C people". That is precisely the "no true
> Scotsman" fallacy.

Again, I was not dismissing any program in itself, or even
class of programs, and therefore the "No True Scotsman"
fallacy CANNOT apply to what I presented.

What is interesting, however, is some of the replies to
shown examples of Ada I've written to those well-versed
in C/C++ but unfamiliar with Ada. If you're interested I
have a LISP interpreter* I would otherwise post to show
some of the the "wows" I've gotten; and I'm not doing
anything too spectacular things like having my
overwriting the S_Expression type's 'read and 'write
attributes so I could do something like:

   Ada.Text_IO.Put_Line( "Begin Run:" );
   Open( Input, In_File, Name => "Temp.Txt" );
   Declare
      In_Stream	: Access Ada.Streams.Root_Stream_Type'Class:=
	Ada.Text_IO.Text_Streams.Stream( Input );
      Use LISP;
   Begin
      S_Expression'Read( In_Stream, S );
      -- Here's where EVAL would go.
      S_Expression'Write( Out_Stream, S );
   End;
   Ada.Text_IO.Put_Line( "" );
   Ada.Text_IO.Put_Line( "End Run." );
   Close( Input );

*Not working, I still have to implement the atomic-level
functions, the special-forms cases {like 'if'}, and the
Eval function.

> > The reverse is less true, I think. If you give an Ada  Programmer
>
>  > a "must do" in C, AND he applied the theory/ideology of Ada
>  > {specifically contract enforcement & rejection/culling of bad
>  > values}, then the result would NOT be "bad C"... would it?
>
> In other words, training in a certain style of programming leads
> to better programs. Sure, that's plausible.

More than plausible. I've had professors able to spot that I'd been
'trained' in Pascal from reading my C-code. "Trained" here actually
being self-taught with little more than the compiler and the user's
manual for the compiler.



^ permalink raw reply	[relevance 4%]

* Re: problems with interfacing c
  2011-01-28  0:39  0%   ` Stoik
@ 2011-01-28  9:41  5%     ` Ludovic Brenta
  0 siblings, 0 replies; 115+ results
From: Ludovic Brenta @ 2011-01-28  9:41 UTC (permalink / raw)


Staszek Goldstein wrote on comp.lang.ada:
> I am sending a solution to a problem to a site managing programming contests, and
> the stdin is in fact redirected to some text file with data. I do not know how
> big the data file will be, I know only the upper limit. Quick reading of the data is the
> key to success, and the two lines of C work very well for the purpose. I have not
> tried your solution, is it not going to cause constraint_error when it meets the end of the
> file?

If you really read from Standard_Input, there is no upper limit to the
size of the file, so you should not depend on one. i.e. your program
should work if you say:

$ yes | my_program

The proper way to read a potentially infinite amount of data from
Standard_Input is to read one character at a time, buffer the input
for processing, and discard the buffer from time to time so your
program runs in constant memory. The points in time where you discard
the buffer depend on the algorithm.

Like Dmitry, I strongly suggest you use Ada.Streams, not Ada.Text_IO,
because the latter is much slower (it does a lot of unnecessary
bookkeeping behind the scenes).

Here is a small example where I process the input buffer whenever it
is full and then discard it. I also do that when I reach the end of
the input stream. Note that I have not compiled this example, so it
may contain (intentional :)) bugs.

with Ada.IO_Exceptions;
with Ada.Text_IO;
with Ada.Strings.Bounded;
procedure My_Program is
   Current_Input : constant Ada.Text_IO.Text_Streams.Stream_Access :=
     Ada.Text_IO.Text_Streams.Stream (Ada.Text_IO.Current_Input);
   package Buffers is new Ada.Strings.Bounded.Generic_Bounded_Length
(Max => 100_000);

   procedure Process_And_Discard (Buffer : in out
Buffers.Bounded_String) is
   begin
      -- actual processing left as an exercise for the reader :)
      Buffers.Delete (Source => Buffer, From => 1, Through =>
Buffers.Max_Length);
   end Process_And_Discard;

   Buffer : Buffers.Bounded_String;
begin
   loop
      declare
          C : Character;
      begin
          Character'Read (Current_Input, C);
          if Buffers.Length (Buffer) = Buffers.Max_Length then --
buffer is full
             Process_And_Discard (Buffer);
          end if;
          Buffers.Append (Source => Buffer, New_Item => C);
      exception
          when Ada.IO_Exceptions.End_Error => -- end of stream reached
             Process_And_Discard (Buffer); -- process whatever we read
last
             exit;
      end;
   end loop;
end My_Program;

> The other question is - how to use the C bindings properly in such a case?

Don't.

--
Ludovic Brenta.



^ permalink raw reply	[relevance 5%]

* Re: problems with interfacing c
  2011-01-20 20:56  5% ` Dmitry A. Kazakov
  2011-01-20 21:31  0%   ` Yannick Duchêne (Hibou57)
@ 2011-01-28  0:39  0%   ` Stoik
  2011-01-28  9:41  5%     ` Ludovic Brenta
  1 sibling, 1 reply; 115+ results
From: Stoik @ 2011-01-28  0:39 UTC (permalink / raw)


On Jan 20, 9:56 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> On Thu, 20 Jan 2011 12:21:08 -0800 (PST), Stoik wrote:
> > I need your help in finding a proper Ada code to simulate the behaviour of the
> > following lines in C:
> > char *bufor = (char*)malloc(100000);
> > fread(bufor, 1, 100000, stdin);
>
> That depends on what are going to achieve. Translating the above literally:
>
> [ with Ada.Text_IO.Text_Streams;
>   use Ada.Text_IO, Ada.Text_IO.Text_Streams; ]
>
>    Buffer : String (1..100_000);
> begin
>    String'Read (Stream (Standard_Input), Buffer);
>
> [ Which certainly nobody would do, but you didn't provide any information
> about the actual problem. ]
>
> > I need to do it from inside of the Ada code. I tried to import fread, use the package
> > interfaces.c.strings etc, but in the end I always get the same message:
> > raised PROGRAM_ERROR : EXCEPTION_ACCESS_VIOLATION
> > Any ideas?
>
> You are using C bindings improperly and you need not C bindings in order to
> read the standard input.
>
> --
> Regards,
> Dmitry A. Kazakovhttp://www.dmitry-kazakov.de

Thanks for your suggestions and comments. The point is that I am
sending
a solution to a problem to a site managing programming contests, and
the stdin
is in fact redirected to some text file with data. I do not know how
big the data file
will be, I know only the upper limit. Quick reading of the data is the
key to success,
and the two lines of C work very well for the purpose. I have not
tried your solution,
is it not going to cause constraint_error when it meets the end of the
file?
The other question is - how to use the C bindings properly in such a
case?

Regards,
Staszek Goldstein



^ permalink raw reply	[relevance 0%]

* Re: problems with interfacing c
  2011-01-20 21:31  0%   ` Yannick Duchêne (Hibou57)
@ 2011-01-20 23:03  0%     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 115+ results
From: Dmitry A. Kazakov @ 2011-01-20 23:03 UTC (permalink / raw)


On Thu, 20 Jan 2011 22:31:47 +0100, Yannick Duch�ne (Hibou57) wrote:

> Le Thu, 20 Jan 2011 21:56:52 +0100, Dmitry A. Kazakov  
> <mailbox@dmitry-kazakov.de> a �crit:
> 
>> On Thu, 20 Jan 2011 12:21:08 -0800 (PST), Stoik wrote:
>>
>>> I need your help in finding a proper Ada code to simulate the behaviour  
>>> of the
>>> following lines in C:
>>> char *bufor = (char*)malloc(100000);
>>> fread(bufor, 1, 100000, stdin);
>>
>> That depends on what are going to achieve. Translating the above  
>> literally:
>>
>> [ with Ada.Text_IO.Text_Streams;
>>   use Ada.Text_IO, Ada.Text_IO.Text_Streams; ]
>>
>>
>>    Buffer : String (1..100_000);
>> begin
>>    String'Read (Stream (Standard_Input), Buffer);
>>
>> [ Which certainly nobody would do, but you didn't provide any information
>> about the actual problem. ]
> 
> Some body do, for some kind of raw IO. Just that this may be more oftenly  
> something like
>     Character'Read (Standard_Input), C);

That the point, when reading characters that suggests some character stream
oriented protocol. Dealing with such protocols one would never read 100K in
one chunk. Because if the client does something wrong that would deadlock
forever.

> in a loop instead (always wondered if there is a more efficient way, I do  
> not know one), because most of time the buffer size may vary in 1..n (I  
> suppose it may vary for the OP matter too).

The best way is full duplex I/O. You should always be prepared to read at
least one character, so that the client is never blocked when it writes
anything out.

P.S. It would be nice if Ada standard library provided asynchronous
in-place I/O facilities (like overlapped I/O). Ada's protected objects are
perfect candidates for this abstraction (as it was done with interrupts
handlers). But I doubt that would ever happen.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[relevance 0%]

* Re: problems with interfacing c
  2011-01-20 20:56  5% ` Dmitry A. Kazakov
@ 2011-01-20 21:31  0%   ` Yannick Duchêne (Hibou57)
  2011-01-20 23:03  0%     ` Dmitry A. Kazakov
  2011-01-28  0:39  0%   ` Stoik
  1 sibling, 1 reply; 115+ results
From: Yannick Duchêne (Hibou57) @ 2011-01-20 21:31 UTC (permalink / raw)


Le Thu, 20 Jan 2011 21:56:52 +0100, Dmitry A. Kazakov  
<mailbox@dmitry-kazakov.de> a écrit:

> On Thu, 20 Jan 2011 12:21:08 -0800 (PST), Stoik wrote:
>
>> I need your help in finding a proper Ada code to simulate the behaviour  
>> of the
>> following lines in C:
>> char *bufor = (char*)malloc(100000);
>> fread(bufor, 1, 100000, stdin);
>
> That depends on what are going to achieve. Translating the above  
> literally:
>
> [ with Ada.Text_IO.Text_Streams;
>   use Ada.Text_IO, Ada.Text_IO.Text_Streams; ]
>
>
>    Buffer : String (1..100_000);
> begin
>    String'Read (Stream (Standard_Input), Buffer);
>
> [ Which certainly nobody would do, but you didn't provide any information
> about the actual problem. ]

Some body do, for some kind of raw IO. Just that this may be more oftenly  
something like
    Character'Read (Standard_Input), C);
in a loop instead (always wondered if there is a more efficient way, I do  
not know one), because most of time the buffer size may vary in 1..n (I  
suppose it may vary for the OP matter too).

>> I need to do it from inside of the Ada code. I tried to import fread,  
>> use the package
>> interfaces.c.strings etc, but in the end I always get the same message:
>> raised PROGRAM_ERROR : EXCEPTION_ACCESS_VIOLATION
>> Any ideas?
>
> You are using C bindings improperly and you need not C bindings in order  
> to
> read the standard input.
I feel the same. Strange to use C interface for an fread (however, for  
file mapping into memory or other specialized access, this would OK).


-- 
Si les chats miaulent et font autant de vocalises bizarres, c’est pas pour  
les chiens.

“I am fluent in ASCII” [Warren 2010]



^ permalink raw reply	[relevance 0%]

* Re: problems with interfacing c
  @ 2011-01-20 20:56  5% ` Dmitry A. Kazakov
  2011-01-20 21:31  0%   ` Yannick Duchêne (Hibou57)
  2011-01-28  0:39  0%   ` Stoik
  0 siblings, 2 replies; 115+ results
From: Dmitry A. Kazakov @ 2011-01-20 20:56 UTC (permalink / raw)


On Thu, 20 Jan 2011 12:21:08 -0800 (PST), Stoik wrote:

> I need your help in finding a proper Ada code to simulate the behaviour of the
> following lines in C:
> char *bufor = (char*)malloc(100000);
> fread(bufor, 1, 100000, stdin);

That depends on what are going to achieve. Translating the above literally:

[ with Ada.Text_IO.Text_Streams;
  use Ada.Text_IO, Ada.Text_IO.Text_Streams; ]


   Buffer : String (1..100_000);
begin
   String'Read (Stream (Standard_Input), Buffer);

[ Which certainly nobody would do, but you didn't provide any information
about the actual problem. ]

> I need to do it from inside of the Ada code. I tried to import fread, use the package
> interfaces.c.strings etc, but in the end I always get the same message:
> raised PROGRAM_ERROR : EXCEPTION_ACCESS_VIOLATION
> Any ideas?

You are using C bindings improperly and you need not C bindings in order to
read the standard input.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[relevance 5%]

* Newbie-ish question about generics and Ada.Streams
@ 2010-12-27 17:23  4% Brian Drummond
  0 siblings, 0 replies; 115+ results
From: Brian Drummond @ 2010-12-27 17:23 UTC (permalink / raw)


Season's greetings!

In between rounds of turkey, I have been trying to learn a bit more about generics, though it still
feels as if I am pushing on a rope.

In particular, I have been trying to use generic procedures for stream access for a large set of
similar data types (enumerations) where I want a specific representation in the output file. This
means attaching the Read and Write procedures - instantiated generics - to the types using
representation clauses.

Which (as I understand it) has to be done before the types are frozen....

I hope the example below is clear...

Comments welcome, but the specific points I am unhappy with are:

(1) The incomplete procedure declarations, with deferred implementation. 
I suspect there is no way around this, as long as I need to freeze the type 
before the procedure body.

(2) The second generic parameter - the named array type. It feels like I am missing 
something obvious here, and there ought to be a way to avoid adding this clutter.

(3) Instantiating the generic under a different name, and renaming to match the incomplete
declaration. Is this (a) necessary, (b) Gnat-specific, or (c) something stupid on my part?

Thanks,
- Brian


with Ada.Text_Io.Text_Streams;
with Ada.Streams;

procedure try_generics is

-- We have multiple enumerations...
type shape is (circle, square);
type colour is (red, green, blue);

-- and we want to control how they are written to a stream
procedure colour_write (Stream : not null access Ada.Streams.Root_Stream_Type'Class; 
			what : in colour);
procedure shape_write (Stream : not null access Ada.Streams.Root_Stream_Type'Class; 
			what : in shape);
for colour'write use colour_write;
for shape'write use shape_write;

-- In this example, we use an array of strings indexed by the enumerations.
-- shapes : constant array(shape) of string(1 .. 7) := ("circle ", "square ");
-- but... generics (below) seem picky about using named vs anonymous subtypes
subtype name is string(1 .. 7);
type shape_names is array(shape) of name;
type colour_names is array(colour) of name;
-- appears to freeze the types; write procedures or representation clauses after this are "too late"
shapes : constant shape_names := ("circle ", "square ");
colours : constant colour_names := ("red    ", "green  ", "blue   ");

-- Example body of a write procedure...
--procedure colour_write (Stream : not null access Ada.Streams.Root_Stream_Type'Class; 
			what : in colour) is
--begin
--   String'write(Stream, colours(what));
--end colour_write;

-- That would get repetitive, so let's use a generic...
   generic
      type Item_Type is (<>);
      type Item_Names(<>) is array(Item_Type) of name;
      -- Feels as if the Item_Names type declaration ought to be unnecessary...
      Names : Item_Names;
   procedure Enum_Write(Stream : not null access Ada.Streams.Root_Stream_Type'Class; 
			Item : in Item_Type);

   procedure Enum_Write(Stream : not null access Ada.Streams.Root_Stream_Type'Class; 
			Item : in Item_Type) is
   begin
      String'Write(Stream, Names(Item));
   end Enum_Write;

-- And instantiate it. First attempt...
--procedure shape_write is new Enum_Write(Item_Type => shape, 
			Item_Names => shape_names, Names => shapes);
--try_generics.adb:12:01: missing body for "shape_write"
--try_generics.adb:43:11: instantiation cannot provide body for "shape_write"

-- So instantiate it under a different name, and rename it...
procedure shape_writer is new Enum_Write(Item_Type => shape, 
			Item_Names => shape_names, Names => shapes);
procedure shape_write(Stream : not null access Ada.Streams.Root_Stream_Type'Class; 
			what : in shape) renames shape_writer;
procedure colour_writer is new Enum_Write(Item_Type => colour, 
			Item_Names => colour_names, Names =>colours);
procedure colour_write (Stream : not null access Ada.Streams.Root_Stream_Type'Class; 
			what : in colour) renames colour_writer;
-- That duplication is ugly ... can this be simplified?

-- Now we can use the enumerations in a toy block
type toy_block is record
   my_colour : colour;
   my_shape : shape;
end record;

-- and output the block to a stream
my_block : constant toy_block := (my_colour => red, my_shape => square);
Stdout : Ada.Text_Io.Text_Streams.Stream_Access :=
Ada.Text_Io.Text_Streams.Stream(Ada.Text_Io.Current_Output);
begin
   toy_block'write(Stdout, my_block); 
end try_generics;





^ permalink raw reply	[relevance 4%]

* Re: for S'Image use Func??
  @ 2010-05-10 22:39  5%                             ` Yannick Duchêne (Hibou57)
  0 siblings, 0 replies; 115+ results
From: Yannick Duchêne (Hibou57) @ 2010-05-10 22:39 UTC (permalink / raw)


Le Mon, 10 May 2010 22:56:11 +0200, Maciej Sobczak  
<see.my.homepage@gmail.com> a écrit:
> Coming back to I/O - what I miss in Ada is the equivalent of fread in
> C - that is, an operation that reads *up to* the given number of
> bytes. Or maybe there is something that I didn't notice?
It's there : look at [ARM 2005 13.13.1] which defines the package  
Ada.Streams, which in turn contains the following :

    type Root_Stream_Type is abstract tagged limited private;
    ...
    type Stream_Element is mod implementation-defined;
    ...

    procedure Read
      (Stream : in out Root_Stream_Type;
       Item   : out Stream_Element_Array;
       Last   : out Stream_Element_Offset)
       is abstract;

    procedure Write
      (Stream : in out Root_Stream_Type;
       Item   : in Stream_Element_Array)
       is abstract;


So, these are abstract. Now the question is : “where are the concret  
implementation” ? The answer is “in derived types”.

Here is one, as a quick and one of the most useful example (see [ARM 2005  
1.12.2]) :


    with Ada.Streams;
    package Ada.Text_IO.Text_Streams is
       type Stream_Access is access all Streams.Root_Stream_Type'Class;
       function Stream (File : in File_Type) return Stream_Access;
    end Ada.Text_IO.Text_Streams;

This re-define Stream_Access (why this access type is redefined here, is  
another story previously discussed with an answer from Randy), and define  
a function which returns a Stream_Access from a File_Type. This File_Type  
is the one defined in the parent package, that is, Ada.Text_IO.

In Ada.Text_IO, you have (see [ARM 2005 A.10.1]) some other interesting  
definitions, which will close the list of required stuff :


    function Standard_Input  return File_Access;
    function Standard_Output return File_Access;
    function Standard_Error  return File_Access;

Summary : in Ada.Text_IO, you have Standard_XXXX or other File_Type. You  
can use this (using an XXX.all to get a File_Type from a File_Access) as  
an argument to the Ada.Text_IO.Text_Streams.Stream function, which will  
return you a Stream_Access which will dispatch to an implementation of   
Ada.Streams.Read and Ada.Streams.Write.

Well, to be honest, this is not exactly the same as with C, as  
Ada.Streams.Stream_Element is implementation defined (which is good,  
because this is indeed platform dependent), so you will need an Assert  
pragma somewhere is your application, which ensures  
Ada.Streams.Stream_Element is 8 bits or at least 8 bits (this is, in most  
of case), and then convert from Ada.Streams.Stream_Element to your  
Byte_Type or anything your application defined as such.

Sorry for being long, I just wanted to give all the details. However, this  
is not so much complicated as all those explanations seems to suggest.

-- 
No-no, this isn't an oops ...or I hope (TM) - Don't blame me... I'm just  
not lucky



^ permalink raw reply	[relevance 5%]

* Re: Why is not Stream_Access defined Ada.Streams ?
  2010-05-07  1:02  5% Why is not Stream_Access defined Ada.Streams ? Yannick Duchêne (Hibou57)
@ 2010-05-07  2:24  0% ` Randy Brukardt
  0 siblings, 0 replies; 115+ results
From: Randy Brukardt @ 2010-05-07  2:24 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 950 bytes --]

"Yannick Duch�ne (Hibou57)" <yannick_duchene@yahoo.fr> wrote in message 
news:op.vca852lexmjfy8@garhos...
> Hi all and Hi others as well,
>
> My dirty stuff of the day : why is Stream_Access not defined once a time 
> in Ada.Streams and is instead defined elsewhere multiple times, like in 
> Ada.Streams.Stream_IO, Ada.Text_IO.Text_Streams, 
> Ada.Wide_Text_IO.Text_Streams and Ada.Wide_Wide_Text_IO.Text_Streams ?
>
> Isn't it funny design ?

Ada 95 didn't have anonymous access returns, so a named type had to be 
defined. I suspect that there was no intent that it be used for anything 
other than defining the result of these functions -- and there was no intent 
that that result be stored: just directly dereferenced and passed to a 
stream attribute.

If we were writing it today, I'm pretty sure that no named type would be 
used at all. But making a change like that now would be incompatible.

                                Randy.





^ permalink raw reply	[relevance 0%]

* Why is not Stream_Access defined Ada.Streams ?
@ 2010-05-07  1:02  5% Yannick Duchêne (Hibou57)
  2010-05-07  2:24  0% ` Randy Brukardt
  0 siblings, 1 reply; 115+ results
From: Yannick Duchêne (Hibou57) @ 2010-05-07  1:02 UTC (permalink / raw)


Hi all and Hi others as well,

My dirty stuff of the day : why is Stream_Access not defined once a time  
in Ada.Streams and is instead defined elsewhere multiple times, like in  
Ada.Streams.Stream_IO, Ada.Text_IO.Text_Streams,  
Ada.Wide_Text_IO.Text_Streams and Ada.Wide_Wide_Text_IO.Text_Streams ?

Isn't it funny design ?

-- 
No-no, this isn't an oops ...or I hope (TM) - Don't blame me... I'm just  
not lucky



^ permalink raw reply	[relevance 5%]

* Re: Preferred way to do binray I/O on standard input/output stream
  2009-10-27  2:36  0%       ` Hibou57 (Yannick Duchêne)
@ 2009-10-27 16:13  5%         ` John B. Matthews
  0 siblings, 0 replies; 115+ results
From: John B. Matthews @ 2009-10-27 16:13 UTC (permalink / raw)


In article 
<a558f6b4-8f4c-459d-8706-4eb8125dae1e@w19g2000yqk.googlegroups.com>,
 Hibou57 (Yannick Duchêne) <yannick_duchene@yahoo.fr> wrote:

> The trouble with this, is that this force a look-ahead : an item
> must be read to know if an item is available, and this can lead
> into numerous logical traps (I prefer to keep distinct the action
> of reading and testing availability of data).

Ah, I see your point. I recall this problem going back to the days of 
UCSD Pascal, which distinguished between interactive and text type files 
for this very reason. My use is to allow command line utilities to read 
from standard input if no file name is supplied. For me, the data stream  
invariably arrives via redirection or a pipe, so the problem does not 
arise. For interactive programming, I typically use GtkAda.

This variation of Copy makes it easier to see what's happening. 
Prefacing the loop with the End_Of_File predicate exposes the problem 
for files with a terminal LF. If running interactively, control-D exits:

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Text_IO.Text_Streams;

procedure Copy is
   Stream_Ptr : Text_Streams.Stream_Access;
   C : Character;

   function Hex(C : Character) return String is
      H : constant String := "0123456789ABCDEF";
      B : Natural := Character'Pos(C);
      S : String(1 .. 4);
   begin
      S(1) := '[';
      S(2) := H(B / 16 + 1);
      S(3) := H(B mod 16 + 1);
      S(4) := ']';
      return S;
   end Hex;

begin
   Stream_Ptr := Text_Streams.Stream(Current_Input);
-- while not End_Of_File loop
   loop
      Character'Read(Stream_Ptr, C);
      Put(Hex(C));
   end loop;
exception
   when End_Error => null;
end Copy;

-- 
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>



^ permalink raw reply	[relevance 5%]

* Re: Preferred way to do binray I/O on standard input/output stream
  2009-10-27  1:14  6%     ` John B. Matthews
@ 2009-10-27  2:36  0%       ` Hibou57 (Yannick Duchêne)
  2009-10-27 16:13  5%         ` John B. Matthews
  0 siblings, 1 reply; 115+ results
From: Hibou57 (Yannick Duchêne) @ 2009-10-27  2:36 UTC (permalink / raw)


On 27 oct, 02:14, "John B. Matthews" <nos...@nospam.invalid> wrote:
> with Ada.Text_IO; use Ada.Text_IO;
> with Ada.Text_IO.Text_Streams;
>
> procedure Copy is
>    Stream_Ptr : Text_Streams.Stream_Access;
>    C : Character;
> begin
>    Stream_Ptr := Text_Streams.Stream(Current_Input);
>    loop
>       Character'Read(Stream_Ptr, C);
>       Put(C);
>    end loop;
> exception
>    when End_Error => null;
> end Copy;
>
> --
> John B. Matthews
> trashgod at gmail dot com
> <http://sites.google.com/site/drjohnbmatthews>

The trouble with this, is that this force a look-ahead : an item must
be read to know if an item is available, and this can lead into
numerous logical traps (I prefer to keep distinct the action of
reading and testing availability of data).

May be this is finally really better to re-create a type to stand for
the standard input as binary, but what I do not like with this way, is
the possible lack of knowledge of some platforms, which is required
for implementations (For me, it will be OK for Windows, BSD, Linux,
but not the others... although in the mean time, I'm not sure I will
ever need it for other platforms).



^ permalink raw reply	[relevance 0%]

* Re: Preferred way to do binray I/O on standard input/output stream
  2009-10-27  0:34  0%   ` Hibou57 (Yannick Duchêne)
@ 2009-10-27  1:14  6%     ` John B. Matthews
  2009-10-27  2:36  0%       ` Hibou57 (Yannick Duchêne)
  0 siblings, 1 reply; 115+ results
From: John B. Matthews @ 2009-10-27  1:14 UTC (permalink / raw)


In article 
<0d02cd9f-2cf1-48b6-a10f-6ea84427139d@k4g2000yqb.googlegroups.com>,
 Hibou57 (Yannick Duchêne) <yannick_duchene@yahoo.fr> wrote:

> On 24 oct, 23:57, "Jeffrey R. Carter" <spam.jrcarter....@spam.acm.org>
> wrote:
> > Package Ada.Text_IO.Text_Streams (ARM A.12.2) allows converting
> > Ada.Text_IO.File_Type to Stream_Access and reading and writing them through 
> > the
> > capabilities of streams.
> While this seems to work most of times, I meet a malfunction (data 
> not preserved) if the stream ends with a line-feed (a byte whose 
> value is 10). When it is, this last byte seems to be dropped from the 
> stream, which cause troubles if the binary format is expecting it. 
> This occurs only when it exactly ends with this byte, and it is Ok if 
> this byte is followed by a byte whose value is 0 (as an example). It 
> does not occur when the stream ends with a byte whose value is that 
> of the carriage- return (13).
> 
> Finally, this does not really turn the stream into a binary stream, 
> and some interpretations remain.

I get the same effect. I don't know if it's the shell (bash) or OS (Mac) 
doing it. I suspect the former: End_Of_File turns True when a final 
linefeed remains to be read; the effect is absent with redirection. I'm 
vaguely uneasy using an exception for flow control, but this seems to 
copy the data unmolested:

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Text_IO.Text_Streams;

procedure Copy is
   Stream_Ptr : Text_Streams.Stream_Access;
   C : Character;
begin
   Stream_Ptr := Text_Streams.Stream(Current_Input);
   loop
      Character'Read(Stream_Ptr, C);
      Put(C);
   end loop;
exception
   when End_Error => null;
end Copy;

-- 
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>



^ permalink raw reply	[relevance 6%]

* Re: Preferred way to do binray I/O on standard input/output stream
  2009-10-24 22:57  5% ` Jeffrey R. Carter
  2009-10-24 23:22  0%   ` Hibou57 (Yannick Duchêne)
@ 2009-10-27  0:34  0%   ` Hibou57 (Yannick Duchêne)
  2009-10-27  1:14  6%     ` John B. Matthews
  1 sibling, 1 reply; 115+ results
From: Hibou57 (Yannick Duchêne) @ 2009-10-27  0:34 UTC (permalink / raw)


On 24 oct, 23:57, "Jeffrey R. Carter" <spam.jrcarter....@spam.acm.org>
wrote:
> Package Ada.Text_IO.Text_Streams (ARM A.12.2) allows converting
> Ada.Text_IO.File_Type to Stream_Access and reading and writing them through the
> capabilities of streams.
While this seems to work most of times, I meet a malfunction (data not
preserved) if the stream ends with a line-feed (a byte whose value is
10). When it is, this last byte seems to be dropped from the stream,
which cause troubles if the binary format is expecting it. This occurs
only when it exactly ends with this byte, and it is Ok if this byte is
followed by a byte whose value is 0 (as an example). It does not occur
when the stream ends with a byte whose value is that of the carriage-
return (13).

Finally, this does not really turn the stream into a binary stream,
and some interpretations remain.



^ permalink raw reply	[relevance 0%]

* Re: Preferred way to do binray I/O on standard input/output stream
  2009-10-24 22:57  5% ` Jeffrey R. Carter
@ 2009-10-24 23:22  0%   ` Hibou57 (Yannick Duchêne)
  2009-10-27  0:34  0%   ` Hibou57 (Yannick Duchêne)
  1 sibling, 0 replies; 115+ results
From: Hibou57 (Yannick Duchêne) @ 2009-10-24 23:22 UTC (permalink / raw)


On 25 oct, 00:57, "Jeffrey R. Carter" <spam.jrcarter....@spam.acm.org>
wrote:
> Package Ada.Text_IO.Text_Streams (ARM A.12.2) allows converting
> Ada.Text_IO.File_Type to Stream_Access and reading and writing them through the
> capabilities of streams. This allows converting standard input and output to
> Stream_Access, since Ada.Text_IO provides the functions Standard_Input and
> Standard_Output which return Ada.Text_IO.File_Type.

So I was lucky to ask about it here

There is further more a note in ARM 12.2, which says (annotated
reference) :

> NOTES
> 6  35 The ability to obtain a stream for a text file allows
> Current_Input, Current_Output, and Current_Error to be processed
> with the functionality of streams, including the mixing of text and
> binary input-output, and the mixing of binary input-output for
> different types.
> 7  36 Performing operations on the stream associated with a text file
> does not affect the column, line, or page counts.

Now I feel I've already seen this in the past, but later forget

Thanks Jeffrey



^ permalink raw reply	[relevance 0%]

* Re: Preferred way to do binray I/O on standard input/output stream
  @ 2009-10-24 22:57  5% ` Jeffrey R. Carter
  2009-10-24 23:22  0%   ` Hibou57 (Yannick Duchêne)
  2009-10-27  0:34  0%   ` Hibou57 (Yannick Duchêne)
  0 siblings, 2 replies; 115+ results
From: Jeffrey R. Carter @ 2009-10-24 22:57 UTC (permalink / raw)


Hibou57 (Yannick Duch�ne) wrote:
> 
> There is no kind of binary mode vs text mode flags with Ada stream/
> file IO, as it there are with C. And then, C files are not typed,
> while Ada files/streams are, thus, this will not make any sense to
> simply talk about binary I/O with Ada. So let simply talk about non-
> text I/O from and to standard input/output.
> 
> When some people need this, what is the typical preferred to do so ?

Package Ada.Text_IO.Text_Streams (ARM A.12.2) allows converting 
Ada.Text_IO.File_Type to Stream_Access and reading and writing them through the 
capabilities of streams. This allows converting standard input and output to 
Stream_Access, since Ada.Text_IO provides the functions Standard_Input and 
Standard_Output which return Ada.Text_IO.File_Type.

For general binary I/O, one can use Ada.Sequential_IO or Ada.Direct_IO 
instantiated with an appropriate type, or Ada.Streams.Stream_IO. For standard 
input and output, however, this can only work if you have a name for these files 
that you can use to open them, and such a name is platform-dependent. The only 
independent way to access these files is through streams and 
Ada.Text_IO.Text_Streams.

-- 
Jeff Carter
"Drown in a vat of whiskey. Death, where is thy sting?"
Never Give a Sucker an Even Break
106



^ permalink raw reply	[relevance 5%]

* Re: Ada Shootout program for K-Nucleotide (patches)
  2009-08-05 22:31  0%                         ` Georg Bauhaus
@ 2009-08-06  7:51  0%                           ` Dmitry A. Kazakov
  0 siblings, 0 replies; 115+ results
From: Dmitry A. Kazakov @ 2009-08-06  7:51 UTC (permalink / raw)


On Thu, 06 Aug 2009 00:31:00 +0200, Georg Bauhaus wrote:

> Ludovic Brenta wrote:
>> Georg Bauhaus wrote on comp.lang.ada:
>>> +    procedure Print (Item : String) is
>>> +       Data : char_array renames To_C (Item & ASCII.LF);
>>> +    begin
>>> +       if fputs (Data'Address, stdout) < 0 then
>>> +          raise Ada.IO_Exceptions.Device_Error;
>>> +       end if;
>>> +    end Print;
>> 
>> I'm curious to know how the following performs:
>>
>> Stdout : constant Ada.Text_IO.Text_Streams.Stream_Access :=
>>   Ada.Text_IO.Text_Streams.Stream (Ada.Text_IO.Standard_Output);
>> 
>> procedure Print (Item : String) is
>> begin
>>    String'Write (Stdout, Item);
>>    Character'Write (Stdout, ASCII.LF);
>> end Print;
> 
> Terribly slow.  Requesting only a tenth of the required amount
> (i.e. N = 2500000) has taken ~30s. By extrapolation the full
> set is produced only after ~5m. That's almost 20x slower
> than the original Ada.Text_IO.
> 
> (The RM explains that String'Write calls procedure
> Character'Write for each component of the String...)

Newer GNATs use blocks of 256 characters or so, I don't remember the
figure. But as Jeff has suggested, you could use raw stream Write from
Ada.Streams.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[relevance 0%]

* Re: Ada Shootout program for K-Nucleotide (patches)
  2009-08-05 22:04  6%                       ` Ludovic Brenta
@ 2009-08-05 22:31  0%                         ` Georg Bauhaus
  2009-08-06  7:51  0%                           ` Dmitry A. Kazakov
  0 siblings, 1 reply; 115+ results
From: Georg Bauhaus @ 2009-08-05 22:31 UTC (permalink / raw)


Ludovic Brenta wrote:
> Georg Bauhaus wrote on comp.lang.ada:
>> +    procedure Print (Item : String) is
>> +       Data : char_array renames To_C (Item & ASCII.LF);
>> +    begin
>> +       if fputs (Data'Address, stdout) < 0 then
>> +          raise Ada.IO_Exceptions.Device_Error;
>> +       end if;
>> +    end Print;
> 
> I'm curious to know how the following performs:
>
> Stdout : constant Ada.Text_IO.Text_Streams.Stream_Access :=
>   Ada.Text_IO.Text_Streams.Stream (Ada.Text_IO.Standard_Output);
> 
> procedure Print (Item : String) is
> begin
>    String'Write (Stdout, Item);
>    Character'Write (Stdout, ASCII.LF);
> end Print;


Terribly slow.  Requesting only a tenth of the required amount
(i.e. N = 2500000) has taken ~30s. By extrapolation the full
set is produced only after ~5m. That's almost 20x slower
than the original Ada.Text_IO.

(The RM explains that String'Write calls procedure
Character'Write for each component of the String...)



^ permalink raw reply	[relevance 0%]

* Re: Ada Shootout program for K-Nucleotide (patches)
  @ 2009-08-05 22:04  6%                       ` Ludovic Brenta
  2009-08-05 22:31  0%                         ` Georg Bauhaus
  0 siblings, 1 reply; 115+ results
From: Ludovic Brenta @ 2009-08-05 22:04 UTC (permalink / raw)


Georg Bauhaus wrote on comp.lang.ada:
> +    procedure Print (Item : String) is
> +       Data : char_array renames To_C (Item & ASCII.LF);
> +    begin
> +       if fputs (Data'Address, stdout) < 0 then
> +          raise Ada.IO_Exceptions.Device_Error;
> +       end if;
> +    end Print;

I'm curious to know how the following performs:

Stdout : constant Ada.Text_IO.Text_Streams.Stream_Access :=
  Ada.Text_IO.Text_Streams.Stream (Ada.Text_IO.Standard_Output);

procedure Print (Item : String) is
begin
   String'Write (Stdout, Item);
   Character'Write (Stdout, ASCII.LF);
end Print;

--
Ludovic Brenta.



^ permalink raw reply	[relevance 6%]

* Re: Ada Shootout program for K-Nucleotide (patches)
  @ 2009-08-02 12:55  6%   ` Georg Bauhaus
    1 sibling, 0 replies; 115+ results
From: Georg Bauhaus @ 2009-08-02 12:55 UTC (permalink / raw)


Ludovic Brenta wrote:
> Georg Bauhaus wrote on comp.lang.ada:
>> This is about the K-Nucleotide program at the
>> Computer Language Benchmark Game,http://shootout.alioth.debian.org/u32/benchmark.php?test=knucleotide&...
>> where some Ada programs have started to fail.
>>
>> In order to have one of them work again, I have patched
>> knucleotide.gnat, with some success.  New version is here:http://home.arcor.de/bauhaus/Ada/knucleotide.gnat
>>
>> Comments?  Does it work on your machine?
>>
>> The two changes:
>>
>> 1 - [stack exhaustion] a loop reading input lines into an
>>  ubounded  string replaces the recursive String "&"ing
>>  procedure. (Noting that the input text file is ~240MB ...)
>>
>> 2 - [heavy bounded strings] a lightweight bounded string ADT
>>  replaces an instance of Generic_Bounded_Length, yielding
>>  an improved running time of ~22s down from ~30s for
>>  the 2,500,000 case.
>>
>> Still, on a relatively small virtual machine running 64bit
>> Debian, the program cannot handle the 25,000,000 case.
> 
> I note that both Martin and yourself use Ada.Text_IO (especially
> Read_Line) which is notoriously slow.  I would use Character'Read and
> a finite state machine to detect the portion of the input file to be
> processed, then to fill in the buffer.  That should be faster.

Not sure that Character'Read will really be faster.
The following Getline has left me unconvinced.
I made a simple test just reading big files and
measuring the time; Text_IO.Get_Line wins on Windows
and even more or Debian.

Also, unless there is bug in the program below,
using Streams and then child packages of Text_IO
for output formatting, seems to confuse the
I/O system.  (Would we be shooting ourselves in
the foot anyway?)

GNAT.IO is, I think, getting us in trouble; it doesn't
signal End_Error, if I'm not mistaken.


with Ada.Text_IO.Text_Streams;

procedure Getline (Item: in out String; Last : out Natural) is
   --
   --  Input via Character'Read.
   --  Assume Unix or Windows line ending conventions.
   --
   Stdin: constant Ada.Text_IO.Text_Streams.Stream_Access :=
     Ada.Text_IO.Text_Streams.Stream (Ada.Text_IO.Standard_Input);
   C : Character;
begin
   Last := Item'First - 1;

   loop
      Character'Read (Stdin, C);
      exit when C = ASCII.LF;
      if C /= ASCII.CR then
         Last := Last + 1;
         Item (Last) := C;
      end if;
      exit when Last = Item'Last;
   end loop;

end Getline;



^ permalink raw reply	[relevance 6%]

* Re: C getchar() functionality in Ada
  2009-02-17  8:16  6%     ` Niklas Holsti
@ 2009-02-17 13:01  0%       ` Georg Bauhaus
  0 siblings, 0 replies; 115+ results
From: Georg Bauhaus @ 2009-02-17 13:01 UTC (permalink / raw)


Niklas Holsti schrieb:
> Thomas Locke wrote:
>> Jeffrey R. Carter wrote:
>>
>>> This is one of the latter cases. You should not be using Character,
>>> String, or Ada.Text_IO for this. I suggest you look at streams and
>>> Ada.Text_IO.Text_Streams.
> 
> Or Ada.Sequential_IO, instantiated for Character (or Storage_Element,
> etc.) which seems to me the best match to the original C program.
> However, Sequential_IO has the problem that the standard-input and
> standard-output channels are not accessible, you must Open named files.
> 
>> I will try this when my Ada skills have improved a bit. For now I will
>> focus on learning how to best use Text_IO.
>>
>> I wouldn't mind a smallish example on using Ada.Text_IO.Text_Streams
>> though...  :D
> 
> Here is a copy-input-to-output program with Text_Streams and Character:
> 
> with Ada.Text_IO.Text_Streams;
> 
> procedure Acopy
> is
>    use Ada.Text_IO;
>    use Ada.Text_IO.Text_Streams;
> 
>    Input  : constant Stream_Access := Stream (Standard_Input);
>    Output : constant Stream_Access := Stream (Standard_Output);
> 
>    Item : Character;
> 
> begin
> 
>    while not End_Of_File (Standard_Input) loop
> 
>       Character'Read (Input , Item);
>       Character'Write(Output, Item);
> 
>    end loop;
> 
> end Acopy;


We can write the same program in Ada, of course. :-)
Only, the Ada version is likely written without
resorting to the C's idiomatic
"statement-used-as-expression-in-the-loop-conditional".

with Interfaces.C;

procedure C_1 is

   use Interfaces.C;

   function getchar return int;
   function putchar(item: int) return int;

   pragma Import(C, getchar);
   pragma Import(C, putchar);

   EOF: constant int := -1;             --  see <stdio.h>
   c, not_checked: int;

begin
   loop
      c := getchar;
      exit when C = EOF;
      not_checked := putchar(c);
   end loop;
end C_1;



^ permalink raw reply	[relevance 0%]

* Re: C getchar() functionality in Ada
  2009-02-17  7:23  5%   ` Thomas Locke
@ 2009-02-17  8:16  6%     ` Niklas Holsti
  2009-02-17 13:01  0%       ` Georg Bauhaus
  0 siblings, 1 reply; 115+ results
From: Niklas Holsti @ 2009-02-17  8:16 UTC (permalink / raw)


Thomas Locke wrote:
> Jeffrey R. Carter wrote:
> 
>> This is one of the latter cases. You should not be using Character, 
>> String, or Ada.Text_IO for this. I suggest you look at streams and 
>> Ada.Text_IO.Text_Streams.

Or Ada.Sequential_IO, instantiated for Character (or 
Storage_Element, etc.) which seems to me the best match to the 
original C program. However, Sequential_IO has the problem that the 
standard-input and standard-output channels are not accessible, you 
must Open named files.

> I will try this when my Ada skills have improved a bit. For now I will 
> focus on learning how to best use Text_IO.
> 
> I wouldn't mind a smallish example on using Ada.Text_IO.Text_Streams 
> though...  :D

Here is a copy-input-to-output program with Text_Streams and Character:

with Ada.Text_IO.Text_Streams;

procedure Acopy
is
    use Ada.Text_IO;
    use Ada.Text_IO.Text_Streams;

    Input  : constant Stream_Access := Stream (Standard_Input);
    Output : constant Stream_Access := Stream (Standard_Output);

    Item : Character;

begin

    while not End_Of_File (Standard_Input) loop

       Character'Read (Input , Item);
       Character'Write(Output, Item);

    end loop;

end Acopy;


-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .



^ permalink raw reply	[relevance 6%]

* Re: C getchar() functionality in Ada
  2009-02-16 21:43  4% ` Jeffrey R. Carter
@ 2009-02-17  7:23  5%   ` Thomas Locke
  2009-02-17  8:16  6%     ` Niklas Holsti
  0 siblings, 1 reply; 115+ results
From: Thomas Locke @ 2009-02-17  7:23 UTC (permalink / raw)


Jeffrey R. Carter wrote:
> This is one of the latter cases. You should not be using Character, 
> String, or Ada.Text_IO for this. I suggest you look at streams and 
> Ada.Text_IO.Text_Streams.


I will try this when my Ada skills have improved a bit. For now I will 
focus on learning how to best use Text_IO.

I wouldn't mind a smallish example on using Ada.Text_IO.Text_Streams 
though...  :D

/Thomas



^ permalink raw reply	[relevance 5%]

* Re: C getchar() functionality in Ada
  @ 2009-02-16 21:43  4% ` Jeffrey R. Carter
  2009-02-17  7:23  5%   ` Thomas Locke
  0 siblings, 1 reply; 115+ results
From: Jeffrey R. Carter @ 2009-02-16 21:43 UTC (permalink / raw)


Thomas Locke wrote:
> 
> I've started redoing all the K&R C examples in Ada, and I've already hit 
> a wall that I'm not able to get around.
> 
> I have this C program:  http://pastebin.com/fbc6bec5
> 
> It's very simple, but still I fail to mimick it in Ada.

This program duplicates standard input on standard output.

You are being mislead by the use of "char" in C. "char" sometimes refers to the 
equivalent of Ada's Character, and other times to the equivalent of 
System.Storage_Elements.Storage_Element or Ada.Streams.Stream_Element.

This is one of the latter cases. You should not be using Character, String, or 
Ada.Text_IO for this. I suggest you look at streams and Ada.Text_IO.Text_Streams.

-- 
Jeff Carter
"Help! Help! I'm being repressed!"
Monty Python & the Holy Grail
67



^ permalink raw reply	[relevance 4%]

* Auto new line
@ 2007-12-18 19:26  6% Jeffrey R. Carter
  0 siblings, 0 replies; 115+ results
From: Jeffrey R. Carter @ 2007-12-18 19:26 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 101 bytes --]


-- 
Jeff Carter
"From this day on, the official language of San Marcos will be Swedish."
Bananas
28

[-- Attachment #2: hello.adb --]
[-- Type: text/plain, Size: 183 bytes --]

with Ada.Text_IO.Text_Streams;

procedure Hello is
   -- null;
begin -- Hello
  String'Write (Ada.Text_IO.Text_Streams.Stream (Ada.Text_IO.Standard_Output), "hello");
end Hello;

^ permalink raw reply	[relevance 6%]

* Re: newline in a simple program
  @ 2007-12-18 13:11  6% ` Dmitry A. Kazakov
  0 siblings, 0 replies; 115+ results
From: Dmitry A. Kazakov @ 2007-12-18 13:11 UTC (permalink / raw)


On Tue, 18 Dec 2007 12:28:28 GMT, Paul wrote:

> Hi, given the following two simple programs
> 
> hello.adb
> -----------------------
> with ada.text_io;
> procedure hello is
> begin
> ada.text_io.put("hello");
> end hello;
> -----------------------
> 
> 
> hello.c
> -----------------------
> #include <stdio.h>
> int main()
> {
>      printf("hello");
> }
> -----------------------
> 
> the result for the ada program is:
> -----------------------
> $ ./hello_in_ada
> hello
> $
> -----------------------
> 
> and for the c program:
> -----------------------
> $ ./hello_in_c
> hello$
> -----------------------
> 
> The c program does not print a new-line, but the ada program does.
> 
> Is there any way to make the ada program not print a new-line?
> 
> And is this behavior part of the Ada standard or is it just part of gnat?
> 
> I looked for answers, but found none.

You can use stream I/O in order to make sure that Text_IO wouldn't add page
formatting you don't need:

with Ada.Text_IO.Text_Streams;

use Ada.Text_IO;
use Ada.Text_IO.Text_Streams;

procedure Hello is
begin
  String'Write (Stream (Standard_Output), "hello");
end Hello;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[relevance 6%]

* Re: I/O streaming with custom data transport
  @ 2006-11-22 16:11  4%         ` Georg Bauhaus
  0 siblings, 0 replies; 115+ results
From: Georg Bauhaus @ 2006-11-22 16:11 UTC (permalink / raw)


On Wed, 2006-11-22 at 15:37 +0100, Maciej Sobczak wrote:

> For the moment I assume that in order to do this with text, I have to 
> first format it in some string buffer and then do:
> 
> String'Write(S, Buf);

Have you considered 
 for T'Write use Your_Function...

Also, Ada.Text_IO.Text_Streams is an example of how to use
the attribute functions with text file streams. So you'd have
the formatting in 'Write and the transport mechanics in the
new byte stream type.





^ permalink raw reply	[relevance 4%]

* Re: I/O streaming with custom data transport
  @ 2006-11-22  9:16  6%   ` Maciej Sobczak
    0 siblings, 1 reply; 115+ results
From: Maciej Sobczak @ 2006-11-22  9:16 UTC (permalink / raw)


Alex R. Mosteo wrote:

>> I'm looking for something like this in Ada.
>>
>> The basic I/O facilities in the standard library don't seem to provide
>> anything like this.
>> I hoped that Ada.Streams allows this by subclassing Root_Stream_Type and
>> providing some overriding operations, but unfortunately I cannot even
>> find the specification of Root_Stream_Type (looks like there isn't any
>> and this type is just a name placeholder in ARM).
> 
> I think you haven't looked right.

Indeed - it's in 13.13.1.

> That's precisely how it's done.

> And you do this just as you say: you extend
> Ada.Streams.Root_Stream_Type and provide the read/write subprograms.

And I actually managed to do this.
Consider the following example of custom stream that for the sake of 
presentation is bound to standard IO and just converts characters to 
uppercase when writing (the point is that if I can do *this*, I can do 
anything else):

-- file my_streams.ads:
with Ada.Streams;
package My_Streams is
    use Ada.Streams;

    type My_Stream is new Root_Stream_Type with null record;

    procedure Read(Stream : in out My_Stream;
                   Item : out Stream_Element_Array;
                   Last : out Stream_Element_Offset);

    procedure Write(Stream : in out My_Stream;
                    Item : in Stream_Element_Array);
end My_Streams;

-- file my_streams.adb:
with Ada.Text_IO.Text_Streams;
with Ada.Characters.Handling;
package body My_Streams is
    use Ada.Text_IO;
    use Ada.Text_IO.Text_Streams;

    Std_Stream : Stream_Access := Stream(Current_Output);

    procedure Read(Stream : in out My_Stream;
                   Item : out Stream_Element_Array;
                   Last : out Stream_Element_Offset) is
    begin
       -- forward to standard streams:
       Read(Std_Stream.all, Item, Last);
    end Read;

    procedure Write(Stream : in out My_Stream;
                    Item : in Stream_Element_Array) is
       Item_Uppercase : Stream_Element_Array := Item;
       C : Character;
    begin
       for I in Item_Uppercase'Range loop
          C := Character'Val(Item_Uppercase(I));
          C := Ada.Characters.Handling.To_Upper(C);
          Item_Uppercase(I) := Stream_Element(Character'Pos(C));
       end loop;

       -- forward to standard streams:
       Write(Std_Stream.all, Item_Uppercase);
    end Write;
end My_Streams;

-- file hello.adb:
with Ada.Text_IO.Text_Streams;
with My_Streams;

procedure Hello is
    use Ada.Text_IO;
    use Ada.Text_IO.Text_Streams;
    use My_Streams;

    procedure Write_Hello(Stream : in out Stream_Access) is
    begin
       String'Write(Stream, "Hello");
    end Write_Hello;

    S1 : Stream_Access := Stream(Current_Output);
    S2 : Stream_Access := new My_Stream;
begin
    Write_Hello(S1);
    New_Line;
    Write_Hello(S2);
    New_Line;
end Hello;

The result is:

$ ./hello
Hello
HELLO
$

The point here is that the Write_Hello procedure can be reused with 
various streams, just like my foo functions in C++ (from initial post).

Is the code above correct? Any traps or problems that I don't see at the 
moment?


-- 
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/



^ permalink raw reply	[relevance 6%]

* Re: Newbie Question: using Text_IO.Open() to read from standard input
  2005-10-13  0:49  4% Newbie Question: using Text_IO.Open() to read from standard input pamela.lum
@ 2005-10-13  3:15  0% ` Steve
  0 siblings, 0 replies; 115+ results
From: Steve @ 2005-10-13  3:15 UTC (permalink / raw)


<pamela.lum@gmail.com> wrote in message 
news:1129164557.586640.154480@g14g2000cwa.googlegroups.com...
> Hi,
>
> I need to open a file that is passed to my ada executable as standard
> input, in the following fashion:
>
> ./myprogram < inputfile.txt
>
> My question is: How can i get the Open() function to open a file from
> standard input so that I can bypass using a static file name? For
> example:
>
> Integer_File : FILE_TYPE;
> Open(Integer_File, In_File, "inputfile.txt"); <-- don't open
> inputfile.txt, open file from standard input instead
>
> I know that this can be done easily with Ada.Text_IO.Text_Streams,
> however I am stubborn and curious to see if there is a simple and easy
> way to do it with the Open() function.
>
> THanks
>
The following simple example works on red hat linux 8.0

with Ada.Text_IO;

procedure TestPassThru is
  package Text_IO renames Ada.Text_IO;
begin
  while not Text_IO.End_Of_File loop
    declare
        text : String( 1 .. 255 );
        last : Natural;
    begin
       Text_IO.Get_Line( text, last );
       Text_IO.Put_Line( text( 1 .. last ) );
    end;
  end loop;
end TestPassThru;

(Sorry for any typo's I had to copy the code from one screen to another).

Steve
(The Duck)





^ permalink raw reply	[relevance 0%]

* Newbie Question: using Text_IO.Open() to read from standard input
@ 2005-10-13  0:49  4% pamela.lum
  2005-10-13  3:15  0% ` Steve
  0 siblings, 1 reply; 115+ results
From: pamela.lum @ 2005-10-13  0:49 UTC (permalink / raw)


Hi,

I need to open a file that is passed to my ada executable as standard
input, in the following fashion:

./myprogram < inputfile.txt

My question is: How can i get the Open() function to open a file from
standard input so that I can bypass using a static file name? For
example:

Integer_File : FILE_TYPE;
Open(Integer_File, In_File, "inputfile.txt"); <-- don't open
inputfile.txt, open file from standard input instead

I know that this can be done easily with Ada.Text_IO.Text_Streams,
however I am stubborn and curious to see if there is a simple and easy
way to do it with the Open() function.

THanks




^ permalink raw reply	[relevance 4%]

* Re: Using fwrite in Ada
    2005-08-10 17:28  5% ` Georg Bauhaus
@ 2005-08-11 17:01  3% ` tmoran
  1 sibling, 0 replies; 115+ results
From: tmoran @ 2005-08-11 17:01 UTC (permalink / raw)


> I want to read and write binary data from stdin/stdout, unfortunately Ada's
> usual IO routines appear to be text only and (on Win32) convert code 10 to
> codes 10 & 13.
  Ada.Text_IO.Text_Streams addresses exactly that problem.

> To get round this I'm trying to use Interfaces.C_Streams, but I don't know
> How to I get a String into the fwrite function?
   Do you need to call "fwrite", or do you just need to write binary data
that can be read back by another Ada program?  In the latter case, 'write,
as has been suggested, will do the job.  The bit pattern that gets written
is implementation defined, unless you override that.  That can be handy.

>  cptr : chars_ptr;
>  Buffer : String (1..100);
>   cptr:=New_String(Buffer);
  implies that chars_ptr is an access to an unconstrained array.  So it
points to both the subscript range of the string and to the character data
in the string.  That is not the same thing as a C pointer to a byte (that
may happen to be the first byte in the string).

>   vptr:=voids(cptr);
>
>   fwrite(vptr,100,1,stdout);
> But this won't compile, the compiler says that it cannot convert the
> chars_ptr to voids. Coming from a C background, I don't understand why
> something cannot be cast to void.
   In Ada, type matters.  What would you expect to happen if you said
  cptr := chars_ptr(vptr);
How would the cptr find out the size of the string that held the byte
that vptr currently points to?

  Look further at Interfaces.  You seem to want to be able to call fwrite
with a String parameter and ignore its result:
   Tell the compiler:
   procedure fwrite(Source : String;
                   Size, Length : Natural;
                   Target : File_Ptr);
   pragma Import(fwrite, C);
then use it
   fwrite(Buffer, 1, Buffer'length, stdout);



^ permalink raw reply	[relevance 3%]

* Re: Using fwrite in Ada
  @ 2005-08-10 17:28  5% ` Georg Bauhaus
  2005-08-11 17:01  3% ` tmoran
  1 sibling, 0 replies; 115+ results
From: Georg Bauhaus @ 2005-08-10 17:28 UTC (permalink / raw)


Makhno wrote:

> Does anybody have any idea as to how I get binary data onto stdout?

Use Streams and the 'Write and 'Read attributes of the type used
for binary data.

Here is a possible output part, it gets binary data onto stdout.
For the input part, use the 'read attribute where the text uses
the 'write attribute.


with Ada.Text_IO.Text_Streams;

procedure binio is

   use Ada.Text_IO;

   type Byte is mod 2**8;
   for Byte'size use 8;  -- just to make sure

   type Binary_Data is array(Natural range <>) of Byte;
     -- the type used for storing binary data internally

   stuff: Binary_Data(1..10);

   destination: Text_Streams.Stream_Access;

begin
   destination := Text_Streams.Stream (standard_output);
   Binary_Data'write(destination, stuff);
end binio;

If you just want to write integers, records (structs) etc.
to standard_output, use the 'Write attributes of the respective
types. That's what they are for. (No need to "cast" something.)



^ permalink raw reply	[relevance 5%]

* Re: Ada bench : count words
  2005-03-23 15:09  6%               ` Marius Amado Alves
@ 2005-03-30 16:08  0%                 ` Andre
  0 siblings, 0 replies; 115+ results
From: Andre @ 2005-03-30 16:08 UTC (permalink / raw)



Marius Amado Alves wrote:
>> I'll review this tomorrow on the bus to work (I think your program is 
>> separating words at buffer end, and it should not).
> 
> 
> Done. Tmoran, sorry, my first sight was wrong, your algorithm is mostly 
> fine. Minor reservations:
> - special statute given to CR; personally I think all characters 
> (control or not) should count to total
> - reliance on Stream_Element representing one character; portable across 
> all range of environments?
> 
> My own program rewritten with Text_Streams attains the same speed as 
> yours. The fact that it is structured doesn't hit performance 
> significantly. Pragma Inline improves a little bit. Real times (ms) on 
> my iBook, for input file repeated 2500 times, all compiled with only -O3:
> C ........................ 600
> Yours, or mine inlined ... 700
> Mine not inlined ......... 750
> 
> So we should submit yours, or mine inlined. It will put Ada right after 
> the Cs w.r.t. speed. W.r.t. executable file size Ada is much bigger. On 
> my iBook:
> C .......  15k
> Mine .... 423k
> Yours ... 459k
> 
> W.r.t. source code size all are similar. Number of significant 
> semicolons (Ada), or semicolons + {} blocks + #includes + #defines (C):
> C .............. 27
> Yours .......... 33
> Mine inlined ... 52
> 
> My program follows for reference. It accepts the code for EOL as an 
> argument. Default = 10 (LF).
> 
> -- The Great Computer Language Shootout
> -- http://shootout.alioth.debian.org/
> -- 
> -- contributed by Guys De Cla
> 
> with Ada.Characters.Handling;
> with Ada.Characters.Latin_1;
> with Ada.Command_Line;
> with Ada.Streams;
> with Ada.Streams.Stream_IO;
> with Ada.Strings.Fixed;
> with Ada.Text_IO;
> with Ada.Text_IO.Text_Streams;
> 
> procedure Count_Words_Portable is
> 
>    use Ada.Characters.Handling;
>    use Ada.Characters.Latin_1;
>    use Ada.Command_Line;
>    use Ada.Streams;
>    use Ada.Streams.Stream_IO;
>    use Ada.Text_IO;
>    use Ada.Text_IO.Text_Streams;
> 
>    Buffer : Stream_Element_Array (1 .. 4096);
>    Input_Stream : Ada.Text_IO.Text_Streams.Stream_Access
>      := Ada.Text_IO.Text_Streams.Stream (Current_Input);
>    EOL_Character_Pos : Stream_Element := Character'Pos (LF);
>    Lines : Natural := 0;
>    Words : Natural := 0;
>    Total : Natural := 0;
>    In_Word : Boolean := False;
>    N : Stream_Element_Offset;
>    Is_Separator : array (Stream_Element) of Boolean :=
>      (0 .. 32 | 127 .. 159 => True, others => False);
> 
>    procedure Begin_Word is
>    begin
>       Words := Words + 1;
>       In_Word := True;
>    end;
> 
>    procedure End_Word is
>    begin
>       In_Word := False;
>    end;
> 
>    procedure End_Line is
>    begin
>       Lines := Lines + 1;
>       End_Word;
>    end;
> 
>    procedure Count_Words (S : in Stream_Element_Array) is
>    begin
>       Total := Total + S'Length;
>       for I in S'Range loop
>          if S (I) = EOL_Character_Pos then
>             End_Line;
>          else
>             if Is_Separator (S (I)) then
>                if In_Word then End_Word; end if;
>             else
>                if not In_Word then Begin_Word; end if;
>             end if;
>          end if;
>       end loop;
>    end;
> 
>    pragma Inline (Begin_Word, End_Word, End_Line, Count_Words);
> 
> begin
>    begin
>       EOL_Character_Pos := Stream_Element'Value (Argument (1));
>    exception
>       when Constraint_Error => null;
>    end;
>    Ada.Text_IO.Put_Line ("EOL =>" & Stream_Element'Image 
> (EOL_Character_Pos));
> 
>    loop
>       Read (Root_Stream_Type'Class (Input_Stream.all), Buffer, N);
>       Count_Words (Buffer (1 .. N));
>       exit when N < Buffer'Length;
>    end loop;
> 
>    Ada.Text_IO.Put_Line
>      (Natural'Image (Lines) &
>       Natural'Image (Words) &
>       Natural'Image (Total));
> end;
> 

I checked with the Shootout side. The Ada program sent in was rated with 
Error. So, maybe you can check why and correct it.

Andr�


^ permalink raw reply	[relevance 0%]

* Re: Gnat 3.15p & Windows & Hyperthreading Q
  2005-03-26 18:36  5% ` tmoran
@ 2005-03-28 13:16  0%   ` Marin David Condic
  0 siblings, 0 replies; 115+ results
From: Marin David Condic @ 2005-03-28 13:16 UTC (permalink / raw)


On a quick scan, I don't see anything obvious. Let me take a look at it 
and I'll see if I spot anything that might be problematic.

MDC

tmoran@acm.org wrote:
> 
>     The original program was posted under "Ada bench : count words",
> as was the dual-Celeron timing.  The hyperthreading timing was a personal
> communication.  It's possible the person was mistaken in thinking they
> had hyperthreading turned on, with processor affinities set correctly.
> I'm inquiring further.
> 
>   So here's the benchmark.  It reads a text file from Standard Input,
> preferably at least a megabyte to get a decent timing read, and prints
> line, word, and character counts to Standard Output.  The number of
> CPU-heavy tasks is the number of elements of
>   Counter : array(1 .. 2) of Counters;
> Probably increasing the buffer size, by lessening task interactions,
> would speed it up and improve the multi-tasking benefit.
> 
> with Ada.Calendar,
>      Ada.Streams,
>      Ada.Streams.Stream_IO,
>      Ada.Text_IO,
>      Ada.Text_IO.Text_Streams;
> procedure Cwt is
>   use Ada.Streams;
>   use type Ada.Calendar.Time;
> 
>   T0  : Ada.Calendar.Time := Ada.Calendar.Clock;  -- start timing
>   T1  : Ada.Calendar.Time;
> 
>   subtype Buffer_Type is Stream_Element_Array(1 .. 4096);
> 
>   LF      : constant Stream_Element := Character'pos(Ascii.LF);
>   Is_Whitespace : constant array(Stream_Element) of Boolean
>     := (Character'pos(Ascii.LF) | Character'pos(Ascii.HT)
>         | Character'pos(' ') => True, others => False);
> 
>   -- "Counters" tasks run independently, asking Data_Source for buffer loads
>   -- and tallying word and line counts.  When done, they wait for their
>   -- (partial) counts to be harvested, then terminate.
> 
>   task type Counters is
>     entry Harvest(Line_Count, Word_Count : out Natural);
>   end Counters;
> 
>   -- Data_Source is the IO task, supplying data as requested to Counters.
>   -- Note that Data_Source counts the whitespace->non-white transitions
>   -- at the ends of buffers.  Counters' partial counts are added to that.
>   -- Data_Source also counts the Total number of characters.
> 
>   task Data_Source is
>     entry Get(Buffer : out Buffer_Type;
>               Last : out Stream_Element_Offset);
>   end Data_Source;
> 
>   task body Counters is
>     Buffer : Buffer_Type;
>     Last : Stream_Element_Offset;
>     Lines, Words, Total : Natural := 0;
>     In_Whitespace : Boolean;
>   begin
>     loop
>       Data_Source.Get(Buffer, Last);
>       exit when Last = 0;
>       In_Whitespace := Is_Whitespace(Buffer(1));
>       for I in 1 .. Last loop
>         if Is_Whitespace(Buffer(I)) then
>           if Buffer(I) = LF then
>             Lines := Lines + 1;
>           end if;
>           In_Whitespace := True;
>         elsif In_Whitespace then
>           In_Whitespace := False;
>           Words := Words + 1;
>         end if;
>       end loop;
>       exit when Last < Buffer'last;
>     end loop;
>     accept Harvest(Line_Count, Word_Count : out Natural) do
>       Line_Count := Lines;
>       Word_Count := Words;
>     end;
>   end Counters;
> 
>   Lines, Words, Total : Natural := 0;
> 
>   task body Data_Source is
>     Stream  : Ada.Text_IO.Text_Streams.Stream_Access;
>     At_End : Boolean := False;
>     In_Whitespace : Boolean := True; -- we must count at edges of buffer loads
>   begin
>     Stream := Ada.Text_IO.Text_Streams.Stream(Ada.Text_IO.Current_Input);
>     loop
>       select
>         accept Get(Buffer : out Buffer_Type;
>                    Last : out Stream_Element_Offset) do
>           if At_End then Last := 0;
>           else
>             Ada.Streams.Read(Ada.Streams.Root_Stream_Type'Class(Stream.all),
>                              Buffer, Last);
>             Total := Total+Integer(Last);
>             if Last > 0 then
>               if In_Whitespace and not Is_Whitespace(Buffer(1)) then
>                 Words := Words+1;
>               end if;
>               In_Whitespace := Is_Whitespace(Buffer(Last));
>             end if;
>             if Last < Buffer'last then At_End := True;end if;
>           end if;
>         end;
>       or terminate;
>       end select;
>     end loop;
>   end Data_Source;
> 
>   A_Line_Count, A_Word_Count : Natural := 0;
> 
>   Counter : array(1 .. 2) of Counters;
> 
> begin
> 
>   for i in Counter'range loop
>     Counter(i).Harvest(A_Line_Count, A_Word_Count);
>     Lines := Lines+A_Line_Count;
>     Words := Words+A_Word_Count;
>   end loop;
> 
>   T1 := Ada.Calendar.Clock;
> 
>   Ada.Text_IO.Put_Line(Natural'Image(Lines)
>                        & Natural'Image(Words)
>                        & Natural'Image(Total));
>   Ada.Text_IO.Put_Line("took" & Duration'Image(T1 - T0));
> end Cwt;

-- 
======================================================================
Marin David Condic
I work for: http://www.belcan.com/
My project is: http://www.jsf.mil/NSFrames.htm

Send Replies To: m   o   d   c @ a   m   o   g
                    c   n   i       c   .   r

     "'Shut up,' he explained."

         --  Ring Lardner
======================================================================



^ permalink raw reply	[relevance 0%]

* Re: Gnat 3.15p & Windows & Hyperthreading Q
  @ 2005-03-26 18:36  5% ` tmoran
  2005-03-28 13:16  0%   ` Marin David Condic
  0 siblings, 1 reply; 115+ results
From: tmoran @ 2005-03-26 18:36 UTC (permalink / raw)


> >   I'm told that a multitask program compiled with Gnat 3.15p and run
> > under Windows XP Pro on a hyperthreaded machine, runs in the same total
> > time as the same program using a single task.  OTOH, when compiled with
> > GNAT 5.02a1 and run on a dual-processor 400 MHz Celeron running Mandrake
> > Linux 8.2, it runs about 50% faster with two rather than one tasks.
>
> That seems strange. In the first case, is it a SINGLE processor machine?
> Or is it the same dual processor 400mhz Celeron in both cases?
> Also, is this just anecdotal or is there an actual benchmark program
> that could be looked at?
    The original program was posted under "Ada bench : count words",
as was the dual-Celeron timing.  The hyperthreading timing was a personal
communication.  It's possible the person was mistaken in thinking they
had hyperthreading turned on, with processor affinities set correctly.
I'm inquiring further.

  So here's the benchmark.  It reads a text file from Standard Input,
preferably at least a megabyte to get a decent timing read, and prints
line, word, and character counts to Standard Output.  The number of
CPU-heavy tasks is the number of elements of
  Counter : array(1 .. 2) of Counters;
Probably increasing the buffer size, by lessening task interactions,
would speed it up and improve the multi-tasking benefit.

with Ada.Calendar,
     Ada.Streams,
     Ada.Streams.Stream_IO,
     Ada.Text_IO,
     Ada.Text_IO.Text_Streams;
procedure Cwt is
  use Ada.Streams;
  use type Ada.Calendar.Time;

  T0  : Ada.Calendar.Time := Ada.Calendar.Clock;  -- start timing
  T1  : Ada.Calendar.Time;

  subtype Buffer_Type is Stream_Element_Array(1 .. 4096);

  LF      : constant Stream_Element := Character'pos(Ascii.LF);
  Is_Whitespace : constant array(Stream_Element) of Boolean
    := (Character'pos(Ascii.LF) | Character'pos(Ascii.HT)
        | Character'pos(' ') => True, others => False);

  -- "Counters" tasks run independently, asking Data_Source for buffer loads
  -- and tallying word and line counts.  When done, they wait for their
  -- (partial) counts to be harvested, then terminate.

  task type Counters is
    entry Harvest(Line_Count, Word_Count : out Natural);
  end Counters;

  -- Data_Source is the IO task, supplying data as requested to Counters.
  -- Note that Data_Source counts the whitespace->non-white transitions
  -- at the ends of buffers.  Counters' partial counts are added to that.
  -- Data_Source also counts the Total number of characters.

  task Data_Source is
    entry Get(Buffer : out Buffer_Type;
              Last : out Stream_Element_Offset);
  end Data_Source;

  task body Counters is
    Buffer : Buffer_Type;
    Last : Stream_Element_Offset;
    Lines, Words, Total : Natural := 0;
    In_Whitespace : Boolean;
  begin
    loop
      Data_Source.Get(Buffer, Last);
      exit when Last = 0;
      In_Whitespace := Is_Whitespace(Buffer(1));
      for I in 1 .. Last loop
        if Is_Whitespace(Buffer(I)) then
          if Buffer(I) = LF then
            Lines := Lines + 1;
          end if;
          In_Whitespace := True;
        elsif In_Whitespace then
          In_Whitespace := False;
          Words := Words + 1;
        end if;
      end loop;
      exit when Last < Buffer'last;
    end loop;
    accept Harvest(Line_Count, Word_Count : out Natural) do
      Line_Count := Lines;
      Word_Count := Words;
    end;
  end Counters;

  Lines, Words, Total : Natural := 0;

  task body Data_Source is
    Stream  : Ada.Text_IO.Text_Streams.Stream_Access;
    At_End : Boolean := False;
    In_Whitespace : Boolean := True; -- we must count at edges of buffer loads
  begin
    Stream := Ada.Text_IO.Text_Streams.Stream(Ada.Text_IO.Current_Input);
    loop
      select
        accept Get(Buffer : out Buffer_Type;
                   Last : out Stream_Element_Offset) do
          if At_End then Last := 0;
          else
            Ada.Streams.Read(Ada.Streams.Root_Stream_Type'Class(Stream.all),
                             Buffer, Last);
            Total := Total+Integer(Last);
            if Last > 0 then
              if In_Whitespace and not Is_Whitespace(Buffer(1)) then
                Words := Words+1;
              end if;
              In_Whitespace := Is_Whitespace(Buffer(Last));
            end if;
            if Last < Buffer'last then At_End := True;end if;
          end if;
        end;
      or terminate;
      end select;
    end loop;
  end Data_Source;

  A_Line_Count, A_Word_Count : Natural := 0;

  Counter : array(1 .. 2) of Counters;

begin

  for i in Counter'range loop
    Counter(i).Harvest(A_Line_Count, A_Word_Count);
    Lines := Lines+A_Line_Count;
    Words := Words+A_Word_Count;
  end loop;

  T1 := Ada.Calendar.Clock;

  Ada.Text_IO.Put_Line(Natural'Image(Lines)
                       & Natural'Image(Words)
                       & Natural'Image(Total));
  Ada.Text_IO.Put_Line("took" & Duration'Image(T1 - T0));
end Cwt;



^ permalink raw reply	[relevance 5%]

* Re: Ada bench : word frequency
  @ 2005-03-24  1:24  5%       ` Marius Amado Alves
  0 siblings, 0 replies; 115+ results
From: Marius Amado Alves @ 2005-03-24  1:24 UTC (permalink / raw)
  To: comp.lang.ada

Program fixed. Zero differences with the reference result.

It's two times slower than the GCC C benchmark :-(

(CPU times (user+sys) on my iBook for n=25 repetitions of the input 
file: C => 0.75, Ada => 1.45)

However that's already enough to put Ada on the 7th place, after OCaml 
and before Eiffel :-)

Program follows.

with Ada.Characters.Handling;
with Ada.Characters.Latin_1;
with Ada.Command_Line;
with Ada.Streams;
with Ada.Streams.Stream_IO;
with Ada.Strings.Fixed;
with Ada.Text_IO;
with Ada.Text_IO.Text_Streams;

procedure Word_Frequency is

    use Ada.Characters.Handling;
    use Ada.Characters.Latin_1;
    use Ada.Command_Line;
    use Ada.Streams;
    use Ada.Streams.Stream_IO;
    use Ada.Text_IO;
    use Ada.Text_IO.Text_Streams;

    Buffer : Stream_Element_Array (1 .. 4096);
    Input_Stream : Ada.Text_IO.Text_Streams.Stream_Access
      := Ada.Text_IO.Text_Streams.Stream (Current_Input);
    N : Stream_Element_Offset;
    Is_Separator : array (Stream_Element) of Boolean :=
      (Character'Pos ('A') .. Character'Pos ('Z') |
       Character'Pos ('a') .. Character'Pos ('z') => False,
       others => True);

    -- N-ary tree of word counts
    -- used to increment the counts in one pass of the input file
    -- branches on the letter
    -- carries the count
    -- very fast
    -- but very space consuming

    subtype Letter is Stream_Element range
      Character'Pos ('a') .. Character'Pos ('z');
    type Word is array (Positive range <>) of Letter;
    type Tree;
    type Tree_Ptr is access Tree;
    type Node is
       record
          Count : Natural := 0;
          Subtree : Tree_Ptr := null;
       end record;
    type Tree is array (Letter) of Node;

    procedure Inc (X : in out Integer) is begin X := X + 1; end;
    procedure Dec (X : in out Integer) is begin X := X - 1; end;

    procedure Inc_Word (Parent : Tree_Ptr; Descendents : Word) is
    begin
       if Descendents'Length > 0 then
          declare
             Child_Index : Positive := Descendents'First;
             Child : Letter renames Descendents (Child_Index);
          begin
             if Descendents'Length = 1 then
                Inc (Parent (Child).Count);
             else
                if Parent (Child).Subtree = null then
                   Parent (Child).Subtree := new Tree;
                end if;
                Inc_Word
                  (Parent (Child).Subtree,
                   Descendents (Child_Index + 1 .. Descendents'Last));
             end if;
          end;
       end if;
    end;

    -- Binary tree of word counts
    -- used for sorting the result by the count (frequency)
    -- branches on the word count
    -- carries the word form

    type Form_Ptr is access Word;
    type Binary_Tree;
    type Binary_Tree_Ptr is access Binary_Tree;
    type Binary_Tree is
       record
          Form : Form_Ptr;
          Count : Natural;
          Left, Right : Binary_Tree_Ptr;
       end record;

    procedure Add_Node (Parent : in out Binary_Tree_Ptr; Form : 
Form_Ptr; Count : Natural) is
    begin
       if Parent = null then
          Parent := new Binary_Tree;
          Parent.Form := Form;
          Parent.Count := Count;
       else
          if Count < Parent.Count then
             Add_Node (Parent.Left, Form, Count);
          else
             Add_Node (Parent.Right, Form, Count);
          end if;
       end if;
    end;

    -- end of binary tree primitives

    Root : Tree_Ptr := new Tree;
    Btree : Binary_Tree_Ptr := null;
    Current_Word : Word (1 .. 1000);
    Current_Word_Length : Natural range 0 .. Current_Word'Last := 0;
    In_Word : Boolean := False;

    procedure Append_To_Word (E : Letter) is
    begin
       Inc (Current_Word_Length);
       Current_Word (Current_Word_Length) := E;
       In_Word := True;
    end;

    procedure End_Word is
    begin
       if Current_Word_Length > 0 then
          Inc_Word (Root, Current_Word (1 .. Current_Word_Length));
       end if;
       Current_Word_Length := 0;
       In_Word := False;
    end;

    To_Lower : array (Stream_Element) of Letter;

    procedure Initialise_To_Lower_Map is
       D : Integer := Character'Pos ('a') - Character'Pos ('A');
    begin
       for I in Character'Pos ('a') .. Character'Pos ('z') loop
          To_Lower (Stream_Element (I)) := Letter (I);
          To_Lower (Stream_Element (I - D)) := Letter (I);
       end loop;
    end;

    procedure Process (S : Stream_Element_Array) is
    begin
       for I in S'Range loop
          if Is_Separator (S (I)) then
             if In_Word then End_Word; end if;
          else
             Append_To_Word (To_Lower (S (I)));
          end if;
       end loop;
    end;

    procedure Populate_Btree (Ntree : Tree_Ptr) is
    begin
       Inc (Current_Word_Length);
       for I in Letter'Range loop
          Current_Word (Current_Word_Length) := I;
          if Ntree (I).Count > 0 then
             Add_Node
                (Btree,
                 Form => new Word'(Current_Word (1 .. 
Current_Word_Length)),
                 Count => Ntree (I).Count);
          end if;
          if Ntree (I).Subtree /= null then
             Populate_Btree (Ntree (I).Subtree);
          end if;
       end loop;
       Dec (Current_Word_Length);
    end;

    procedure Populate_Btree is
    begin
       Current_Word_Length := 0;
       Populate_Btree (Root);
    end;

    function To_String (X : Form_Ptr) return String is
       S : String (X'Range);
    begin
       for I in X'Range loop
          S (I) := Character'Val (X (I));
       end loop;
       return S;
    end;

    subtype String7 is String (1 .. 7);

    function Img7 (X : Natural) return String7 is
       S : String := Natural'Image (X);
    begin
       return String' (1 .. 8 - S'Length => ' ') & S (2 .. S'Last);
    end;

    procedure Dump_Btree (X : Binary_Tree_Ptr := Btree) is
    begin
       if X /= null then
          Dump_Btree (X.Right);
          Ada.Text_IO.Put_Line
            (Img7 (X.Count) & " " & To_String (X.Form));
          Dump_Btree (X.Left);
       end if;
    end;

begin
    Initialise_To_Lower_Map;
    loop
       Read (Root_Stream_Type'Class (Input_Stream.all), Buffer, N);
       Process (Buffer (1 .. N));
       exit when N < Buffer'Length;
    end loop;
    if In_Word then End_Word; end if;
    Populate_Btree;
    Dump_Btree;
end;




^ permalink raw reply	[relevance 5%]

* Re: Ada bench : count words
  @ 2005-03-23 21:38  5% ` tmoran
  0 siblings, 0 replies; 115+ results
From: tmoran @ 2005-03-23 21:38 UTC (permalink / raw)


Here's a simple multitasking conversion.  I would appreciate it if someone
with a dual core or hyperthreaded CPU tried it out.  Probably increasing
the buffer size, by lessening task interactions, would speed it up.  With
multiple CPUs, the array
  Counter : array(1 .. 2) of Counters;
might be increased to more tasks, also.

with Ada.Calendar,
     Ada.Streams,
     Ada.Streams.Stream_IO,
     Ada.Text_IO,
     Ada.Text_IO.Text_Streams;
procedure Cwt is
  use Ada.Streams;
  use type Ada.Calendar.Time;

  T0  : Ada.Calendar.Time := Ada.Calendar.Clock;  -- start timing
  T1  : Ada.Calendar.Time;

  subtype Buffer_Type is Stream_Element_Array(1 .. 4096);

  LF      : constant Stream_Element := Character'pos(Ascii.LF);
  Is_Whitespace : constant array(Stream_Element) of Boolean
    := (Character'pos(Ascii.LF) | Character'pos(Ascii.HT)
        | Character'pos(' ') => True, others => False);

  -- "Counters" tasks run independently, asking Data_Source for buffer loads
  -- and tallying word and line counts.  When done, they wait for their
  -- (partial) counts to be harvested, then terminate.

  task type Counters is
    entry Harvest(Line_Count, Word_Count : out Natural);
  end Counters;

  -- Data_Source is the IO task, supplying data as requested to Counters.
  -- Note that Data_Source counts the whitespace->non-white transitions
  -- at the ends of buffers.  Counters' partial counts are added to that.
  -- Data_Source also counts the Total number of characters.

  task Data_Source is
    entry Get(Buffer : out Buffer_Type;
              Last : out Stream_Element_Offset);
  end Data_Source;

  task body Counters is
    Buffer : Buffer_Type;
    Last : Stream_Element_Offset;
    Lines, Words, Total : Natural := 0;
    In_Whitespace : Boolean;
  begin
    loop
      Data_Source.Get(Buffer, Last);
      exit when Last = 0;
      In_Whitespace := Is_Whitespace(Buffer(1));
      for I in 1 .. Last loop
        if Is_Whitespace(Buffer(I)) then
          if Buffer(I) = LF then
            Lines := Lines + 1;
          end if;
          In_Whitespace := True;
        elsif In_Whitespace then
          In_Whitespace := False;
          Words := Words + 1;
        end if;
      end loop;
      exit when Last < Buffer'last;
    end loop;
    accept Harvest(Line_Count, Word_Count : out Natural) do
      Line_Count := Lines;
      Word_Count := Words;
    end;
  end Counters;

  Lines, Words, Total : Natural := 0;

  task body Data_Source is
    Stream  : Ada.Text_IO.Text_Streams.Stream_Access;
    At_End : Boolean := False;
    In_Whitespace : Boolean := True; -- we must count at edges of buffer loads
  begin
    Stream := Ada.Text_IO.Text_Streams.Stream(Ada.Text_IO.Current_Input);
    loop
      select
        accept Get(Buffer : out Buffer_Type;
                   Last : out Stream_Element_Offset) do
          if At_End then Last := 0;
          else
            Ada.Streams.Read(Ada.Streams.Root_Stream_Type'Class(Stream.all),
                             Buffer, Last);
            Total := Total+Integer(Last);
            if Last > 0 then
              if In_Whitespace and not Is_Whitespace(Buffer(1)) then
                Words := Words+1;
              end if;
              In_Whitespace := Is_Whitespace(Buffer(Last));
            end if;
            if Last < Buffer'last then At_End := True;end if;
          end if;
        end;
      or terminate;
      end select;
    end loop;
  end Data_Source;

  A_Line_Count, A_Word_Count : Natural := 0;

  Counter : array(1 .. 2) of Counters;

begin

  for i in Counter'range loop
    Counter(i).Harvest(A_Line_Count, A_Word_Count);
    Lines := Lines+A_Line_Count;
    Words := Words+A_Word_Count;
  end loop;

  T1 := Ada.Calendar.Clock;

  Ada.Text_IO.Put_Line(Natural'Image(Lines)
                       & Natural'Image(Words)
                       & Natural'Image(Total));
  Ada.Text_IO.Put_Line("took" & Duration'Image(T1 - T0));
end Cwt;



^ permalink raw reply	[relevance 5%]

* Ada bench : word frequency
  @ 2005-03-23 20:39  5%   ` Marius Amado Alves
    0 siblings, 1 reply; 115+ results
From: Marius Amado Alves @ 2005-03-23 20:39 UTC (permalink / raw)
  To: comp.lang.ada

Here's a shot at the word frequency benchmark. By my calculations, it 
is as fast as the GCC C benchmark. I did not compare the output with 
the reference output. A line-by-line comparison requires a criterion 
for words with the same frequency, which AFAICT is not documented. 
Also, my current concept of word separator does not include punctuation 
marks. Again, I could not find a reference definition.

The program does not use any external data structures library. It 
includes its own specific structures, an n-ary tree keyed by word form, 
and a binary tree keyed by word frequency. It increments the counts in 
the n-ary tree, then traverses the n-ary tree to populate the binary 
tree (to order by count), then dumps the latter.

with Ada.Characters.Handling;
with Ada.Characters.Latin_1;
with Ada.Command_Line;
with Ada.Streams;
with Ada.Streams.Stream_IO;
with Ada.Strings.Fixed;
with Ada.Text_IO;
with Ada.Text_IO.Text_Streams;

procedure Word_Frequency is

    use Ada.Characters.Handling;
    use Ada.Characters.Latin_1;
    use Ada.Command_Line;
    use Ada.Streams;
    use Ada.Streams.Stream_IO;
    use Ada.Text_IO;
    use Ada.Text_IO.Text_Streams;

    Buffer : Stream_Element_Array (1 .. 4096);
    Input_Stream : Ada.Text_IO.Text_Streams.Stream_Access
      := Ada.Text_IO.Text_Streams.Stream (Current_Input);
    N : Stream_Element_Offset;
    Is_Separator : array (Stream_Element) of Boolean :=
      (0 .. 32 | 127 .. 159 => True, others => False);

    -- N-ary tree of word counts
    -- used to increment the counts in one pass of the input file
    -- branches on the letter
    -- carries the count
    -- very fast
    -- but very space consuming

    subtype Letter is Stream_Element range 0 .. 255;
    type Word is array (Positive range <>) of Letter;
    type Tree;
    type Tree_Ptr is access Tree;
    type Node is
       record
          Count : Natural := 0;
          Subtree : Tree_Ptr := null;
       end record;
    type Tree is array (Letter) of Node;

    procedure Inc (X : in out Integer) is begin X := X + 1; end;
    procedure Dec (X : in out Integer) is begin X := X - 1; end;

    procedure Inc_Word (Parent : Tree_Ptr; Descendents : Word) is
    begin
       if Descendents'Length > 0 then
          declare
             Child_Index : Positive := Descendents'First;
             Child : Letter renames Descendents (Child_Index);
          begin
             if Descendents'Length = 1 then
                Inc (Parent (Child).Count);
             else
                if Parent (Child).Subtree = null then
                   Parent (Child).Subtree := new Tree;
                end if;
                Inc_Word
                  (Parent (Child).Subtree,
                   Descendents (Child_Index + 1 .. Descendents'Last));
             end if;
          end;
       end if;
    end;

    -- Binary tree of word counts
    -- used for sorting the result by the count (frequency)
    -- branches on the word count
    -- carries the word form

    type Form_Ptr is access Word;
    type Binary_Tree;
    type Binary_Tree_Ptr is access Binary_Tree;
    type Binary_Tree is
       record
          Form : Form_Ptr;
          Count : Natural;
          Left, Right : Binary_Tree_Ptr;
       end record;

    procedure Add_Node (Parent : in out Binary_Tree_Ptr; Form : 
Form_Ptr; Count : Natural) is
    begin
       if Parent = null then
          Parent := new Binary_Tree;
          Parent.Form := Form;
          Parent.Count := Count;
       else
          if Count < Parent.Count then
             Add_Node (Parent.Left, Form, Count);
          else
             Add_Node (Parent.Right, Form, Count);
          end if;
       end if;
    end;

    -- end of binary tree primitives

    Root : Tree_Ptr := new Tree;
    Btree : Binary_Tree_Ptr := null;
    Current_Word : Word (1 .. 1000);
    Current_Word_Length : Natural range 0 .. Current_Word'Last := 0;
    In_Word : Boolean := False;

    procedure Append_To_Word (E : Stream_Element) is
    begin
       Inc (Current_Word_Length);
       Current_Word (Current_Word_Length) := E;
       In_Word := True;
    end;

    procedure End_Word is
    begin
       if Current_Word_Length > 0 then
          Inc_Word (Root, Current_Word (1 .. Current_Word_Length));
       end if;
       Current_Word_Length := 0;
       In_Word := False;
    end;

    procedure Process (S : Stream_Element_Array) is
    begin
       for I in S'Range loop
          if Is_Separator (S (I)) then
             if In_Word then End_Word; end if;
          else
             Append_To_Word (S (I));
          end if;
       end loop;
    end;

    procedure Populate_Btree (Ntree : Tree_Ptr) is
    begin
       Inc (Current_Word_Length);
       for I in Letter'Range loop
          Current_Word (Current_Word_Length) := I;
          if Ntree (I).Count > 0 then
             Add_Node
                (Btree,
                 Form => new Word'(Current_Word (1 .. 
Current_Word_Length)),
                 Count => Ntree (I).Count);
          end if;
          if Ntree (I).Subtree /= null then
             Populate_Btree (Ntree (I).Subtree);
          end if;
       end loop;
       Dec (Current_Word_Length);
    end;

    procedure Populate_Btree is
    begin
       Current_Word_Length := 0;
       Populate_Btree (Root);
    end;

    function To_String (X : Form_Ptr) return String is
       S : String (X'Range);
    begin
       for I in X'Range loop
          S (I) := Character'Val (X (I));
       end loop;
       return S;
    end;

    procedure Dump_Btree (X : Binary_Tree_Ptr := Btree) is
    begin
       if X /= null then
          Dump_Btree (X.Right);
          Ada.Text_IO.Put_Line
            (To_String (X.Form) &
             Natural'Image (X.Count));
          Dump_Btree (X.Left);
       end if;
    end;

begin
    loop
       Read (Root_Stream_Type'Class (Input_Stream.all), Buffer, N);
       Process (Buffer (1 .. N));
       exit when N < Buffer'Length;
    end loop;
    if In_Word then End_Word; end if;
    Populate_Btree;
    Dump_Btree;
end;




^ permalink raw reply	[relevance 5%]

* Re: Ada bench : count words
       [not found]                 ` <00b362390273e6c04844dd4ff1885ee0@netcabo.pt>
@ 2005-03-23 15:09  6%               ` Marius Amado Alves
  2005-03-30 16:08  0%                 ` Andre
  0 siblings, 1 reply; 115+ results
From: Marius Amado Alves @ 2005-03-23 15:09 UTC (permalink / raw)
  To: comp.lang.ada

> I'll review this tomorrow on the bus to work (I think your program is 
> separating words at buffer end, and it should not).

Done. Tmoran, sorry, my first sight was wrong, your algorithm is mostly 
fine. Minor reservations:
- special statute given to CR; personally I think all characters 
(control or not) should count to total
- reliance on Stream_Element representing one character; portable 
across all range of environments?

My own program rewritten with Text_Streams attains the same speed as 
yours. The fact that it is structured doesn't hit performance 
significantly. Pragma Inline improves a little bit. Real times (ms) on 
my iBook, for input file repeated 2500 times, all compiled with only 
-O3:
C ........................ 600
Yours, or mine inlined ... 700
Mine not inlined ......... 750

So we should submit yours, or mine inlined. It will put Ada right after 
the Cs w.r.t. speed. W.r.t. executable file size Ada is much bigger. On 
my iBook:
C .......  15k
Mine .... 423k
Yours ... 459k

W.r.t. source code size all are similar. Number of significant 
semicolons (Ada), or semicolons + {} blocks + #includes + #defines (C):
C .............. 27
Yours .......... 33
Mine inlined ... 52

My program follows for reference. It accepts the code for EOL as an 
argument. Default = 10 (LF).

-- The Great Computer Language Shootout
-- http://shootout.alioth.debian.org/
--
-- contributed by Guys De Cla

with Ada.Characters.Handling;
with Ada.Characters.Latin_1;
with Ada.Command_Line;
with Ada.Streams;
with Ada.Streams.Stream_IO;
with Ada.Strings.Fixed;
with Ada.Text_IO;
with Ada.Text_IO.Text_Streams;

procedure Count_Words_Portable is

    use Ada.Characters.Handling;
    use Ada.Characters.Latin_1;
    use Ada.Command_Line;
    use Ada.Streams;
    use Ada.Streams.Stream_IO;
    use Ada.Text_IO;
    use Ada.Text_IO.Text_Streams;

    Buffer : Stream_Element_Array (1 .. 4096);
    Input_Stream : Ada.Text_IO.Text_Streams.Stream_Access
      := Ada.Text_IO.Text_Streams.Stream (Current_Input);
    EOL_Character_Pos : Stream_Element := Character'Pos (LF);
    Lines : Natural := 0;
    Words : Natural := 0;
    Total : Natural := 0;
    In_Word : Boolean := False;
    N : Stream_Element_Offset;
    Is_Separator : array (Stream_Element) of Boolean :=
      (0 .. 32 | 127 .. 159 => True, others => False);

    procedure Begin_Word is
    begin
       Words := Words + 1;
       In_Word := True;
    end;

    procedure End_Word is
    begin
       In_Word := False;
    end;

    procedure End_Line is
    begin
       Lines := Lines + 1;
       End_Word;
    end;

    procedure Count_Words (S : in Stream_Element_Array) is
    begin
       Total := Total + S'Length;
       for I in S'Range loop
          if S (I) = EOL_Character_Pos then
             End_Line;
          else
             if Is_Separator (S (I)) then
                if In_Word then End_Word; end if;
             else
                if not In_Word then Begin_Word; end if;
             end if;
          end if;
       end loop;
    end;

    pragma Inline (Begin_Word, End_Word, End_Line, Count_Words);

begin
    begin
       EOL_Character_Pos := Stream_Element'Value (Argument (1));
    exception
       when Constraint_Error => null;
    end;
    Ada.Text_IO.Put_Line ("EOL =>" & Stream_Element'Image 
(EOL_Character_Pos));

    loop
       Read (Root_Stream_Type'Class (Input_Stream.all), Buffer, N);
       Count_Words (Buffer (1 .. N));
       exit when N < Buffer'Length;
    end loop;

    Ada.Text_IO.Put_Line
      (Natural'Image (Lines) &
       Natural'Image (Words) &
       Natural'Image (Total));
end;




^ permalink raw reply	[relevance 6%]

* Re: Ada bench : count words
  2005-03-22 19:49  6%           ` tmoran
  2005-03-22 21:51  0%             ` Dmitry A. Kazakov
@ 2005-03-22 22:33  0%             ` Marius Amado Alves
       [not found]                 ` <00b362390273e6c04844dd4ff1885ee0@netcabo.pt>
  2 siblings, 0 replies; 115+ results
From: Marius Amado Alves @ 2005-03-22 22:33 UTC (permalink / raw)
  To: comp.lang.ada

On 22 Mar 2005, at 19:49, tmoran@acm.org wrote:

>> - the speed is circa 1/3 of the GCC C version
>> ...
>> The complete program follows.
>
>   I missed the original post with the URL of the benchmark, but this
> appears on my machine to be about 5x as fast (gnatmake -gnato -O2):

Excelent.

> with Ada.Calendar,
>      Ada.Streams,
>      Ada.Streams.Stream_IO,
>      Ada.Text_IO,
>      Ada.Text_IO.Text_Streams;

I'm so stupid! I had forgotten about Text_Streams!
I'll review this tomorrow on the bus to work (I think your program is 
separating words at buffer end, and it should not).




^ permalink raw reply	[relevance 0%]

* Re: Ada bench : count words
  2005-03-22 19:49  6%           ` tmoran
@ 2005-03-22 21:51  0%             ` Dmitry A. Kazakov
  2005-03-22 22:33  0%             ` Marius Amado Alves
       [not found]                 ` <00b362390273e6c04844dd4ff1885ee0@netcabo.pt>
  2 siblings, 0 replies; 115+ results
From: Dmitry A. Kazakov @ 2005-03-22 21:51 UTC (permalink / raw)


On Tue, 22 Mar 2005 13:49:26 -0600, tmoran@acm.org wrote:

>> - the speed is circa 1/3 of the GCC C version
>> ...
>> The complete program follows.
> 
>   I missed the original post with the URL of the benchmark,

I saw two:

http://shootout.alioth.debian.org/great/benchmark.php?test=wc&lang=all&sort=fullcpu,

and

http://dada.perl.it/shootout/wc.html

> but this
> appears on my machine to be about 5x as fast (gnatmake -gnato -O2):
> 
> with Ada.Calendar,
>      Ada.Streams,
>      Ada.Streams.Stream_IO,
>      Ada.Text_IO,
>      Ada.Text_IO.Text_Streams;
> procedure Cw is
>   use Ada.Streams;
>   use type Ada.Calendar.Time;
>   Stream  : Ada.Text_IO.Text_Streams.Stream_Access;
>   Buffer  : Stream_Element_Array(1 .. 4096);
>   Last    : Stream_Element_Offset;
>   Lines, Words, Total : Natural := 0;
>   In_Word : Boolean := False;
>   LF      : constant Stream_Element := Character'pos(Ascii.LF);
>   CR      : constant Stream_Element := Character'pos(Ascii.CR);
>   EOF_Char: constant Stream_Element := 16#1A#;
>   Is_Separator: constant array (Stream_Element) of Boolean
>     := (0 .. 32 | 127 .. 159 => True, others => False);

It seems (from the description) that the separators are HT, SP, LF.
Everything else is a "letter".

>   T0, T1  : Ada.Calendar.Time;
> begin
> 
>   T0 := Ada.Calendar.Clock;

No, they count load time as the run-time to be run as:

for i in 1 2 3 4 5 6 7 8 9 10; do time command done

So better link all static! (:-))

>   Stream := Ada.Text_IO.Text_Streams.Stream(Ada.Text_IO.Current_Input);
>   Through_File:
>   loop
>     Ada.Streams.Read(Ada.Streams.Root_Stream_Type'Class(Stream.all),
>                      Buffer, Last);
>     for I in 1 .. Last loop
>       exit Through_File when Buffer(I) = EOF_Char;
>       Total := Total + 1;
>       if Is_Separator(Buffer(I)) then
>         In_Word := False;
>         if Buffer(I) = LF then -- LF counts toward Total and toward Lines
>           Lines := Lines + 1;
>         elsif Buffer(I) = CR then -- don't count CR as content or as a line
>           Total := Total-1;

Remove this, CR is a letter! (:-))

>         end if;
>       else
>         if not In_Word then
>           Words := Words + 1;
>           In_Word := True;
>         end if;
>       end if;
>     end loop;
>     exit Through_File when Last < Buffer'Last;
>   end loop Through_File;
> 
>   T1 := Ada.Calendar.Clock;
> 
>   Ada.Text_IO.Put_Line(Natural'Image(Lines)
>                        & Natural'Image(Words)
>                        & Natural'Image(Total));
>   Ada.Text_IO.Put_Line("took" & Duration'Image(T1 - T0));
> end Cw;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



^ permalink raw reply	[relevance 0%]

* Re: Ada bench : count words
    @ 2005-03-22 19:49  6%           ` tmoran
  2005-03-22 21:51  0%             ` Dmitry A. Kazakov
                               ` (2 more replies)
  1 sibling, 3 replies; 115+ results
From: tmoran @ 2005-03-22 19:49 UTC (permalink / raw)


> - the speed is circa 1/3 of the GCC C version
> ...
> The complete program follows.

  I missed the original post with the URL of the benchmark, but this
appears on my machine to be about 5x as fast (gnatmake -gnato -O2):

with Ada.Calendar,
     Ada.Streams,
     Ada.Streams.Stream_IO,
     Ada.Text_IO,
     Ada.Text_IO.Text_Streams;
procedure Cw is
  use Ada.Streams;
  use type Ada.Calendar.Time;
  Stream  : Ada.Text_IO.Text_Streams.Stream_Access;
  Buffer  : Stream_Element_Array(1 .. 4096);
  Last    : Stream_Element_Offset;
  Lines, Words, Total : Natural := 0;
  In_Word : Boolean := False;
  LF      : constant Stream_Element := Character'pos(Ascii.LF);
  CR      : constant Stream_Element := Character'pos(Ascii.CR);
  EOF_Char: constant Stream_Element := 16#1A#;
  Is_Separator: constant array (Stream_Element) of Boolean
    := (0 .. 32 | 127 .. 159 => True, others => False);
  T0, T1  : Ada.Calendar.Time;
begin

  T0 := Ada.Calendar.Clock;

  Stream := Ada.Text_IO.Text_Streams.Stream(Ada.Text_IO.Current_Input);
  Through_File:
  loop
    Ada.Streams.Read(Ada.Streams.Root_Stream_Type'Class(Stream.all),
                     Buffer, Last);
    for I in 1 .. Last loop
      exit Through_File when Buffer(I) = EOF_Char;
      Total := Total + 1;
      if Is_Separator(Buffer(I)) then
        In_Word := False;
        if Buffer(I) = LF then -- LF counts toward Total and toward Lines
          Lines := Lines + 1;
        elsif Buffer(I) = CR then -- don't count CR as content or as a line
          Total := Total-1;
        end if;
      else
        if not In_Word then
          Words := Words + 1;
          In_Word := True;
        end if;
      end if;
    end loop;
    exit Through_File when Last < Buffer'Last;
  end loop Through_File;

  T1 := Ada.Calendar.Clock;

  Ada.Text_IO.Put_Line(Natural'Image(Lines)
                       & Natural'Image(Words)
                       & Natural'Image(Total));
  Ada.Text_IO.Put_Line("took" & Duration'Image(T1 - T0));
end Cw;



^ permalink raw reply	[relevance 6%]

* Re: Ada bench : count words
  @ 2005-03-22 12:22  6%             ` Jeff C
  0 siblings, 0 replies; 115+ results
From: Jeff C @ 2005-03-22 12:22 UTC (permalink / raw)


Dmitry A. Kazakov wrote:
> On Tue, 22 Mar 2005 01:16:09 +0000, Marius Amado Alves wrote:
> 
> 
>>I took a shot at the count-words benchmark, a program to count lines, 
>>words and characters. The Ada program currently published there is 
>>broken. My program is correct and portable but:
>>
>>- the speed is circa 1/3 of the GCC C version
>>
>>- it fails to comply with the requirement that the input be taken from 
>>standard input. To implement buffering, I have resorted to 
>>Ada.Direct_IO, which I think cannot apply to standard input.
> 
> 
> Is Text_IO that bad?


It can be. It does a few  things that real programs often do not need to 
do (counting pages) and may not do buffering that is optimal for the job 
here. The problem is of course that it is a requirement to read from 
standard input and if I were running the website I would reject a 
program that does not.

Perhaps this could be done by using ada.text_io.text_streams to get 
access to a stream based on standard input and then use the "Read" 
procedure (v.s. 'read attribute) to get 4k blocks of data (recommended 
chunking size from problem definition). The Read procedure uses an 
"Item" and "Last" approach so you can look for Last to see how much you 
actually read.


Note since Ada 95 came out I hardly ever use direct_io anymore because 
even problems that seem to line up well with direct IO over time degrade 
  as file formats change.

I tend to jump (perhaps to soon) to ada.streams.stream_io approaches and 
or approaches like getting access to text_io streams. Note in this case 
I am not saying that the text_io stream approach will be faster..I dont 
really know..But at least it can be made compliant with the requirements 
of the test.

with Text_IO;
with Ada.Text_IO.Text_Streams;

use Ada.Text_IO.Text_Streams;
use Text_IO;

with Ada.Streams;
use Ada.Streams;

procedure stre_test is


S : Stream_Access := Stream(Standard_Input);

Data : Stream_Element_Array(1 .. 10);
Last : Stream_Element_Offset;
begin

Read(S.all, Data, Last);
Text_IO.Put_Line(Stream_Element_Offset'image(Last));

end stre_test;



^ permalink raw reply	[relevance 6%]

* [Fwd: Re: SEQUENTIA_IO and stdin/stdout]
@ 2003-10-14 14:42  5% Marius Amado Alves
  0 siblings, 0 replies; 115+ results
From: Marius Amado Alves @ 2003-10-14 14:42 UTC (permalink / raw)
  To: comp.lang.ada

[-- Attachment #1: Type: text/plain, Size: 68 bytes --]

[Sorry, reply button habit. Ada-france, please set Reply-To field.]

[-- Attachment #2: Forwarded message - Re: SEQUENTIA_IO and stdin/stdout --]
[-- Type: message/rfc822, Size: 1042 bytes --]

From: Marius Amado Alves <amado.alves@netcabo.pt>
To: Lo Shu <iin@rgdata.ukrtel.net>
Subject: Re: SEQUENTIA_IO and stdin/stdout
Date: Tue, 14 Oct 2003 14:39:26 +0000
Message-ID: <1066142366.24379.84.camel@a213-22-81-194.netcabo.pt>

On Tue, 2003-10-14 at 12:44, Lo Shu wrote:
> I came from C world and brought the question: how I can open stdin or
> stdout as a SEQUENTIAL file?

As an Ada.Sequential_IO file you can't. But you can achieve what I think
you want to using streams:

with Ada.Text_IO;
with Ada.Text_IO.Text_Streams;

procedure Example is
   type Element is new Character;
   use Ada.Text_IO;
begin
   Element'Write (Text_Streams.Stream (Standard_Output), 'A');
end;      

/*
It is perhaps an unfortunate feature of Ada that the standard i/o
channels are hardwired to the Text_IO file type.
*/

^ permalink raw reply	[relevance 5%]

* Re: procedure Create(file : in out File_Type; from : in Stream_Access); ?
  2003-10-01  7:34  5%             ` Jean-Pierre Rosen
@ 2003-10-01 12:32  0%               ` Lutz Donnerhacke
  0 siblings, 0 replies; 115+ results
From: Lutz Donnerhacke @ 2003-10-01 12:32 UTC (permalink / raw)


* Jean-Pierre Rosen wrote:
> So, if I understand correctly, you want a Text_IO.File_Type from
> *any* stream?

Yes, I do.

> Can't you use Ada.Text_IO.Text_Streams.Stream_Access right from the
> start?

No. I have GNAT.Sockets.Socket_Type.



^ permalink raw reply	[relevance 0%]

* Re: procedure Create(file : in out File_Type; from : in Stream_Access); ?
  2003-10-01  0:10  5%           ` sk
@ 2003-10-01  7:34  5%             ` Jean-Pierre Rosen
  2003-10-01 12:32  0%               ` Lutz Donnerhacke
  0 siblings, 1 reply; 115+ results
From: Jean-Pierre Rosen @ 2003-10-01  7:34 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 820 bytes --]


"sk" <noname@myob.com> a �crit dans le message de news:mailman.19.1064966674.25614.comp.lang.ada@ada-france.org...
> rosen@adalog.fr:
>  > With this package, you have both a File and a Stream refering
>  > to the same physical file.You can use that any way you want.
>  > Unless I missed something?
>
> The Gnat 3.15p Ada.Text_Io.Text_Streams provides stream
> access to an Ada.Text_Io.File_Type, not the other way
> around (an Ada.Text_Io.File_Type from an Ada Stream)
> unless I am missing something :-)
>
So, if I understand correctly, you want a Text_IO.File_Type from
*any* stream? Can't you use Ada.Text_IO.Text_Streams.Stream_Access
right from the start?

-- 
---------------------------------------------------------
           J-P. Rosen (rosen@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr





^ permalink raw reply	[relevance 5%]

* Re: procedure Create(file : in out File_Type; from : in Stream_Access); ?
  2003-09-30 14:24  0%         ` Jean-Pierre Rosen
@ 2003-10-01  0:10  5%           ` sk
  2003-10-01  7:34  5%             ` Jean-Pierre Rosen
  0 siblings, 1 reply; 115+ results
From: sk @ 2003-10-01  0:10 UTC (permalink / raw)
  To: comp.lang.ada

rosen@adalog.fr:
 > With this package, you have both a File and a Stream refering
 > to the same physical file.You can use that any way you want.
 > Unless I missed something?

The Gnat 3.15p Ada.Text_Io.Text_Streams provides stream
access to an Ada.Text_Io.File_Type, not the other way
around (an Ada.Text_Io.File_Type from an Ada Stream)
unless I am missing something :-)


-- 
-------------------------------------------------
-- Merge vertically for real address
--
--     s n p @ t . o
--      k i e k c c m
-------------------------------------------------




^ permalink raw reply	[relevance 5%]

* Re: procedure Create(file : in out File_Type; from : in Stream_Access); ?
  2003-09-30 13:27  0%       ` Lutz Donnerhacke
@ 2003-09-30 14:24  0%         ` Jean-Pierre Rosen
  2003-10-01  0:10  5%           ` sk
  0 siblings, 1 reply; 115+ results
From: Jean-Pierre Rosen @ 2003-09-30 14:24 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 514 bytes --]


"Lutz Donnerhacke" <lutz@iks-jena.de> a �crit dans le message de news:slrnbnj15t.nr.lutz@taranis.iks-jena.de...
> > Did you notice Ada.Text_IO.Text_Streams (A.12.2) ?
>
> This is the other way around.
???
With this package, you have both a File and a Stream refering to the same physical file.
You can use that any way you want.
Unless I missed something?

-- 
---------------------------------------------------------
           J-P. Rosen (rosen@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr





^ permalink raw reply	[relevance 0%]

* Re: procedure Create(file : in out File_Type; from : in Stream_Access); ?
  2003-09-30 12:34  4%     ` Jean-Pierre Rosen
@ 2003-09-30 13:27  0%       ` Lutz Donnerhacke
  2003-09-30 14:24  0%         ` Jean-Pierre Rosen
  0 siblings, 1 reply; 115+ results
From: Lutz Donnerhacke @ 2003-09-30 13:27 UTC (permalink / raw)


* Jean-Pierre Rosen wrote:
> "Lutz Donnerhacke" <lutz@iks-jena.de> a �crit dans le message de news:slrnbnh205.dsr.lutz@belenus.iks-jena.de...
>> All my programs does read data sequentially from a file/stream. So I use as
>> file as a stream. That's why, I'd like to handle a Stream with the common
>> Text_IO functions.
>>
> Did you notice Ada.Text_IO.Text_Streams (A.12.2) ?

This is the other way around.



^ permalink raw reply	[relevance 0%]

* Re: procedure Create(file : in out File_Type; from : in Stream_Access); ?
  @ 2003-09-30 12:34  4%     ` Jean-Pierre Rosen
  2003-09-30 13:27  0%       ` Lutz Donnerhacke
  0 siblings, 1 reply; 115+ results
From: Jean-Pierre Rosen @ 2003-09-30 12:34 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 822 bytes --]


"Lutz Donnerhacke" <lutz@iks-jena.de> a �crit dans le message de news:slrnbnh205.dsr.lutz@belenus.iks-jena.de...
> * Stephen Leake wrote:
> > Lutz Donnerhacke <lutz@iks-jena.de> writes:
> >> Knows anybody out there a way to create a File_Type (for Ada.Text_IO) from a
> >> Ada.Streams.Root_Type derivate?
> >
> > I don't see how this would be possible; a stream may not be a file (it
> > may be a socket or just memory, for example).
>
> All my programs does read data sequentially from a file/stream. So I use as
> file as a stream. That's why, I'd like to handle a Stream with the common
> Text_IO functions.
>
Did you notice Ada.Text_IO.Text_Streams (A.12.2) ?

-- 
---------------------------------------------------------
           J-P. Rosen (rosen@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr





^ permalink raw reply	[relevance 4%]

* Re: Ada.Streams.Stream_IO.File_Type
  2003-07-17 15:10  0% ` Ada.Streams.Stream_IO.File_Type Craig Carey
@ 2003-07-17 16:42  0%   ` Nick Roberts
  0 siblings, 0 replies; 115+ results
From: Nick Roberts @ 2003-07-17 16:42 UTC (permalink / raw)


"Craig Carey" <research@ijs.co.nz> wrote in message
news:mt7chvs7heoihdv7a3a6psh5h8v1b46i2i@4ax.com...

> On Tue, 15 Jul 2003 13:30:33 -0500, "David C. Hoos"
> > The package Ada.TextIO.Text_Streams allows one
> > to obtain the stream object corresponding to the
> > standard input -- i.e.:
> >
> > Standard_Input_Stream :
> >    Ada.Text_IO.Text_Streams.Stream_Access :=
> >       Ada.Text_IO.Text_Streams.Stream
> >          (Ada.Text_IO.Standard_Input);
>
> This comment is not on Text_Streams:
> ...
> A fix would be to add this next line to Ada.Streams.Stream_IO:
>
>     function Standard_Input return File_Type;
>
> Anyone know why it is not in there already?

Yes! Because you can use the technique given by David Hoos.

> Portable Ada programs handling piping or CGI I/O may
> need that unless using C (etc.).

If an Ada program which is a client of the Common Gateway Interface (CGI) --
used by various web (HTTP) server programs to allow 'client' programs to
dyamically generate web pages -- implements the interface by directly
interacting with its 'standard input' and 'standard output' (in the Unix
sense), it must be considered essentially non-portable.

Such a program may be portable among Unix-based (maybe POSIX-based)
environments, but generally not otherwise. In this case, the Ada program
might just as well import the appropriate C functions to read or write bytes
directly; I would suggest that in most cases interaction is all text-based
anyway, and it would be easier and better to use Ada.Text_IO (and if the Ada
implementation isn't able to handle line termination correctly, I would say
that's a major problem with the implementation).

For true portability, an Ada program which is intended to be used as a CGI
client should put everything specific to interfacing with the environment
into a package (named 'CGI' perhaps ;-) and I'm fairly sure at least one
such package is available. To port the program to a (significantly
different) environment, this package (only) needs to be reimplemented. This
would provide further advantageous isolation (such as from changes to the
HTTP header that a CGI client program should output).

> ...
> Currently GNAT 3.15's Text_IO.Text_Streams feature
> stops reading, on encountering a ASCII.SUB character
> (= character 10#26#).

That's just a problem with GNAT, isn't it?

> Presumably they don't like the RM's design.

Presumably it's a simple bug in GNAT 3.15. It's quite reasonable (in my
'humble' opinion :-) for text-oriented I/O (except Look_Ahead and
Get_Immediate) to stop on a SUB, but not stream-oriented I/O. The RM permits
this; I think it would often be handy for Ada implementations to provide
options with regard to line, page, and file termination.

--
Nick Roberts
Jabber: debater@charente.de [ICQ: 159718630]






^ permalink raw reply	[relevance 0%]

* Re: Ada.Streams.Stream_IO.File_Type
  @ 2003-07-17 15:10  0% ` Craig Carey
  2003-07-17 16:42  0%   ` Ada.Streams.Stream_IO.File_Type Nick Roberts
  0 siblings, 1 reply; 115+ results
From: Craig Carey @ 2003-07-17 15:10 UTC (permalink / raw)



On Tue, 15 Jul 2003 20:13:37 GMT, tmoran@acm.org wrote:

---------------------------
>Why is this [Ada.Streams.Stream_IO.File_Type] not a descendant of
>  Ada.Finalization.Limited_Controlled?
---------------------------

That would be done to allow no call to Close(). Close might raise errors.
 GNAT's already code has the doubly linked list (in GNAT-'only' package
 System.File_Control_Block).

---

From another thread (mis)titled "Re: Terminating a task"

It was on the 2nd computer language shootout contest:
  http://dada.perl.it/shootout/  (wc example: counting words in binary)

---------------------------
On Tue, 15 Jul 2003 13:30:33 -0500, "David C. Hoos" 
>The package Ada.TextIO.Text_Streams allows one to obtain the stream
> object corresponding to the standard input -- i.e.:
>
>Standard_Input_Stream : Ada.Text_IO.Text_Streams.Stream_Access =
>   Ada.Text_IO.Text_Streams.Stream (Ada.Text_IO.Standard_Input);
---------------------------

This comment is not on Text_Streams:

---------------------------
From: "Randy Brukardt" <randy@rrsoftware.com>
Newsgroups: comp.lang.ada
Subject: Re: Fill string with multiple lines from standard_input
Date: Fri, 16 Aug 2002 21:26:29 -0500

...
Keep in mind that Stream_IO was virtually untested by the ACATS until
recently, and even now the standard has serious problems which can make
the use of Stream_IO non-portable (since compilers pretty much all do
the wrong thing). So even an implementation which passes the ACATS tests
may still have problems in some cases (having to do with writing, [...]
---------------------------

It is a problem with the design rather than the testing. ACT doesn't
 like the design.

A fix would be to add this next line to Ada.Streams.Stream_IO:

    function Standard_Input return File_Type;

Anyone know why it is not in there already?. Portable Ada programs
 handling piping or CGI I/O may need that unless using C (etc.).

I looked for an AI or comment at Ada-Comment, hinting that a fix is
 desired or intended, but found nothing.

Using C's setmode() and read() seems to be a good solution.

--

Currently GNAT 3.15's Text_IO.Text_Streams feature stops reading, on
 encountering a ASCII.SUB character (= character 10#26#). Presumably
 they don't like the RM's design.

Demo code:   % cat data | tr \\032-\\032 " " | wc
----------------------------------
   type Tio is Ada.Text_IO;
   In_Stream   : Tio.Text_Streams.Stream_Access;
   Out_Stream  : Tio.Text_Streams.Stream_Access;
   Input_Chars : Ada.Streams.Stream_Element_Array (1 .. 1024);
   Last        : Ada.Streams.Stream_Element_Offset;
...
      --  Now use the "do a type conversions on a pointer" package:
   In_Stream := Tio.Text_Streams.Stream (Tio.Current_Input);
   Out_Stream := Tio.Text_Streams.Stream (Tio.Current_Output);
      --  Now use the text package to handle binary I/O:
   loop
      Ada.Streams.Read (In_Stream.all, Input_Chars, Last);
      exit when Last = 0;    --  Quit on the first ASCII.SUB character
      Ada.Streams.Write (Out_Stream.all, Input_Chars (1 .. Last));
   end loop;
----------------------------------


AARM A.12.2: Package Text_IO.Text_Streams:
   http://www.adaic.org/standards/95aarm/html/AA-A-12-2.html

AARM 13.13.1: Package Streams:
   http://www.adaic.org/standards/95aarm/html/AA-13-13-1.html

AARM A.12.1: Package Streams.Stream_IO:
   http://www.adaic.org/standards/95aarm/html/AA-A-12-1.html


______

- Craig Carey

How to Cross-Compiled in FreeBSD to/for a x86 Linux target:
 http://www.ijs.co.nz/code/ada95-freebsd-to-linux-cross-compiler.txt






^ permalink raw reply	[relevance 0%]

* Re: Terminating a task
  @ 2003-07-15 18:30  6%         ` David C. Hoos
  0 siblings, 0 replies; 115+ results
From: David C. Hoos @ 2003-07-15 18:30 UTC (permalink / raw)
  To: comp.lang.ada; +Cc: Craig Carey

"Craig Carey" <research@ijs.co.nz> wrote in message
news:5ra8hvkkabsvevc2r0abu4mp71dfochelr@4ax.com...
>
<snip>
> Ada 95 can't read data accurately from the console: (a) Text_IO has an
> undefined behaviour on what bounds lines. The Stream_IO package does not
> let the standard input be specified. GNAT extensions were not used (i.e.
> fread() in Interfaces.C_Streams).

What do you mean by
"Text_IO has an undefined behaviour on what bounds lines."?

The procedures Ada.Text_IO.Get_Line and Ada.Text_IO.Put_Line certainly
know what "bounds lines."

True, the Stream_IO package does not allow the standard input to be
specified,
but that's not the proper package to use for dealing with _text_ streams.

The package Ada.TextIO.Text_Streams allows one to obtain the stream object
corresponding to the standard input -- i.e.:

Standard_Input_Stream : Ada.Text_IO.Text_Streams.Stream_Access =
   Ada.Text_IO.Text_Streams.Stream (Ada.Text_IO.Standard_Input);




^ permalink raw reply	[relevance 6%]

* Re: Can I treat Current_Output as a file of bytes?
  2002-11-05 22:27  0%     ` Ted Dennison
  2002-11-06 23:40  0%       ` Randy Brukardt
@ 2002-11-07  0:44  0%       ` Bj�rn Persson
  1 sibling, 0 replies; 115+ results
From: Bj�rn Persson @ 2002-11-07  0:44 UTC (permalink / raw)


On 5 Nov 2002 14:27:39 -0800
dennison@telepath.com (Ted Dennison) wrote:

> Bj rn Persson <bjorn_persson.spam-is-evil@sverige.nu> wrote in message
>news:<20021105170130.2684e53f.bjorn_persson.spam-is-evil@sverige.nu>...
> > On 5 Nov 2002 06:30:59 -0800
> > dennison@telepath.com (Ted Dennison) wrote:
> > > Supposedly, that's what Ada.Text_IO.Text_Streams is there for (see
> > 
> > Hmm, I didn't try that because I assumed that it would write through the
> > usual Standard_Output, and so the line break would be added anyways, but
> > maybe I should give it a try.
> 
> That's my worry too. Tell us how it works. :-)

It seems to work well for output, but I've run into problems with input.

I want to read as much data as is available, and then process that before
I wait for more. I thought I had solved that with Get_Immediate, but it
turns out that Get_Immediate (or rather some underlying C routine)
translates CR LF to a single LF when running in Windows, and I can't find
any other way to check if input is available. Neither can I push back what
I've read with Get_Immediate to read it again with Character'Read.

(I'm using Gnat 3.14p in Windows and 3.13p in Redhat.)

Bj�rn Persson



^ permalink raw reply	[relevance 0%]

* Re: Can I treat Current_Output as a file of bytes?
  2002-11-05 22:27  0%     ` Ted Dennison
@ 2002-11-06 23:40  0%       ` Randy Brukardt
  2002-11-07  0:44  0%       ` Bj�rn Persson
  1 sibling, 0 replies; 115+ results
From: Randy Brukardt @ 2002-11-06 23:40 UTC (permalink / raw)


Ted Dennison wrote in message
<4519e058.0211051427.48557033@posting.google.com>...
>Bj rn Persson <bjorn_persson.spam-is-evil@sverige.nu> wrote in message
news:<20021105170130.2684e53f.bjorn_persson.spam-is-evil@sverige.nu>...
>> On 5 Nov 2002 06:30:59 -0800
>> dennison@telepath.com (Ted Dennison) wrote:
>> > Supposedly, that's what Ada.Text_IO.Text_Streams is there for (see
>>
>> Hmm, I didn't try that because I assumed that it would write through
the
>> usual Standard_Output, and so the line break would be added anyways,
but
>> maybe I should give it a try.
>
>That's my worry too. Tell us how it works. :-)

I would be very surprised if a compiler implementer went out of their
way to add stuff there that OS does not add. In this case, neither
Windows nor Unix adds any line breaks to standard output, so why would
an Ada compiler? (If you're not using Windows or Unix, your mileage may
vary, but you probably don't have a standard output in the first
place...)

Of course, the ability of compiler implementers to do odd things should
never be underestimated. There is the case of the compiler that raises
Storage_Error for certain null string literals, for instance. So do test
it carefully, but I'd expect it to work.

               Randy Brukardt.





^ permalink raw reply	[relevance 0%]

* Re: Can I treat Current_Output as a file of bytes?
  2002-11-05 16:01  0%   ` Bj�rn Persson
  2002-11-05 18:13  0%     ` Warren W. Gay VE3WWG
@ 2002-11-05 22:27  0%     ` Ted Dennison
  2002-11-06 23:40  0%       ` Randy Brukardt
  2002-11-07  0:44  0%       ` Bj�rn Persson
  1 sibling, 2 replies; 115+ results
From: Ted Dennison @ 2002-11-05 22:27 UTC (permalink / raw)


Bj rn Persson <bjorn_persson.spam-is-evil@sverige.nu> wrote in message news:<20021105170130.2684e53f.bjorn_persson.spam-is-evil@sverige.nu>...
> On 5 Nov 2002 06:30:59 -0800
> dennison@telepath.com (Ted Dennison) wrote:
> > Supposedly, that's what Ada.Text_IO.Text_Streams is there for (see
> 
> Hmm, I didn't try that because I assumed that it would write through the
> usual Standard_Output, and so the line break would be added anyways, but
> maybe I should give it a try.

That's my worry too. Tell us how it works. :-)



^ permalink raw reply	[relevance 0%]

* Re: Can I treat Current_Output as a file of bytes?
  2002-11-05 16:01  0%   ` Bj�rn Persson
@ 2002-11-05 18:13  0%     ` Warren W. Gay VE3WWG
  2002-11-05 22:27  0%     ` Ted Dennison
  1 sibling, 0 replies; 115+ results
From: Warren W. Gay VE3WWG @ 2002-11-05 18:13 UTC (permalink / raw)


Bj�rn Persson wrote:
> On 5 Nov 2002 06:30:59 -0800
> dennison@telepath.com (Ted Dennison) wrote:
> 
>>Bj rn Persson <bjorn_persson.spam-is-evil@sverige.nu> wrote in message
>>news:<20021104233454.2042ef78.bjorn_persson.spam-is-evil@sverige.nu>...
>>
>>>I'm writing a little program that reads from standard in and writes to
>>>standard out, but I'd need to treat them as raw files of bytes or
>>>characters, and Text_IO's line-oriented features get in my way. When
>>
>>Supposedly, that's what Ada.Text_IO.Text_Streams is there for (see
>>A.12.2(6)  - http://www.adaic.org/standards/95lrm/html/RM-A-12-2.html
>>). I've never tried writing binary data to Standard_Output myself
>>though, so I can't say how/if it works.
> 
> 
> Hmm, I didn't try that because I assumed that it would write through the
> usual Standard_Output, and so the line break would be added anyways, but
> maybe I should give it a try.
> 
> Bj�rn Persson

You should also be aware from A.12.2.(7) that "Performing operations on
the stream associated with a text file does not affect the column,
line, or page counts."

-- 
Warren W. Gay VE3WWG
http://home.cogeco.ca/~ve3wwg




^ permalink raw reply	[relevance 0%]

* Re: Can I treat Current_Output as a file of bytes?
  2002-11-05 14:30  4% ` Ted Dennison
@ 2002-11-05 16:01  0%   ` Bj�rn Persson
  2002-11-05 18:13  0%     ` Warren W. Gay VE3WWG
  2002-11-05 22:27  0%     ` Ted Dennison
  0 siblings, 2 replies; 115+ results
From: Bj�rn Persson @ 2002-11-05 16:01 UTC (permalink / raw)


On 5 Nov 2002 06:30:59 -0800
dennison@telepath.com (Ted Dennison) wrote:

> Bj rn Persson <bjorn_persson.spam-is-evil@sverige.nu> wrote in message
>news:<20021104233454.2042ef78.bjorn_persson.spam-is-evil@sverige.nu>...
> > I'm writing a little program that reads from standard in and writes to
> > standard out, but I'd need to treat them as raw files of bytes or
> > characters, and Text_IO's line-oriented features get in my way. When
> 
> Supposedly, that's what Ada.Text_IO.Text_Streams is there for (see
> A.12.2(6)  - http://www.adaic.org/standards/95lrm/html/RM-A-12-2.html
> ). I've never tried writing binary data to Standard_Output myself
> though, so I can't say how/if it works.

Hmm, I didn't try that because I assumed that it would write through the
usual Standard_Output, and so the line break would be added anyways, but
maybe I should give it a try.

Bj�rn Persson



^ permalink raw reply	[relevance 0%]

* Re: Can I treat Current_Output as a file of bytes?
  @ 2002-11-05 14:30  4% ` Ted Dennison
  2002-11-05 16:01  0%   ` Bj�rn Persson
  0 siblings, 1 reply; 115+ results
From: Ted Dennison @ 2002-11-05 14:30 UTC (permalink / raw)


Bj rn Persson <bjorn_persson.spam-is-evil@sverige.nu> wrote in message news:<20021104233454.2042ef78.bjorn_persson.spam-is-evil@sverige.nu>...
> I'm writing a little program that reads from standard in and writes to
> standard out, but I'd need to treat them as raw files of bytes or
> characters, and Text_IO's line-oriented features get in my way. When

Supposedly, that's what Ada.Text_IO.Text_Streams is there for (see
A.12.2(6)  - http://www.adaic.org/standards/95lrm/html/RM-A-12-2.html
). I've never tried writing binary data to Standard_Output myself
though, so I can't say how/if it works.



^ permalink raw reply	[relevance 4%]

* Re: New to Ada..need some help regarding Binary Conversion??
  2002-10-15 17:48  4% ` sk
@ 2002-10-16 11:09  0%   ` Paula
  0 siblings, 0 replies; 115+ results
From: Paula @ 2002-10-16 11:09 UTC (permalink / raw)


sk <noname@myob.com> wrote in message news:<mailman.1034704382.5852.comp.lang.ada@ada.eu.org>...
> Hi,
> 
> Pipes ? 
> 
> -----------------------
>  Test file (hello-txt)
> -----------------------
> Hello (contents of piped test file).
> 
> ------------
>  Ada source 
> ------------
> with Ada.Text_Io;
> 
> procedure Print_Pipe is
> 
>     package TIO renames Ada.Text_Io;
> 
>     Char : Character;
> 
> begin
>     loop
>         -- Explicit mention of "Standard_Input" and
>         -- "Standard_Output" to document ...
> 
>         exit when TIO.End_Of_File (TIO.Standard_Input);
> 
>         TIO.Get (TIO.Standard_Input, Char);
> 
>         TIO.Put (TIO.Standard_Output, Char);
> 
>     end loop;
> 
> end Print_Pipe;
> 
> --------------------------
> -- Command line (Linux) --
> --------------------------
> 
> $ cat hello-txt | print_pipe 
> Hello (contents of piped test file).
> 
> 
> For your particular criteria (16-bit data), define
> your 16-bit data type, use Ada.Text_Io.Text_Streams
> to convert Standard_Input to a stream (or use the 
> Interfaces.C.Streams <<check package name>> directly)
> and do 'Reads or 'Inputs on the stream
> 
>    ...
>    type My_16_Bits is mod 2**16;
> 
> 
>    My_16 : My_16_Bits;
>    ...
> 
>    In_Stream := Stream (TIO.Standard_Input);
> 
>    ...
> 
>    My_Value := My_16_Bits'Read (In_Stream);
>    
>    ...


Hmmm, ok....this looks more promising. I'll try it. Thanks ;-)

Paula



^ permalink raw reply	[relevance 0%]

* Re: New to Ada..need some help regarding Binary Conversion??
  @ 2002-10-15 17:48  4% ` sk
  2002-10-16 11:09  0%   ` Paula
  0 siblings, 1 reply; 115+ results
From: sk @ 2002-10-15 17:48 UTC (permalink / raw)


Hi,

Pipes ? 

-----------------------
 Test file (hello-txt)
-----------------------
Hello (contents of piped test file).

------------
 Ada source 
------------
with Ada.Text_Io;

procedure Print_Pipe is

    package TIO renames Ada.Text_Io;

    Char : Character;

begin
    loop
        -- Explicit mention of "Standard_Input" and
        -- "Standard_Output" to document ...

        exit when TIO.End_Of_File (TIO.Standard_Input);

        TIO.Get (TIO.Standard_Input, Char);

        TIO.Put (TIO.Standard_Output, Char);

    end loop;

end Print_Pipe;

--------------------------
-- Command line (Linux) --
--------------------------

$ cat hello-txt | print_pipe 
Hello (contents of piped test file).


For your particular criteria (16-bit data), define
your 16-bit data type, use Ada.Text_Io.Text_Streams
to convert Standard_Input to a stream (or use the 
Interfaces.C.Streams <<check package name>> directly)
and do 'Reads or 'Inputs on the stream

   ...
   type My_16_Bits is mod 2**16;


   My_16 : My_16_Bits;
   ...

   In_Stream := Stream (TIO.Standard_Input);

   ...

   My_Value := My_16_Bits'Read (In_Stream);
   
   ...

-- 
-------------------------------------
-- Merge vertically for real address
-------------------------------------
s n p @ t . o
 k i e k c c m
-------------------------------------



^ permalink raw reply	[relevance 4%]

* Re: Fill string with multiple lines from standard_input
  2002-08-20 18:26  4%           ` Vincent Smeets
  2002-08-20 19:46  0%             ` tmoran
  2002-08-21 12:50  4%             ` Jean-Pierre Rosen
@ 2002-08-21 19:19  3%             ` Randy Brukardt
  2 siblings, 0 replies; 115+ results
From: Randy Brukardt @ 2002-08-21 19:19 UTC (permalink / raw)


Vincent Smeets wrote in message ...
>
>This will bring be back to my other problem. If I use the streams from
>Ada.Text_IO.Text_Streams I will lose the <CR>s.
>
>I can't use Ada.Streams.Stream_IO either because I can't read from the
>standard input with that package. You can only read from files that are
>opened first by Stream_IO.Open call. I would need the following
function
>like in Text_IO:
>    function Standard_Input
>        return Ada.Streams.Stream_IO.File_Type;


That is exactly what Ada.Text_IO.Text_Streams gives you. (I can't
imagine an implementor doing something else...)

Probably your problem is that the OS is eating the <CR>s from Standard
Input, and Ada never sees them. I would expect that you would find this
behavior with any file type that read from the Standard Input handle.

In the mail handling code I've written, I simply assume that the <CR>s
are where they are supposed to be by the RFCs, and put them back in as
needed. Mail that violates RFCs is almost certainly spam anyway; don't
worry about that causing problems, just dump it.

(Bare <CR>s and <LF>s are prohibited by the mail and MIME RFCs anyway,
no mail should have such characters, and what mail servers do with such
mail is undefined. <CR>s paired with <LF>s can always be inserted [and
should be inserted] if you get any bare line ending characters.)

            Randy Brukardt
            (Working on a spam mail filter for the IMS mail server,
written in Ada.)





>Thanks,
>Vincent
>
>





^ permalink raw reply	[relevance 3%]

* Re: Fill string with multiple lines from standard_input
  2002-08-20 18:26  4%           ` Vincent Smeets
  2002-08-20 19:46  0%             ` tmoran
@ 2002-08-21 12:50  4%             ` Jean-Pierre Rosen
  2002-08-21 19:19  3%             ` Randy Brukardt
  2 siblings, 0 replies; 115+ results
From: Jean-Pierre Rosen @ 2002-08-21 12:50 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 410 bytes --]


"Vincent Smeets" <No@Spam.org> a �crit dans le message news:
aju1tq$qna$07$1@news.t-online.com...
> I can't use Ada.Streams.Stream_IO either because I can't read from the
> standard input with that package.
But you can with Ada.Text_IO.Text_Streams....

--
---------------------------------------------------------
           J-P. Rosen (rosen@adalog.fr)
Visit Adalog's web site at http://www.adalog.fr





^ permalink raw reply	[relevance 4%]

* Re: Fill string with multiple lines from standard_input
  2002-08-20 18:26  4%           ` Vincent Smeets
@ 2002-08-20 19:46  0%             ` tmoran
  2002-08-21 12:50  4%             ` Jean-Pierre Rosen
  2002-08-21 19:19  3%             ` Randy Brukardt
  2 siblings, 0 replies; 115+ results
From: tmoran @ 2002-08-20 19:46 UTC (permalink / raw)


>If I use the streams from Ada.Text_IO.Text_Streams I will lose the <CR>s.
>
>I can't use Ada.Streams.Stream_IO either because I can't read from the
>standard input with that package. You can only read from files that are
  I suspect your problem is that Standard Input is not opened by the
_OS_ in binary mode, but rather in text mode.  You simply can't use
Standard Input for what you want - you'll have to open a file yourself.



^ permalink raw reply	[relevance 0%]

* Re: Fill string with multiple lines from standard_input
  @ 2002-08-20 18:26  4%           ` Vincent Smeets
  2002-08-20 19:46  0%             ` tmoran
                               ` (2 more replies)
  0 siblings, 3 replies; 115+ results
From: Vincent Smeets @ 2002-08-20 18:26 UTC (permalink / raw)



"Stephen Leake" <stephen.a.leake.1@gsfc.nasa.gov> wrote in message
news:uznvh1snf.fsf@gsfc.nasa.gov...
> "Vincent Smeets" <No@Spam.org> writes:
>
> > As a second release, I want to rewrite my program to work line by line.
This
> > way, I will need to preserve more state in between the processing of the
> > lines, but this will too need the <CR>s as they are in the input stream!
>
> What is the advantage of working "line by line"? If it is to reduce
> the memory usage, then a better approach is to define a stream buffer
> size, and handle the end-of-buffer condition appropriately. "lines"
> don't mean much in this kind of application; in fact, as you have
> seen, using Ada.Text_IO to read lines actually breaks the application.

This will bring be back to my other problem. If I use the streams from
Ada.Text_IO.Text_Streams I will lose the <CR>s.

I can't use Ada.Streams.Stream_IO either because I can't read from the
standard input with that package. You can only read from files that are
opened first by Stream_IO.Open call. I would need the following function
like in Text_IO:
    function Standard_Input
        return Ada.Streams.Stream_IO.File_Type;

Thanks,
Vincent





^ permalink raw reply	[relevance 4%]

* Re: Fill string with multiple lines from standard_input
  2002-08-17 10:24  4%         ` Robert Dewar
@ 2002-08-19 13:40  0%           ` Ted Dennison
  0 siblings, 0 replies; 115+ results
From: Ted Dennison @ 2002-08-19 13:40 UTC (permalink / raw)


dewar@gnat.com (Robert Dewar) wrote in message news:<5ee5b646.0208170224.19d9d267@posting.google.com>...
> dennison@telepath.com (Ted Dennison) wrote in message news:<4519e058.0208161130.6c77138c@posting.google.com>...
> 
> > Yeah, but its an Ada.Text_IO.File_Type. Stream_IO can 
> > only deal with files it can open by name itself.
> 
> You are confusing stream input-output and the package Stream_IO, have
> a look at Ada.Text_IO.Text_Streams.
> Seems like you have missed a major and important language
> feature!

err...have a look about 3 posts back. He tried that first, but it was
translating line terminators on him (or at least he said it was...).



^ permalink raw reply	[relevance 0%]

* Re: Fill string with multiple lines from standard_input
  2002-08-16 19:30  4%       ` Ted Dennison
  2002-08-17  2:26  4%         ` Randy Brukardt
@ 2002-08-17 10:24  4%         ` Robert Dewar
  2002-08-19 13:40  0%           ` Ted Dennison
  1 sibling, 1 reply; 115+ results
From: Robert Dewar @ 2002-08-17 10:24 UTC (permalink / raw)


dennison@telepath.com (Ted Dennison) wrote in message news:<4519e058.0208161130.6c77138c@posting.google.com>...

> Yeah, but its an Ada.Text_IO.File_Type. Stream_IO can 
> only deal with files it can open by name itself.

You are confusing stream input-output and the package Stream_IO, have
a look at Ada.Text_IO.Text_Streams.
Seems like you have missed a major and important language
feature!



^ permalink raw reply	[relevance 4%]

* Re: Fill string with multiple lines from standard_input
  2002-08-16 19:30  4%       ` Ted Dennison
@ 2002-08-17  2:26  4%         ` Randy Brukardt
  2002-08-17 10:24  4%         ` Robert Dewar
  1 sibling, 0 replies; 115+ results
From: Randy Brukardt @ 2002-08-17  2:26 UTC (permalink / raw)


Ted Dennison wrote in message
<4519e058.0208161130.6c77138c@posting.google.com>...
>> Standard_Input is a file of sorts.  Check the RM for more details.
>
>Yeah, but its an Ada.Text_IO.File_Type. Stream_IO can only deal with
>files it can open by name itself.


Huh? The point of Ada.Text_IO.Text_Streams is to convert a File_Type
into a Stream.

OIC -- someone is confusing Stream_IO with Streams.

>What we don't have here is a reason why the input processing that
>Ada.Text_IO.Text_Streams is doing to him is a problem. The only reason
>I could think of is that it actually contains data rather than text.
>This may sound a bit cheesy, but its exactly what a lot of Unix
>programs like gunzip do. So the person trying to rewrite Linux in Ada
>might stumble over this issue. :-)


What input processing? I can't quite see why an implementor
(particularly on Unix or Windows) would bother with any special
processing here. The "stream" just does input on the raw handle (taking
into account any buffering that is used) that corresponds to the Text_IO
file. The device itself might be doing some special processing (as in a
terminal or keyboard), but that doesn't extend to a disk file. Doing
something else is more work and much slower -- why would you want to do
that? (Besides the point that it is dubious that it is intended or
allowed.)

Keep in mind that Stream_IO was virtually untested by the ACATS until
recently, and even now the standard has serious problems which can make
the use of Stream_IO non-portable (since compilers pretty much all do
the wrong thing). So even an implementation which passes the ACATS tests
may still have problems in some cases (having to do with writing,
reading is OK).

                    Randy.








^ permalink raw reply	[relevance 4%]

* Re: Fill string with multiple lines from standard_input
  @ 2002-08-16 19:30  4%       ` Ted Dennison
  2002-08-17  2:26  4%         ` Randy Brukardt
  2002-08-17 10:24  4%         ` Robert Dewar
  0 siblings, 2 replies; 115+ results
From: Ted Dennison @ 2002-08-16 19:30 UTC (permalink / raw)


"chris.danx" <spamoff.danx@ntlworld.com> wrote in message news:<emV69.1927$U06.25552@newsfep3-gui.server.ntli.net>...
> Vincent Smeets wrote:
> 
> > I think that Stream_IO won't do any input processing, but with Stream_IO, I
> > can only read from a file, not from Standard_Input!
> 
> Standard_Input is a file of sorts.  Check the RM for more details.

Yeah, but its an Ada.Text_IO.File_Type. Stream_IO can only deal with
files it can open by name itself.

What we don't have here is a reason why the input processing that
Ada.Text_IO.Text_Streams is doing to him is a problem. The only reason
I could think of is that it actually contains data rather than text.
This may sound a bit cheesy, but its exactly what a lot of Unix
programs like gunzip do. So the person trying to rewrite Linux in Ada
might stumble over this issue. :-)

-- 
T.E.D. 
Home     -  mailto:dennison@telepath.com (Yahoo: Ted_Dennison)
Homepage -  http://www.telepath.com/~dennison/Ted/TED.html



^ permalink raw reply	[relevance 4%]

* Re: Fill string with multiple lines from standard_input
  2002-08-15  2:30  7% ` SteveD
  2002-08-15 18:02  5%   ` Vincent Smeets
@ 2002-08-15 19:07  4%   ` Vincent Smeets
    1 sibling, 1 reply; 115+ results
From: Vincent Smeets @ 2002-08-15 19:07 UTC (permalink / raw)


Hallo,

I have tested your streams and it didn't work! (Win2000 GNAT 3.13p)

I have a file of 253283 bytes (3310 lines with <CR><LF>). I start my program
with:
    prog <file
and I read 249873 bytes in my buffer. That is exactly 3310 bytes less than
the input file. There is probably some input processing that will leave out
the <CR>. How can I also read the <CR>?

I think that Stream_IO won't do any input processing, but with Stream_IO, I
can only read from a file, not from Standard_Input!

Thanks for any help.

"SteveD" <nospam_steved94@attbi.com> wrote in message
news:bnE69.29717$Zl2.6800@sccrnsc02...
>
> "Vincent Smeets" <No@Spam.org> wrote in message
> news:ajebhb$ndl$01$1@news.t-online.com...
> > Is the a nice Ada95 way to do this?
> >
> Try this:
>
> with Ada.Text_Io.Text_Streams;
> with Ada.Streams;
> procedure TestRead is
>
>   in_stream   : Ada.Text_Io.Text_Streams.Stream_Access;
>   out_stream  : Ada.Text_Io.Text_Streams.Stream_Access;
>   input_chars : Ada.Streams.Stream_Element_Array( 1 .. 1024 );
>   last        : Ada.Streams.Stream_Element_Offset;
> begin
>   in_stream :=
Ada.Text_Io.Text_Streams.Stream( Ada.Text_Io.Current_Input );
>   out_stream := Ada.Text_Io.Text_Streams.Stream(
> Ada.Text_Io.Current_Output );
>   Ada.Streams.Read( in_Stream.ALL, input_chars, last );
>   Ada.Streams.Write( out_Stream.ALL, input_chars(1 .. last ) );
> end TestRead;
>
> BTW: There is nothing that says a stream element will correspond to a
> character, but in practice I think it will be.
>
> SteveD
>
>
>




^ permalink raw reply	[relevance 4%]

* Re: Fill string with multiple lines from standard_input
  2002-08-15  2:30  7% ` SteveD
@ 2002-08-15 18:02  5%   ` Vincent Smeets
  2002-08-15 19:07  4%   ` Vincent Smeets
  1 sibling, 0 replies; 115+ results
From: Vincent Smeets @ 2002-08-15 18:02 UTC (permalink / raw)


Thanks,

This will give me a Stream_Element_Array. Is it possible to read it directly
in a String or do I have to convert every element to a character in a
string?

Vincent

"SteveD" <nospam_steved94@attbi.com> wrote in message
news:bnE69.29717$Zl2.6800@sccrnsc02...
>
> "Vincent Smeets" <No@Spam.org> wrote in message
> news:ajebhb$ndl$01$1@news.t-online.com...
> > Is the a nice Ada95 way to do this?
> >
> Try this:
>
> with Ada.Text_Io.Text_Streams;
> with Ada.Streams;
> procedure TestRead is
>
>   in_stream   : Ada.Text_Io.Text_Streams.Stream_Access;
>   out_stream  : Ada.Text_Io.Text_Streams.Stream_Access;
>   input_chars : Ada.Streams.Stream_Element_Array( 1 .. 1024 );
>   last        : Ada.Streams.Stream_Element_Offset;
> begin
>   in_stream :=
Ada.Text_Io.Text_Streams.Stream( Ada.Text_Io.Current_Input );
>   out_stream := Ada.Text_Io.Text_Streams.Stream(
> Ada.Text_Io.Current_Output );
>   Ada.Streams.Read( in_Stream.ALL, input_chars, last );
>   Ada.Streams.Write( out_Stream.ALL, input_chars(1 .. last ) );
> end TestRead;
>
> BTW: There is nothing that says a stream element will correspond to a
> character, but in practice I think it will be.
>
> SteveD
>
>
>




^ permalink raw reply	[relevance 5%]

* Re: Fill string with multiple lines from standard_input
    @ 2002-08-15  2:30  7% ` SteveD
  2002-08-15 18:02  5%   ` Vincent Smeets
  2002-08-15 19:07  4%   ` Vincent Smeets
  1 sibling, 2 replies; 115+ results
From: SteveD @ 2002-08-15  2:30 UTC (permalink / raw)



"Vincent Smeets" <No@Spam.org> wrote in message
news:ajebhb$ndl$01$1@news.t-online.com...
> Is the a nice Ada95 way to do this?
>
Try this:

with Ada.Text_Io.Text_Streams;
with Ada.Streams;
procedure TestRead is

  in_stream   : Ada.Text_Io.Text_Streams.Stream_Access;
  out_stream  : Ada.Text_Io.Text_Streams.Stream_Access;
  input_chars : Ada.Streams.Stream_Element_Array( 1 .. 1024 );
  last        : Ada.Streams.Stream_Element_Offset;
begin
  in_stream := Ada.Text_Io.Text_Streams.Stream( Ada.Text_Io.Current_Input );
  out_stream := Ada.Text_Io.Text_Streams.Stream(
Ada.Text_Io.Current_Output );
  Ada.Streams.Read( in_Stream.ALL, input_chars, last );
  Ada.Streams.Write( out_Stream.ALL, input_chars(1 .. last ) );
end TestRead;

BTW: There is nothing that says a stream element will correspond to a
character, but in practice I think it will be.

SteveD






^ permalink raw reply	[relevance 7%]

* Re: reading from a file
  @ 2002-02-25 20:46  5%     ` sk
  0 siblings, 0 replies; 115+ results
From: sk @ 2002-02-25 20:46 UTC (permalink / raw)


Hi,

>F is defined as 'text_io.file_type'
>
>i am using Sequentional_io
>
>and the file is open
>
>regards,
>deepie

Use Text_Io functions (Get_Line, Skip_Line etc) on 
"Text_Io.File_Type"

Use Sequential_Io functions on "Sequential_Io.File_Type"

If you really (**REALLY**) need to access text files
sequentially and access sequential files as text, you 
will probably need to use the various Stream abilities.

Ada.Streams;
Ada.Streams.Stream_Io;
Ada.Text_Io.Text_Streams (??? - check actual package name).
...

You also need to watch out for the mode you use to "Open"
a file. Reading from an output file, writing to an input
file, for examples, will bite you.

-------------------------------------
-- Merge vertically for real address
-------------------------------------
s n p @ t . o
 k i e k c c m
------------------------------------



^ permalink raw reply	[relevance 5%]

* Re: implementation question about writing and reading from files
  2001-08-10 14:49  4%     ` Ted Dennison
@ 2001-08-10 15:44  0%       ` Warren W. Gay VE3WWG
  0 siblings, 0 replies; 115+ results
From: Warren W. Gay VE3WWG @ 2001-08-10 15:44 UTC (permalink / raw)


Ted Dennison wrote:
> In article <9kv5rs$6hosn$2@ID-102190.news.dfncis.de>, Francis Crick says...
> >And also, if I want to use a stream for keeping data in memory, how do i
> >that?  How do i instantiate a stream that I can just write to and read from
> >at my leisure?
> 
> The only language-defined streams are in Ada.Streams.Stream_IO,
> Ada.Text_IO.Text_Streams, and Ada.Wide_Text_IO.Text_Streams. I believe they all
> deal with files. If you want to use one to make yourself a buffer, you will have
> to code it yourself by deriving it from Ada.Streams.Root_Stream_Type and
> overriding "Read" and "Write".

If you want a number of examples of streams code, download the AdaVox software
from: http://members.home.net/ve3wwg

I am currently re-vamping AdaVox, because there are a number of design problems
in it, but in the originally released code (see above), you will find
some code that implements a stream buffer. Look for file wc-streams-buffer.ads.

I am sure you can improve upon it, but it will get you started at least.

> 
> >               Also, the data I'm moving is large, and chances are I won't
> >be using it for much else other than writing back to other file streams, so
> >how can i make the reading and writing as fast as possible?  Could I make it
> >read a whole mb in one go as a single unit?
> 
> The easiest way to do that is to unchecked_conversion your data (or better yet,
> a pointer to it) into a Ada.Streams.Stream_Element_Array, then call
> Ada.Streams.Write directly. If you just use the stream attributes, it will
> perform one write for each element, which I've found to be significantly slower
> (even when the target is a memory-based stream).

I think the GNAT implementation is built upon the stdio (C) package, ultimately.
One way to improve performance some, is to increase the buffer size of the 
underlying "file". You'll need to look at the GNAT User Guide to find out how.
You will need to open a C file, and then turn it into an Ada stream.
Maybe someone else can volunteer the details here (I'm too pressed for
time to look it up).

This won't compensate for the procedure(attribute) calls (that Ted referred to), 
but it will make each I/O a larger one.

> A good Ada book should go over the basics of this. Stream use is a complicated
> enough topic that you really ought to have such a resource to learn the basics
> from.

Otherwise, be prepared to look at the streams specs a lot (as I did).
-- 
Warren W. Gay VE3WWG
http://members.home.net/ve3wwg



^ permalink raw reply	[relevance 0%]

* Re: implementation question about writing and reading from files
  @ 2001-08-10 14:49  4%     ` Ted Dennison
  2001-08-10 15:44  0%       ` Warren W. Gay VE3WWG
  0 siblings, 1 reply; 115+ results
From: Ted Dennison @ 2001-08-10 14:49 UTC (permalink / raw)


In article <9kv5rs$6hosn$2@ID-102190.news.dfncis.de>, Francis Crick says...
>And also, if I want to use a stream for keeping data in memory, how do i
>that?  How do i instantiate a stream that I can just write to and read from
>at my leisure? 

The only language-defined streams are in Ada.Streams.Stream_IO,
Ada.Text_IO.Text_Streams, and Ada.Wide_Text_IO.Text_Streams. I believe they all
deal with files. If you want to use one to make yourself a buffer, you will have
to code it yourself by deriving it from Ada.Streams.Root_Stream_Type and
overriding "Read" and "Write". 

>               Also, the data I'm moving is large, and chances are I won't
>be using it for much else other than writing back to other file streams, so
>how can i make the reading and writing as fast as possible?  Could I make it
>read a whole mb in one go as a single unit?

The easiest way to do that is to unchecked_conversion your data (or better yet,
a pointer to it) into a Ada.Streams.Stream_Element_Array, then call
Ada.Streams.Write directly. If you just use the stream attributes, it will
perform one write for each element, which I've found to be significantly slower
(even when the target is a memory-based stream).

A good Ada book should go over the basics of this. Stream use is a complicated
enough topic that you really ought to have such a resource to learn the basics
from.

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



^ permalink raw reply	[relevance 4%]

* Re: Binary Data File - PLEASE HELP
  @ 2001-03-26 14:55  4%   ` Marin David Condic
  0 siblings, 0 replies; 115+ results
From: Marin David Condic @ 2001-03-26 14:55 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1291 bytes --]

Nice bit of flame-bait.

If you're really serious and this is not simply a troll to get someone to do
a homework assignment......

You might try looking at the packages: Ada.Streams (ARM 13.13.1),
Ada.Streams.Stream_IO (ARM A.12.1), Ada.Text_IO.Text_Streams (ARM A.12.2)

Somewhere in those packages lies the answer to all your problems.

MDC
--
Marin David Condic
Senior Software Engineer
Pace Micro Technology Americas    www.pacemicro.com
Enabling the digital revolution
e-Mail:    marin.condic@pacemicro.com
Web:      http://www.mcondic.com/



"Sergio" <alguien@microsoft.com> wrote in message
news:J3Iv6.56705$CL6.1997020@telenews.teleline.es...
> Ada simply cannot do that, sorry.
> Ada sucks.
>
> "Sergio" <alguien@microsoft.com> escribi� en el mensaje
> news:n5su6.24687$CL6.767652@telenews.teleline.es...
> > How could I do this in Ada? Could I do it at a reasonable speed? I don't
> > know how, please help me. Thanks
> >
> > void WorkFile(char *fileName)
> > {
> >     char Buffer[4096];
> >     FILE *handle;
> >
> >     handle = fopen(fileName, "r");
> >     while (!feof(handle))
> >     {
> >         fread(handle, 4096, 1, buffer); /* Read data from file to buffer
> */
> >         Work(Buffer);   /* ... do some work with such data */
> >     }
> > }
> >
> >
> >
>
>





^ permalink raw reply	[relevance 4%]

* Re: GNAT bug or expectations problem with Text_Io.Text_Streams
  2000-09-23  0:00  6% GNAT bug or expectations problem with Text_Io.Text_Streams Jeff Creem
  2000-09-24  0:00  0% ` Preben Randhol
@ 2000-09-24  0:00  0% ` David C. Hoos, Sr.
  1 sibling, 0 replies; 115+ results
From: David C. Hoos, Sr. @ 2000-09-24  0:00 UTC (permalink / raw)


For what it's worth, the observed condition is not what you described.

What _is_ obeserved is that whenever a byte of value 16#0A# is written to
the stream, a byte of value 16#0D# is "helpfully" added _before_ the
16#0A#.  Bytes of value 16#0D# are written without decoration.

That said, the observed behavior seems to me to violate RM A 12.2 (34),
viz.:
"The ability to obtain a stream for a text file allows Current_Input,
Current_Output, and Current_Error to be processed with the functionality
of streams, including the mixing of text and binary input-output, and the
mixing of binary input-output for different types."

"Jeff Creem" <jcreem@atetola.mv.com> wrote in message
news:8qjmp5$189$1@pyrite.mv.net...
> Yes...I know ACT does not take bug reports from here so I will send one
once
> I get some concurrence that this is not a problem with my expectations.
>
> I just recently tried to create a file with a text header and binary data
> after..Looked like one way to do this was using Text_IO and then
> Text_IO.Text_Streams to get a stream access for the 'write calls
> later...While this compiles ok I find that when the 'writes write a byte
> value
> that would have meaning in a text stream I get problems.
>
> For example,  when a byte with 16#0D# is written to the stream it is
> followed
> autmatically by 16#0A#. (Running on Win 95) looks to me like text_io
> is still watching in the background and sees a CR so it sticks in a LF
which
> is
> not what I wanted.
>
> So, given that an alternate approach is to stay in stream_io space the
whole
> time and totally pass on text_io I will probably do that but is this a bug
> or
> an expectations problem. The LRM section on Text_Streams is pretty terse
but
> my feeling after reading this is that the compiler should not do this.
>
> Of course on a Unix box this particular "problem" would probably not
happen
> due to the end of line
> approach there...
>
> Code follows :
> with Ada.Text_Io;
> with Ada.Text_Io.Text_Streams;
>
> procedure Show_Improper_Stream_Use is
>
>   type My_Byte_Type is mod 2**8;
>   for My_Byte_Type'Size use 8;
>
>   Zero_Byte : My_Byte_Type := 0;
>
>   File : Ada.Text_Io.File_Type;
>
> begin
>   Ada.Text_Io.Create(
>     Name => "test_file1",
>     File => File);
>   Ada.Text_Io.Put_Line(
>     File => File,
>     Item => "Hello");
>
>   for My_Byte in My_Byte_Type'range loop
>     My_Byte_Type'Write(Ada.Text_Io.Text_Streams.Stream(File), Zero_Byte);
>     My_Byte_Type'Write(Ada.Text_Io.Text_Streams.Stream(File), Zero_Byte);
>
>
>     My_Byte_Type'Write(Ada.Text_Io.Text_Streams.Stream(File), My_Byte);
>   end loop;
>
>   Ada.Text_Io.Close(File);
>
> end Show_Improper_Stream_Use;
>
>
>
> Hex dump of first part of file:
>
> 00000000   48 65 6C 6C 6F 0D 0A 00  00 00 00 00 01 00 00 02 00 00 03 00 00
> 04 00 00   Hello...............
> 00000024   05 00 00 06 00 00 07 00  00 08 00 00 09 00 00 0D 0A 00 00 0B 00
> 00 0C 00   ....................
>
> ^----I don't think this should be here.
>
>
>
>










^ permalink raw reply	[relevance 0%]

* Re: GNAT bug or expectations problem with Text_Io.Text_Streams
  2000-09-23  0:00  6% GNAT bug or expectations problem with Text_Io.Text_Streams Jeff Creem
@ 2000-09-24  0:00  0% ` Preben Randhol
  2000-09-24  0:00  0%   ` Preben Randhol
  2000-09-24  0:00  0% ` David C. Hoos, Sr.
  1 sibling, 1 reply; 115+ results
From: Preben Randhol @ 2000-09-24  0:00 UTC (permalink / raw)


On Sat, 23 Sep 2000 21:56:42 -0400, Jeff Creem wrote:
>with Ada.Text_Io;
>with Ada.Text_Io.Text_Streams;
>
>procedure Show_Improper_Stream_Use is
>
>  type My_Byte_Type is mod 2**8;
>  for My_Byte_Type'Size use 8;
>
>  Zero_Byte : My_Byte_Type := 0;
>
>  File : Ada.Text_Io.File_Type;
>
>begin
>  Ada.Text_Io.Create(
>    Name => "test_file1",
>    File => File);
>  Ada.Text_Io.Put_Line(
>    File => File,
>    Item => "Hello");
>
>  for My_Byte in My_Byte_Type'range loop
>    My_Byte_Type'Write(Ada.Text_Io.Text_Streams.Stream(File), Zero_Byte);
>    My_Byte_Type'Write(Ada.Text_Io.Text_Streams.Stream(File), Zero_Byte);
>
>
>    My_Byte_Type'Write(Ada.Text_Io.Text_Streams.Stream(File), My_Byte);
                                                               ^^^^^^^
                                                               Not
                                                               declared?

It is probably I that do not understand streams, but I don't understand
why Gnat didn't complain that there is no My_Byte declared? Can somebody
enlighten me on this, please?

-- 
Preben Randhol - Ph.D student - http://www.pvv.org/~randhol/
"i too once thought that when proved wrong that i lost somehow"
                               - i was hoping, alanis morisette




^ permalink raw reply	[relevance 0%]

* Re: GNAT bug or expectations problem with Text_Io.Text_Streams
  2000-09-24  0:00  0% ` Preben Randhol
@ 2000-09-24  0:00  0%   ` Preben Randhol
  0 siblings, 0 replies; 115+ results
From: Preben Randhol @ 2000-09-24  0:00 UTC (permalink / raw)


On 24 Sep 2000 08:43:39 GMT, Preben Randhol wrote:
>>  for My_Byte in My_Byte_Type'range loop
        ^^^^^^^

        Arg I need new glases I think. Sorry I didn't see it here.


>>    My_Byte_Type'Write(Ada.Text_Io.Text_Streams.Stream(File), My_Byte);
>                                                               ^^^^^^^
>                                                               Not
>                                                               declared?

-- 
Preben Randhol - Ph.D student - http://www.pvv.org/~randhol/
"i too once thought that when proved wrong that i lost somehow"
                               - i was hoping, alanis morisette




^ permalink raw reply	[relevance 0%]

* GNAT bug or expectations problem with Text_Io.Text_Streams
@ 2000-09-23  0:00  6% Jeff Creem
  2000-09-24  0:00  0% ` Preben Randhol
  2000-09-24  0:00  0% ` David C. Hoos, Sr.
  0 siblings, 2 replies; 115+ results
From: Jeff Creem @ 2000-09-23  0:00 UTC (permalink / raw)


Yes...I know ACT does not take bug reports from here so I will send one once
I get some concurrence that this is not a problem with my expectations.

I just recently tried to create a file with a text header and binary data
after..Looked like one way to do this was using Text_IO and then
Text_IO.Text_Streams to get a stream access for the 'write calls
later...While this compiles ok I find that when the 'writes write a byte
value
that would have meaning in a text stream I get problems.

For example,  when a byte with 16#0D# is written to the stream it is
followed
autmatically by 16#0A#. (Running on Win 95) looks to me like text_io
is still watching in the background and sees a CR so it sticks in a LF which
is
not what I wanted.

So, given that an alternate approach is to stay in stream_io space the whole
time and totally pass on text_io I will probably do that but is this a bug
or
an expectations problem. The LRM section on Text_Streams is pretty terse but
my feeling after reading this is that the compiler should not do this.

Of course on a Unix box this particular "problem" would probably not happen
due to the end of line
approach there...

Code follows :
with Ada.Text_Io;
with Ada.Text_Io.Text_Streams;

procedure Show_Improper_Stream_Use is

  type My_Byte_Type is mod 2**8;
  for My_Byte_Type'Size use 8;

  Zero_Byte : My_Byte_Type := 0;

  File : Ada.Text_Io.File_Type;

begin
  Ada.Text_Io.Create(
    Name => "test_file1",
    File => File);
  Ada.Text_Io.Put_Line(
    File => File,
    Item => "Hello");

  for My_Byte in My_Byte_Type'range loop
    My_Byte_Type'Write(Ada.Text_Io.Text_Streams.Stream(File), Zero_Byte);
    My_Byte_Type'Write(Ada.Text_Io.Text_Streams.Stream(File), Zero_Byte);


    My_Byte_Type'Write(Ada.Text_Io.Text_Streams.Stream(File), My_Byte);
  end loop;

  Ada.Text_Io.Close(File);

end Show_Improper_Stream_Use;



Hex dump of first part of file:

00000000   48 65 6C 6C 6F 0D 0A 00  00 00 00 00 01 00 00 02 00 00 03 00 00
04 00 00   Hello...............
00000024   05 00 00 06 00 00 07 00  00 08 00 00 09 00 00 0D 0A 00 00 0B 00
00 0C 00   ....................

^----I don't think this should be here.







^ permalink raw reply	[relevance 6%]

* Re: 'Read for pointers
  @ 2000-07-28  0:00  6% ` tmoran
  0 siblings, 0 replies; 115+ results
From: tmoran @ 2000-07-28  0:00 UTC (permalink / raw)


>The value of My_Handle is _not_ copied to Item at the procedure call.
>That only happens for "in" or "in out" parameters, not "out" parameters.

with Ada.Streams,
     Ada.Text_IO,
     Ada.Text_IO.Text_Streams;
procedure Test is
  type Instance is new Integer;

  type Handle is access all Instance;

  procedure Read
    (Stream : access Ada.Streams.Root_Stream_Type'Class;
     Item   : out    Handle
    );
  for Handle'Read use Read;

  procedure Read
    (Stream : access Ada.Streams.Root_Stream_Type'Class;
     Item   : out    Handle
    ) is
  begin
    Item.all := 2;
    Item := new Instance;
    Item.all := 3;
  end Read;

  Dummy_File : Ada.Text_IO.File_Type;

  Dummy_Stream_Access : Ada.Text_IO.Text_Streams.Stream_Access;

  P, Saved_P : Handle;

begin

  Ada.Text_IO.Open(Dummy_File, Ada.Text_IO.In_File, "dummy");
  Dummy_Stream_Access := Ada.Text_IO.Text_Streams.Stream(Dummy_File);

  P := new Instance;
  P.all := 1;
  Saved_P := P;
  Ada.Text_IO.Put_Line("P.all=" & Instance'image(P.all)
                       & " Saved_P.all=" & Instance'image(Saved_P.all));
  Ada.Text_IO.Put_Line("Handle'Read(Dummy_Stream_Access, P);");
  Handle'Read(Dummy_Stream_Access, P);
  Ada.Text_IO.Put_Line("P.all=" & Instance'image(P.all)
                       & " Saved_P.all=" & Instance'image(Saved_P.all));
  Ada.Text_IO.Close(Dummy_File);

end Test;

produces:

P.all= 1 Saved_P.all= 1
Handle'Read(Dummy_Stream_Access, P);
P.all= 3 Saved_P.all= 2

So Handle'Read not only returned a P to a new Instance with P.all=3,
but it also modified the instance previously pointed to by P,
setting Saved_P.all=2.
  Also, if, due to an error, it hadn't done
    Item := new Instance;
then in fact P would still point to the same thing as Saved_P, to
the eventual surprise of the programmer.




^ permalink raw reply	[relevance 6%]

* Re: Type mess in Ada standard library
  1999-07-20  0:00  2% Type mess in Ada standard library Markus Kuhn
  1999-07-20  0:00  0% ` Michael F. Yoder
@ 1999-07-23  0:00  0% ` Tucker Taft
  1 sibling, 0 replies; 115+ results
From: Tucker Taft @ 1999-07-23  0:00 UTC (permalink / raw)


Markus Kuhn wrote:
> 
> Why do the packages
> 
>   Ada.Streams.Stream_IO
> 
> and
> 
>   Ada.Text_IO.Text_Streams
> 
> both have to define their own identical but incompatible
> 
>   type Stream_Access is access all Streams.Root_Stream_Type'Class;
> 
> ???
> 
> This looks like a complete mess to me. If I use both packages (and
> it is certainly not unreasonable to do so!), I have two different types
> for exactly the same purpose. ...

Well, to answer this question narrowly:  These Stream_Access types
are *only* used as the result type of the "Stream" function, which
is designed for passing directly into another subprogram like
T'Input, T'Output, etc.  So at least in this particular case,
there is almost no need to define any variables of the type
Stream_Access (and in fact, it is probably unwise, since the
lifetime of the access values produced is tied to the lifetime
of the File type).

I appreciate your larger concern, but I think in this
case the use of a local Stream_Access type is appropriate.
Perhaps a "NOTE" to indicate the intended use of values of
Stream_Access type might have alleviated your concern.

> Markus
> 
> --
> Markus G. Kuhn, Computer Laboratory, University of Cambridge, UK
> Email: mkuhn at acm.org,  WWW: <http://www.cl.cam.ac.uk/~mgk25/>

-- 
-Tucker Taft   stt@averstar.com   http://www.averstar.com/~stt/
Technical Director, Distributed IT Solutions  (www.averstar.com/tools)
AverStar (formerly Intermetrics, Inc.)   Burlington, MA  USA




^ permalink raw reply	[relevance 0%]

* Type mess in Ada standard library
@ 1999-07-20  0:00  2% Markus Kuhn
  1999-07-20  0:00  0% ` Michael F. Yoder
  1999-07-23  0:00  0% ` Tucker Taft
  0 siblings, 2 replies; 115+ results
From: Markus Kuhn @ 1999-07-20  0:00 UTC (permalink / raw)


Why do the packages

  Ada.Streams.Stream_IO

and

  Ada.Text_IO.Text_Streams

both have to define their own identical but incompatible

  type Stream_Access is access all Streams.Root_Stream_Type'Class;

???

This looks like a complete mess to me. If I use both packages (and
it is certainly not unreasonable to do so!), I have two different types
for exactly the same purpose. This is a classical example of the
needless type inflation under which so many Ada libraries suffer,
just because frequently required types are not defined in the
base packages into which they really should belong, and because
Ada forces library writers to create new types each time something
isn't already available in the standard library. Stream_Access
very clearly should have been defined in Ada.Streams, which is
anyway used by both the above packages.

Did I just missunderstand something here, or is the Ada standard
library really as badly designed at some places as I get the
impression?

This brings me to a more general question:

I have heard the story that derived types (probably the underlying
reason for all these problems) were introduced against the vote of
all other Ada83 design team members by Jean Ichbiah alone. I think
more and more that this was a very big mistake. It causes a lot of headaches
that never show up in other languages without derived types if one
wants to avoid ugly type conversions. The problem is not the existance
of derived types, but that Ada forces programmers to create new incompatible
types at much too many places, e.g. each time you create an access or
array type of something.

For example, some package A defines a type T, and two other independently
developed packages B and C both define arrays over T. Then there is
no way for B and C to come up with a common type for these arrays over
T, unless they know about each other a priory. This severely hinders
code reusability, because programmers who want to move arrays of
T between B and C now constantly have to copy these around, even
though the machine representation is identical and there is no
technical reason at all for doing this copying.

Again, did I just missunderstans something, or is it really that bad?
Is it really not possible to create in a compatible (= not requiring
conversions) way pointers to and arrays of some type T in Ada?
In C, if I create a (T *) type here and a (T *) type there, then they
are automatically the same time and can be assigned to each other without
any problems. How do I do this with pointers and arrays in Ada?

Markus

-- 
Markus G. Kuhn, Computer Laboratory, University of Cambridge, UK
Email: mkuhn at acm.org,  WWW: <http://www.cl.cam.ac.uk/~mgk25/>




^ permalink raw reply	[relevance 2%]

* Re: Type mess in Ada standard library
  1999-07-20  0:00  2% Type mess in Ada standard library Markus Kuhn
@ 1999-07-20  0:00  0% ` Michael F. Yoder
  1999-07-23  0:00  0% ` Tucker Taft
  1 sibling, 0 replies; 115+ results
From: Michael F. Yoder @ 1999-07-20  0:00 UTC (permalink / raw)


Markus Kuhn wrote:
> 
> Why do the packages
> 
>   Ada.Streams.Stream_IO
> 
> and
> 
>   Ada.Text_IO.Text_Streams
> 
> both have to define their own identical but incompatible
> 
>   type Stream_Access is access all Streams.Root_Stream_Type'Class;
> 
> ???

They don't have to, but it is a good idea to do so.

> This looks like a complete mess to me. If I use both packages (and
> it is certainly not unreasonable to do so!), I have two different types
> for exactly the same purpose.

They are only "for the same purpose" if you take a machine-oriented view
of things rather than a problem-oriented one.  The latter is more
appropriate here.  It should be clear that the ability to distinguish a
text-only stream from a general one via strong typing is desirable.  If
you really need to interconvert, you can use P.all'Access.  If this is
unaesthetic, it doesn't bother me, because needing to interconvert
suggests there is a misdesign somewhere.

> This is a classical example of the
> needless type inflation under which so many Ada libraries suffer,
> just because frequently required types are not defined in the
> base packages into which they really should belong, and because
> Ada forces library writers to create new types each time something
> isn't already available in the standard library. Stream_Access
> very clearly should have been defined in Ada.Streams, which is
> anyway used by both the above packages.

The creation of new types is in almost every case a good thing, not a
bad one.  This is what strong typing is all about.  Indeed, strong
typing is nearly the only technique in computer science that deserves to
be called a magic bullet.  I'm not talking about aesthetics; I'm
measuring its value entirely in money, or, if you prefer, labor hours
spent by programmers and testers.

> Did I just missunderstand something here, or is the Ada standard
> library really as badly designed at some places as I get the
> impression?

I suspect you undervalue strong typing to a huge degree.  This is common
in the industry but less common in comp.lang.ada.  :-)

> This brings me to a more general question:
> 
> I have heard the story that derived types (probably the underlying
> reason for all these problems) were introduced against the vote of
> all other Ada83 design team members by Jean Ichbiah alone. I think
> more and more that this was a very big mistake. It causes a lot of headaches
> that never show up in other languages without derived types if one
> wants to avoid ugly type conversions. The problem is not the existance
> of derived types, but that Ada forces programmers to create new incompatible
> types at much too many places, e.g. each time you create an access or
> array type of something.

I'm unwilling to condemn the other team members here, because I don't
know what my opinion would have been knowing only the information
available at the time.  However his judgment was unquestionably
vindicated in this case.

> For example, some package A defines a type T, and two other independently
> developed packages B and C both define arrays over T. Then there is
> no way for B and C to come up with a common type for these arrays over
> T, unless they know about each other a priory. This severely hinders
> code reusability, because programmers who want to move arrays of
> T between B and C now constantly have to copy these around, even
> though the machine representation is identical and there is no
> technical reason at all for doing this copying.

I don't think this is so: you can use a type conversion on an 'out' or
'in out' parameter and a good compiler will pass by reference.  But
different arrays of T may need copying for at least three reasons: (1)
the strides may be different, as in packed vs. unpacked versions; (2) if
the index type is a "gappy" enumeration type with non-consecutive
representation values, two array types may use different indexing
methods; (3) a FORTRAN-style array may order elements differently.

> Again, did I just missunderstans something, or is it really that bad?
> Is it really not possible to create in a compatible (= not requiring
> conversions) way pointers to and arrays of some type T in Ada?
> In C, if I create a (T *) type here and a (T *) type there, then they
> are automatically the same time and can be assigned to each other without
> any problems. How do I do this with pointers and arrays in Ada?

This aspect of C is a very major bug, not a feature.  Try this
experiment: examine available problem notesfiles of various projects and
roughly estimate the number of programmer hours lost due to weak typing
in (say) a month.  Multiply by your estimate of the number of projects
in existence, divided by the number of projects you examined, and then
multiply by 12 to get an estimate of the yearly cost to the industry of
weak typing.  All of that money and time could have been spent on
activities more productive than bug-hunting and bug-fixing.

--
----
Michael Yoder




^ permalink raw reply	[relevance 0%]

* Re: Streams - copying stdin to stdout
  @ 1999-02-10  0:00  5%   ` David Brown
  1999-02-10  0:00  0%     ` rdt
  0 siblings, 1 reply; 115+ results
From: David Brown @ 1999-02-10  0:00 UTC (permalink / raw)


Stephen Leake <Stephen.Leake@gsfc.nasa.gov> writes:

> "Chris Miller" <chrismil@ozemail.com.au> writes:
> 
> > To test the operation of Streams I wrote the following sample
> > program that copies standard input to standard output :
> >
> <snip code>
> >     while not Text_IO.End_Of_File loop
> <snip more code>
> 
> > The problem is that the input file has 5 bytes, which are the characters
> > "test" plus the line feed added by vi, however the output file is only
> > 4 bytes.
> 
> I suspect you want Streams_IO.End_Of_File. Text_IO adds semantics
> about line and page endings, which will get in your way.

Streams_IO.End_Of_File wants a Ada.Stremas.Stream_IO.File_Type
whereas we have either a Ada.Text_IO.Text_Streams.Stream_Access
or Ada.Text_IO.File_Type (or File_Access).

The RM doesn't say much about this.  It looks to me like Text_IO's
End_Of_File would be the one to use, but it doesn't work.

David Brown
dlbrown@acm.org




^ permalink raw reply	[relevance 5%]

* Re: Streams - copying stdin to stdout
  1999-02-10  0:00  5%   ` David Brown
@ 1999-02-10  0:00  0%     ` rdt
  0 siblings, 0 replies; 115+ results
From: rdt @ 1999-02-10  0:00 UTC (permalink / raw)


In article <osk8xqoek7.fsf@dt022n82.san.rr.com>,
  David Brown <dlbrown@acm.org> wrote:
> Stephen Leake <Stephen.Leake@gsfc.nasa.gov> writes:
>
> > "Chris Miller" <chrismil@ozemail.com.au> writes:
> >
> > > To test the operation of Streams I wrote the following sample
> > > program that copies standard input to standard output :
> > >
> > <snip code>
> > >     while not Text_IO.End_Of_File loop
> > <snip more code>
> >
> > > The problem is that the input file has 5 bytes, which are the characters
> > > "test" plus the line feed added by vi, however the output file is only
> > > 4 bytes.
> >
> > I suspect you want Streams_IO.End_Of_File. Text_IO adds semantics
> > about line and page endings, which will get in your way.
>
> Streams_IO.End_Of_File wants a Ada.Stremas.Stream_IO.File_Type
> whereas we have either a Ada.Text_IO.Text_Streams.Stream_Access
> or Ada.Text_IO.File_Type (or File_Access).
>
> The RM doesn't say much about this.  It looks to me like Text_IO's
> End_Of_File would be the one to use, but it doesn't work.

The problem seems to stem from the fact that you are not calling
Text_Io.Close. Sect A10.2(3) of the RM suggests that this is when page/file
terminators are written to text files.

This would be done after the end of the loop before the program terminates.

However, this is not possible with Standard output as you do not have a
variable File_Type.

Regards
Richard Toy

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    




^ permalink raw reply	[relevance 0%]

* Streams - copying stdin to stdout
@ 1999-02-07  0:00  6% Chris Miller
    0 siblings, 1 reply; 115+ results
From: Chris Miller @ 1999-02-07  0:00 UTC (permalink / raw)


To test the operation of Streams I wrote the following sample
program that copies standard input to standard output :


with Text_IO;
with Ada.Text_IO.Text_Streams;
with Interfaces;

procedure params is

    Stdin  : Ada.Text_IO.Text_Streams.Stream_Access;
    Stdout : Ada.Text_IO.Text_Streams.Stream_Access;
    C : Interfaces.Unsigned_8;

begin
    Stdin := Ada.Text_IO.Text_Streams.Stream (
      File => Text_IO.Standard_Input);
    Stdout := Ada.Text_IO.Text_Streams.Stream (
      File => Text_IO.Standard_Output);

    while not Text_IO.End_Of_File loop

      Interfaces.Unsigned_8'Read(Stdin,C);
      Interfaces.Unsigned_8'Write(Stdout,C);

--      Text_io.Put_Line("Value of Char read is " &
Integer'Image(Integer(C)));

    end loop;

end params;

The compiler was the recently released Gnat 3.11p on Debian 2.0 Linux.

Using vi I created a file called "input" containing the single line "test".

The program was compiled with gnatmake and then run as

  ./params < input > output


The output from ls -l was

-rw-rw-r--   1 chrismil chrismil        5 Feb  7 16:54 input
-rw-rw-r--   1 chrismil chrismil        4 Feb  7 18:09 output

The problem is that the input file has 5 bytes, which are the characters
"test" plus the line feed added by vi, however the output file is only
4 bytes.

Printing out the characters with the Text_IO statement confirms that
only 4 bytes were processed.

Is this a bug or am I missing something ?.

How does one copy a file, viewed as an unstructered block of bytes, from
standard input to standard output.

Chris Miller
chrismil@ozemail.com.au
7-Feb-1999









^ permalink raw reply	[relevance 6%]

* Re: Image processing File I/O
  @ 1998-09-24  0:00  2%   ` Michael F Brenner
  0 siblings, 0 replies; 115+ results
From: Michael F Brenner @ 1998-09-24  0:00 UTC (permalink / raw)



In addition to Sequential IO on an 8-bit NUMERICAL byte type in 
the old Ada 83, you could use Stream IO in Ada. Here is a package
that permits you to read and write binary data using Stream IO
in DOS, Windows, and Linux (you need to change the one line
that is marked for the directory separator, forward or backwards
slash).

The package HAND below makes stream IO streams look like ordinary
files by giving them handle numbers you can open, close, read from,
and right to. The two features used in Ada that were not present
in the old Ada 83 are the streams themselves, and 8-bit characters.

Of course, Ada still permits you to do sequential IO on files of
numerical 8-bit bytes, but timing tests on Solaris, DOS, and 
Windows NT (using the DOS compiler) all show that, in these
environments, stream IO is now quicker. (Earlier versions of 
gnat had sequential IO quicker).

-----------------------------------------------------------------

package string_control is
  pragma pure (string_control);

 -- Ordinary String control

 function  caselessly_equal (left, right: character)
                             return boolean;
 function  caselessly_equal (object: string; start, length: natural;
                             pattern: string)
                             return boolean;
 procedure concat           (message:  character;
                             onto: in out string;
                             length:   in out natural);
 procedure concat           (message:  string;
                             onto: in out string;
                             length:   in out natural);

 -- First-missing and first-occurring return 0 when not found.

 function  first_missing    (message: string;
                             pattern: character := ' ')
                             return integer;
 function  first_occurring  (message: string;
                             pattern: character := ' ')
                             return integer;
 function  first_occurring  (message: string;
                             pattern: string)
                             return integer;
 function  image            (message: string)
                             return string;
 procedure in_place_insert  (message: in out string;
                             message_length: in out natural;
                             insertion: string;
                             after: natural);
 function  indent           (message: string)
                             return string;

 function  length           (message: string)
                             return natural;

 -- Last-missing and last-occuring return 0 when not found.

 function  last_missing     (message: string;
                             pattern: character := ' ')
                             return integer;
 function  last_occurring   (message: string;
                             pattern: character := ' ')
                             return integer;
 function  left_trim        (message: string;
                             pattern: character := ' ')
                             return string;
 procedure lower_case       (message: in out string;
                             start: natural;
                             finish: natural);
 function  lower_case       (c: character)
                             return character;
 function  lower_case       (message: string)
                             return string;
 function  right_trim       (message: string;
                             pattern: character := ' ')
                             return string;
 function  quotes_are_good  (message: string;
                             quote:   character := '"')
                             return boolean;
 procedure quotes_inserted  (message: string;
                             result:  in out string; -- 2+2*message'length
                             length:  out natural;
                             quote:   character := '"');
 procedure quotes_removed   (message: string;
                             result:  in out string; -- message'length
                             length:  out natural;
                             quote:   character := '"');
 function  same             (left, right: string)
                             return boolean;
 function  substitute       (base_string: string;
                             search_string: string;
                             replace_string: string)
                             return string;
 procedure upper_case       (message: in out string;
                             start: natural;
                             finish: natural);
 function  upper_case       (c: character)
                             return character;
 function  upper_case       (message: string)
                             return string;

  -- http://email:port/disk:file1/file2/.../filen#anchor?arg1?arg2?...?argk
  --
  -- @ Separators (://, :, /, #, ?)
  -- @ Words (protocol, email, port, disk, file, anchor, arg)
  -- @ Nonquoted words may contain alphanumerics, ~, _, !, @, -, and periods.
  -- @ Quoted words may contain anything, doubling the quotes

  procedure url_break_apart (url: string;
                             protocol_start:  out natural;
                             protocol_finish: out natural;
                             internet_start:  out natural;
                             internet_finish: out natural;
                             port_start:      out natural;
                             port_finish:     out natural;
                             disk_start:      out natural;
                             disk_finish:     out natural;
                             file_start:      out natural;
                             file_finish:     out natural;
                             anchor_start:    out natural;
                             anchor_finish:   out natural;
                             args_start:      out natural;
                             args_finish:     out natural);

  -- Lexical classes are sets of characters, here represented as bits.

  type classes is array(character) of boolean;
  pragma pack (classes);

  small_letter_class: constant classes :=
    (character'first .. character'val (96) => false,
     'a' .. 'z' => true,
     '{' .. character'last => false);

  capital_letter_class: constant classes :=
    (character'first .. '@' => false,
     'A' .. 'Z' => true,
     '[' .. character'last => false);

  alphabetic_class: constant classes :=
    (character'first .. '@' => false,
     'A' .. 'Z' => true,
     '[' .. character'val (96) => false,
     'a' .. 'z' => true,
     '{' .. character'last => false);

  digit_class: constant classes :=
    (character'first .. '/' => false,
     '0'..'9' => true,
     ':'..character'last => false);

  sign_class: constant classes :=
    (character'first .. character'pred ('+') => false,
     '+' => true,
     character'succ('+')..character'pred('-') => false,
     '-' => true,
     character'succ('-').. character'last => false);

  digit_or_sign_class: constant classes :=
    (character'first .. character'pred ('+') => false,
     '+' => true,
     character'succ('+')..character'pred('-') => false,
     '-' => true,
     character'succ('-')..character'pred('0') => false,
     '0'..'9' => true,
     character'succ('9')..character'last => false);



  underline_class: constant classes :=
    (character'first .. '^' => false,
     '_' => true,
     character'val (96) ..character'last => false);

  alphanumeric_class: constant classes :=
    (character'first .. '@' => false,
     'A' .. 'Z' => true,
     '[' .. '^' => false,
     '_' => true,
     character'val (96) => false,
     'a' .. 'z' => true,
     '{' .. character'last => false);

  null_class: constant classes := (others => false);

  -- The MATCH method searches for a character class in the MESSAGE,
  -- returning the column in which the pattern was found,
  -- otherwise returning zero.

  type recognitions is record
    RSTART, RLENGTH: natural;
  end record;

  function match (message: string; class: classes) return recognitions;

end string_control;


package body string_control is

 function  caselessly_equal (left, right: character) return boolean is
 begin
   return
     left=right or else
     (left in 'A'..'Z' and then right=character'val(character'pos(left)+32))
     or else
     (left in 'a'..'z' and then right=character'val(character'pos(left)-32));
 end caselessly_equal;

 function  caselessly_equal (object: string; start, length: natural;
                             pattern: string) return boolean is
 begin
   if length /= pattern'length then return FALSE;
   else
     for i in 1..length loop
       if not caselessly_equal (object  (start         + i - 1),
                                pattern (pattern'first + i - 1)) then
          return FALSE;
       end if;
     end loop;
   end if;
   return TRUE;
 end caselessly_equal;

 procedure concat (message:  character;
                   onto: in out string;
                   length:   in out natural) is
   concat_too_long: exception;
 begin
   if length + 1 > onto'length then
     raise concat_too_long;
   end if;
   onto (length + 1) := message;
   length := length + 1;
 end concat;

 procedure concat (message:  string;
                   onto: in out string;
                   length:   in out natural) is
   concat_too_long: exception;
 begin
   if length + message'length > onto'length then
     raise concat_too_long;
   end if;
   onto (length + 1 .. length + message'length) := message;
   length := length + message'length;
 end concat;

 function first_missing (message: string;
                         pattern: character := ' ') return integer is
 begin
   for i in message'range loop
     if message(i) /= pattern then
       return i;
     end if;                -- message (message'first..i) are patterns.
   end loop;
   return 0;                -- Returns the first column without PATTERN.
 end first_missing;

 function first_occurring (message: string;
                           pattern: character := ' ') return integer is
 begin
   for i in message'range loop
     if message(i)  = pattern then
       return i;            -- message contains the pattern
     end if;                -- message (message'first..i) contains no pattern
   end loop;
   return 0;                -- message contains no pattern
 end first_occurring;

 function first_occurring (message: string; pattern: string)
                           return integer is
   upto: natural := message'first;
   last: integer := message'last + 1 - pattern'length;
   in_first_occuring_the_pattern_is_null: exception;
   RSTART:  natural := 0;
 begin
   RSTART := 0;

   if pattern="" then
      raise in_first_occuring_the_pattern_is_null;
   end if;

   loop
     exit when upto>last;

     if message(upto..upto+pattern'length-1)=pattern then
       RSTART := upto;
       return RSTART;
     end if;

     upto := upto + 1;
   end loop;
   return 0;
 end first_occurring;

 function image (message: string) return string is
   hold: string (1..message'length) := message;
 begin
   return hold;
 end image;

 procedure in_place_insert (message: in out string;
                            message_length: in out natural;
                            insertion: string;
                            after: natural) is
   string_control_in_place_insert_ml_plus_il_gt_ml: exception;
 begin
   if message_length + insertion'length > message'length then
     raise string_control_in_place_insert_ml_plus_il_gt_ml;
   end if;
   message(insertion'length + 1 + after .. message_length+insertion'length) :=
     message(after+1..message_length);
   message(after+1..after+insertion'length) := insertion;
   message_length := message_length + insertion'length;
 end in_place_insert;

 function indent(message: string) return string is
 begin
   return (1..message'length + 1 => ' ');
 end indent;

 function last_missing (message: string;
                        pattern: character := ' ') return integer is
 begin
   for i in reverse message'range loop
     if message(i) /= pattern then
       return i;
     end if;                -- message (i..message'last) are patterns.
   end loop;
   return 0;                -- Returns the last column without PATTERN.
 end last_missing;

 function last_occurring (message: string;
                          pattern: character := ' ') return integer is
 begin
   for i in reverse message'range loop
     if message (i) = pattern then
       return i;
     end if;                -- message (i..message'last) contains no pattern
   end loop;
   return 0;                -- Returns the last column with PATTERN.
 end last_occurring;

 function left_trim (message: string;
                     pattern: character := ' ') return string is
   left_trim_last: constant natural := first_missing (message, pattern);
 begin
   if left_trim_last = 0 then
     return ""; -- blank not found at all means null string
   else
     return message (left_trim_last .. message'last);
   end if;
 end left_trim;

 function length (message: string) return natural is
 begin
   return message'length;
 end length;

 function lower_case (c: character) return character is
 begin
   if c in 'A'..'Z' then
     return character'val (character'pos (c) + 32);
   end if;
   return c;
 end lower_case;

 procedure lower_case (message: in out string;
                       start: natural; finish: natural) is
 begin
   for i in start..finish loop
     if message (i) in 'A'..'Z' then
       message (i) := character'val (character'pos (message (i)) + 32);
     end if;
   end loop;
 end lower_case;

 function lower_case (message: string) return string is
   hold_message: string (1..message'length) := message;
   ch:           character;
   offset: constant := character'pos ('a') - character'pos ('A');
 begin
   for c in hold_message'range loop
     ch := hold_message (c);
     if ch in 'A'..'Z' then
       hold_message (c) := character'val (character'pos (ch) + offset);
     end if;            -- MESSAGE (FIRST..C) is in lower_case.
   end loop;
   return hold_message; -- MESSAGE is in lower_case.
 end lower_case;

 function match (message: string; class: classes) return recognitions is
   recognition: recognitions;
   RSTART:  natural renames recognition.RSTART;
   RLENGTH: natural renames recognition.RLENGTH;
   upto: natural := message'first;
 begin
   RSTART := 0;
   loop
      exit when upto > message'last;
      exit when class (message (upto)) ;
      upto := upto + 1;
   end loop;
   if upto > message'last then
     return (0, 0);
   else
     RSTART := upto;
   end if;
   loop
     exit when upto > message'last;
     exit when not class (message (upto));
     upto := upto + 1;
   end loop;
   RLENGTH := upto - RSTART;
   return recognition;
 end match;

 function  quotes_are_good  (message: string;
                             quote:   character := '"')
                             return boolean is
   input: natural := message'first + 1;
 begin
   if message'length<2 or else
      message(message'first)/=quote or else
      message(message'last) /=quote then
     return false;
   end if;
   loop
     exit when input >= message'length;
     if message(input)/='"' then
       input:=input+1;
     elsif message(input+1)/='"' then
       return false;
     elsif input=message'length-1 then
       return false;
     else
       input:=input+2;
     end if;
   end loop;
   return true;
 end quotes_are_good;

 procedure quotes_inserted  (message: string;
                             result:  in out string; -- 2+2*message'length
                             length:  out natural;
                             quote:   character := '"') is
   output: natural := 0;
 begin
   concat (quote, result, output);
   for input in message'range loop
     if message(input) = quote then
       concat (quote, result, output);
       concat (quote, result, output);
     else
       concat (message(input), result, output);
     end if;
   end loop;
   concat (quote, result, output);
   length := output;
 end quotes_inserted;

 procedure quotes_removed   (message: string;
                             result:  in out string; -- message'length
                             length:  out natural;
                             quote:   character := '"') is
   output: natural := result'first - 1;
   input:  natural := message'first+1;
   quotation_is_not_proper1: exception;
   quotation_is_not_proper2: exception;
 begin
   if    message'length < 2 or else
         message(message'first) /= quote or else
         message(message'last)  /= quote then
     output := message'length;
     result(result'first-1+1..result'first-1+message'length) := message;
   else
     loop
       exit when input>=message'last; -- Since message(message'last)=quote.
       if    message(input)/=quote then
         concat(message(input), result, output);
       elsif message(input+1) /= quote then
         raise quotation_is_not_proper2;
       else -- Two quotes in a row
         concat(message(input), result, output);
         input:=input+1;
       end if;
       input:=input+1;
     end loop;
   end if;
   length := output;
 end quotes_removed;

 function right_trim (message: string;
                      pattern: character := ' ') return string is
   right_trim_last: constant natural := last_missing (message, pattern);
 begin
   return message (message'first .. right_trim_last);
 end right_trim;

 function same (left, right: string)  return boolean is

   -- String Comparison: Semantically, left=right.

 begin
   return left'length = right'length and then
          left = right;
 end same;

 function substitute (base_string: string;
                      search_string: string;
                      replace_string: string)
                      return string is

   location: constant natural := first_occurring (base_string, search_string);
 begin
   if location = 0 then
     return base_string;
   elsif location = 1 then -- this requires the base_string to start at 1
     return replace_string &
            base_string (location+
                         search_string'length..
                         base_string'last);
   elsif location = base_string'last + 1 - search_string'length then
     return base_string (base_string'first..
                         base_string'last-search_string'length) &
            replace_string;
   else
     declare
       left_part: constant string :=
         base_string (base_string'first..location - 1);
     begin
       return left_part &
              replace_string &
              base_string (location + search_string'length ..
                           base_string'last);
     end;
   end if;
 end substitute;

 function upper_case (c: character) return character is
 begin
   if c in 'a'..'z' then
     return character'val (character'pos (c) - 32);
   end if;
   return c;
 end upper_case;

 procedure upper_case (message: in out string;
                       start: natural; finish: natural) is
 begin
   for i in start..finish loop
     if message (i) in 'a'..'z' then
       message (i) := character'val (character'pos (message (i)) - 32);
     end if;
   end loop;
 end upper_case;

 function upper_case (message: string) return string is
   hold_message:          string (1..message'length) := message;
   ch:                    character;
   offset: constant := character'pos ('a') - character'pos ('A');
 begin
   for c in hold_message'range loop
     ch := hold_message (c);
     if ch in 'a'..'z' then
       hold_message (c) := character'val (character'pos (ch) - offset);
     end if;            -- MESSAGE (FIRST..C) is in upper_case.
   end loop;
   return hold_message; -- MESSAGE is in upper case.
 end upper_case;

 procedure get_url_word (message: string;
                         message_start:    natural;
                         message_finish:   natural;
                         word_start:       out natural;
                         word_finish:      out natural;
                         separator_start:  out natural;
                         separator_finish: out natural;
                         separators: string := ":/#?") is

   -- Example 1: ~_.!a.7.@
   -- Example 2: "http://email.address/cgi/bin#query?""what """" quote"""

   c:          character;
   hold_quote: character := ascii.nul;
   upto:       natural   := message_start;
   something_cannot_arise_from_nothing: exception;
   unclosed_quote:                      exception;
   single_quote: constant character    := ''';
   double_quote: constant character    := '"';
   quotes:       constant string(1..2) := single_quote & double_quote;
 begin
   word_start := message_start;
   if message_start  > message_finish or
      message_finish < message'first  or
      message_start  > message'last then
     raise something_cannot_arise_from_nothing;
   end if;

   -- The range message_start..message_finish in contained in MESSAGE.

   if first_occurring (quotes, message (message_start)) /= 0 then
       -- Quote at start.
     hold_quote := message (upto);
     upto := upto + 1;
     loop
       exit when upto > message_finish;
       c := message (upto);
       if c = hold_quote then
         if upto < message_finish and then
            message (upto+1) = hold_quote then
           upto := upto + 1;
         else
           word_finish := upto;
           separator_start := upto+1;
           separator_finish := upto+1;
           return;
         end if;
       end if;
       upto := upto + 1;
     end loop;
     raise unclosed_quote;

   else -- No quote at start.
     loop
       exit when upto > message_finish;
       c := message (upto);
       if first_occurring (separators, c) /= 0 then
         word_finish := upto-1;
         separator_start := upto;
         loop
           exit when upto > message_finish;
           c := message (upto);
           exit when first_occurring (separators, c) = 0;
           upto := upto + 1;
         end loop;
         separator_finish := upto - 1;
         return;
       end if;
       upto := upto + 1;
     end loop;
     word_finish := upto - 1;
     separator_start := upto;
     separator_finish := 0;
   end if;
 end get_url_word;

 procedure url_break_apart (url: string;
                            protocol_start:  out natural;
                            protocol_finish: out natural;
                            internet_start:  out natural;
                            internet_finish: out natural;
                            port_start:      out natural;
                            port_finish:     out natural;
                            disk_start:      out natural;
                            disk_finish:     out natural;
                            file_start:      out natural;
                            file_finish:     out natural;
                            anchor_start:    out natural;
                            anchor_finish:   out natural;
                            args_start:      out natural;
                            args_finish:     out natural) is

   -- Under NT 4.0 the following rules apply:
   --   @ the file part goes up to 255 characters long
   --   @ permit as many periods anywhere in the file
   --   @ forbid characters: question mark and asterisk in a file
   --   @ permit as many blanks in the middle of the file
   --   @ strip off all blanks at the beginning and end of the file's name
   --
   -- This code currently compiles under the first two rules, and
   -- does not enforce the other 3 rules.

   ws, wf, ss, sf: natural;
   sl: integer;
   type separators is (error, colon_slash_slash, colon, other, none);
   separator: separators := error;
   separator_c: character;
   not_a_url: exception;

   procedure ts_get_url_word is -- for unit test only
     type expected_results is array (1..4) of natural;
     ws, wf, ss, sf: natural; -- set by get_word
     message1: constant string (2..19) := "~_.!a.7.@://aaa#b?";
     message2: constant string (1..15) := """what """" quote""";
     ts_get_url_word_failed: exception;
   begin
     get_url_word (message1, 2, 12, ws, wf, ss, sf);
     if    ws /=  2 then raise ts_get_url_word_failed;
     elsif wf /= 10 then raise ts_get_url_word_failed;
     elsif ss /= 11 then raise ts_get_url_word_failed;
     elsif sf /= 12 then raise ts_get_url_word_failed;
     end if;

     get_url_word (message1, 15, 19, ws, wf, ss, sf);
     if ws /= 15 or wf /=16 or ss /= 17 or sf /= 17 then
       raise ts_get_url_word_failed;
     end if;

     get_url_word (message2, 1, 15, ws, wf, ss, sf);
     if    ws /=  1 then raise ts_get_url_word_failed;
     elsif wf /= 15 then raise ts_get_url_word_failed;
     elsif ss /= 16 then raise ts_get_url_word_failed;
     elsif sf /= 16 then raise ts_get_url_word_failed;
     end if;
   end ts_get_url_word;
 begin
   ts_get_url_word;
   protocol_start := 0;
   protocol_finish := 0;
   internet_start := 0;
   internet_finish := 0;
   port_start := 0;
   port_finish := 0;
   disk_start := 0;
   disk_finish := 0;
   file_start := 0;
   file_finish := 0;
   anchor_start := 0;
   anchor_finish := 0;
   args_start := 0;
   args_finish := 0;

   get_url_word (url, url'first, url'last, ws, wf, ss, sf);

   sl:=sf+1-ss;
   if    ss not in url'first..url'last then
     separator := none;
   elsif sl=3 and then url (ss..sf) = "://" then -- it is a full URL
     separator := colon_slash_slash;
   elsif sl=1 and then url (ss) = ':' then -- it is a disk drive
     separator := colon;
   else
     separator := other;
   end if;

   case separator is
     when error => raise not_a_url;
     when colon_slash_slash =>
       protocol_start := ws;
       protocol_finish := wf;
       get_url_word (url, sf+1, url'last, ws, wf, ss, sf);
       internet_start := ws;
       internet_finish := wf;
       if ss in url'range and then ss=sf and then url (ss) = ':' then -- port
         get_url_word (url, sf+1, url'last, ws, wf, ss, sf);
         port_start := ws;
         port_finish := wf;
       end if;
       if ss not in url'range or else ss/=sf or else url (ss) /= '/' then
         return;
       end if;
       get_url_word (url, sf+1, url'last, ws, wf, ss, sf);
     when colon => null;
     when none  => null;
     when other => null;
   end case;

   if ss=sf and ss in url'range then
     separator_c := url (ss);
   else
     separator_c := ascii.lf;
   end if;

   if separator_c = ':' then
     disk_start := ws;
     disk_finish := wf;
     get_url_word (url, sf+1, url'last, ws, wf, ss, sf);
   end if;

   if ss=sf and ss in url'range then
     separator_c := url (ss);
   else
     separator_c := ascii.lf;
   end if;

   file_start := ws;
   loop
     file_finish := wf;
     exit when separator_c /= '/';
     get_url_word (url, sf+1, url'last, ws, wf, ss, sf);
     if ss=sf and ss in url'range then
       separator_c := url (ss);
     else
       separator_c := ascii.lf;
     end if;
   end loop;

   if separator_c = '#' then -- that is, the PRIOR separator
     get_url_word (url, sf+1, url'last, ws, wf, ss, sf);
     if ss=sf and ss in url'range then
       separator_c := url (ss);
     else
       separator_c := ascii.lf;
     end if;
     anchor_start := ws;
     anchor_finish := wf;
   end if;

   if separator_c = '?' then -- that is, the PRIOR separator
     get_url_word (url, sf+1, url'last, ws, wf, ss, sf);
     args_start := ws;
     loop
       get_url_word (url, sf+1, url'last, ws, wf, ss, sf);
       exit when ss /= sf or else ss not in url'range or else url (ss) /= '?';
     end loop;
     args_finish := wf;
   end if;
 end url_break_apart;

end string_control;


package variable_string_control is
   pragma pure (variable_string_control);

-- Variable strings are each allocated to any maximum length, and vary
-- from 0 to that maximum in length. Compiler enforces specifying that
-- maximum length when each variable is declared.

   type variable_strings (size: positive) is limited private;

-- The concatenation of variable strings is an unconstrained string.

  function "&" (left: variable_strings;
                right: variable_strings)
                return string;
  function "&" (left: string;
                right: variable_strings)
                return string;
  function "&" (left: variable_strings;
                right: string)
                return string;

-- When strings agree up to the minimum of their lengths,
-- the shorter string is considered less than the longer string.

  function "<"  (left, right: variable_strings) return boolean;
  function ">"  (left, right: variable_strings) return boolean;
  function "<=" (left, right: variable_strings) return boolean;
  function ">=" (left, right: variable_strings) return boolean;

-- COPY is used to change variable strings.

  procedure copy (source: variable_strings; target: in out variable_strings);
  procedure copy (source: string; target: in out variable_strings);

-- The concatenation method is used to append onto the end of a v string.

  procedure concat(appendage: string;
                   onto: in out variable_strings);
  procedure concat(appendage: variable_strings;
                   onto: in out variable_strings);

-- The ELEMENT method returns a column of a variable string just like
-- array references get columns from ordinary_strings.

  function element (message: variable_strings;
                    col: natural) return character;

-- The IMAGE method returns the string image of a variable string.

  function image (message: variable_strings) return string;

-- The in_place_lower_case function converts
-- alphabetic character from upper to lower
-- case, ignoring all other characters.

  procedure in_place_lower_case (message: in out variable_strings);

-- The in_place_truncate method is a procedure instead of a function,
-- for efficiency.

  procedure in_place_truncate (message: in out variable_strings;
                               ch: character := ' ');

-- The in_place_upper_case function converts
-- alphabetic character from lower to upper
-- case, ignoring all other characters.

  procedure in_place_upper_case (message: in out variable_strings);

-- The LENGTH method returns the length of the variablestring.

  function length (message: variable_strings) return natural;

-- The length_allocated returns the maximum length of the v string.

  function length_allocated (message: variable_strings) return natural;

-- The SAME method is the equality operator for variable strings. To
-- be equal, the two strings must be of the same length, and agree
-- for each of their characters.

  function same (left, right: variable_strings) return boolean;
  function same (left: variable_strings; right: string) return boolean;

-- The set_element method sets a character in a single column
-- of a variable string like array references do for character
-- strings.

  procedure set_element (message: in out variable_strings;
                         col: natural;
                         value:  character);

-- The set_length method truncates a string to a given length or else
-- extends its current length with blanks.

  procedure set_length (message: in out variable_strings;
                        new_length: natural);

-- The SLICE method emulates array slices for variable strings. The
-- SUBSTR method is similar, but based on length instead of final column.
-- The two-argument SUBSTR gets all characters on or after the given column.
-- All of these permit the START argument to take on a value equal to the
-- length of the variable string plus 1, returning the null ordinary_string.

  function slice  (message: variable_strings;
                   start, finish: natural) return string;
  function substr (message: variable_strings;
                   start, length: natural) return string;
  function substr (message: variable_strings;
                   start: natural) return string;
private
  type variable_strings (size: positive) is record
    length: integer := -1; -- Causes arrays of strings to fully Allocate.
    list:   string (1..size);
  end record;
end variable_string_control;                                             


ith string_control;
package body variable_string_control is

 procedure is_okay (message: variable_strings) is
   varstring_never_init: exception;
 begin
   if message.length < 0 then
     raise varstring_never_init;
   end if;
 end is_okay;

 function "&" (left: variable_strings;
               right: variable_strings)
               return string is
   hold: variable_strings (left.length + right.length);
 begin
   is_okay (left);
   is_okay (right);
   copy (left, hold);
   concat (right.list(1..right.length), onto=>hold);
   return hold.list(1..hold.length);
 end "&";

 function "&" (left: string; right: variable_strings) return string is
   hold: variable_strings (left'length + right.length);
 begin
   is_okay (right);
   copy (left, hold);
   concat (right.list(1..right.length), onto=>hold);
   return hold.list(1..hold.length);
 end "&";

 function "&" (left: variable_strings; right: string) return string is
   hold: variable_strings (left.length + right'length);
 begin
   is_okay (left);
   copy (left, hold);
   concat (right, onto=>hold);
   return hold.list(1..hold.length);
 end "&";

 function "<" (left, right: variable_strings) return boolean is
 begin
   is_okay(left);
   is_okay(right);
   if    left.length < right.length then
     return left.list(1..left.length)  <= right.list(1..left.length);
   elsif left.length = right.length then
     return left.list(1..left.length)  <  right.list(1..left.length);
   else -- left.length > right.length
     return left.list(1..right.length) <  right.list(1..right.length);
   end if;
 end "<";

 function ">" (left, right: variable_strings) return boolean is
 begin
   is_okay(left);
   is_okay(right);
   if    left.length < right.length then
     return left.list(1..left.length)  >  right.list(1..left.length);
   elsif left.length = right.length then
     return left.list(1..left.length)  >  right.list(1..left.length);
   else -- left.length > right.length
     return left.list(1..right.length) >= right.list(1..right.length);
   end if;
 end ">";

 function "<=" (left, right: variable_strings) return boolean is
 begin
   return left < right or else left = right;
 end "<=";

 function ">=" (left, right: variable_strings) return boolean is
 begin
   return left > right or else left = right;
 end ">=";

 procedure concat(appendage: string; onto: in out variable_strings) is
   new_length: constant integer := onto.length + appendage'length;
   concat_string_onto_varstring_too_long: exception;
 begin
   is_okay (onto);
   if new_length > onto.size then
     raise concat_string_onto_varstring_too_long;
   end if;
   onto.list(onto.length+1..new_length) := appendage;
   onto.length := new_length;
 end concat;

 procedure concat(appendage: variable_strings;
                  onto: in out variable_strings) is
   new_length: constant integer := onto.length + appendage.length;
   concat_varstring_onto_varstring_too_long: exception;
 begin
   is_okay (onto);
   if new_length > onto.size then
     raise concat_varstring_onto_varstring_too_long;
   end if;
   onto.list(onto.length+1..new_length) :=
     appendage.list(1..appendage.length);
   onto.length := new_length;
 end concat;

 procedure copy (source: variable_strings; target: in out variable_strings) is
   copy_varstring_to_varstring_too_long: exception;
 begin
   is_okay (source);
   if source.length > target.size then
     raise copy_varstring_to_varstring_too_long;
   end if;
   target.length := source.length;
   target.list (1..source.length) := source.list (1..source.length);
 end copy;

 procedure copy (source: string; target: in out variable_strings) is
   copy_string_to_varstring_too_long: exception;
 begin
   if source'length > target.size then
     raise copy_string_to_varstring_too_long;
   end if;
   target.length := source'length;
   if source'length>0 then
     target.list (1..source'length) := source;
   end if;
 end copy;

 function element (message: variable_strings;
                   col: natural) return character is
   varstring_element_out_of_range: exception;
 begin
   is_okay (message);
   if    col not in 1..message.length then
     raise varstring_element_out_of_range;
   end if;
   return message.list (col);
 end element;

 function image (message: variable_strings) return string is
 begin
   is_okay (message);
   if message.length=0 then return "";
   else                     return message.list (1..message.length);
   end if;
 end image;


 procedure in_place_lower_case (message: in out variable_strings) is
 begin
   is_okay (message);
   for i in 1..message.length loop
     message.list(i) := string_control.lower_case (message.list(i));
   end loop;
 end in_place_lower_case;

 procedure in_place_truncate (message: in out variable_strings;
                              ch: character := ' ') is
 begin
   is_okay (message);
   loop
     exit when message.length = 0;
     exit when message.list (message.length) /= ch;
     message.length := message.length - 1;
   end loop;
 end in_place_truncate;

 procedure in_place_upper_case (message: in out variable_strings) is
 begin
   is_okay (message);
   for i in 1..message.length loop
     message.list(i) := string_control.upper_case (message.list(i));
   end loop;
 end in_place_upper_case;

 function length (message: variable_strings) return natural is
 begin
   is_okay (message);
   return message.length;
 end length;

 function length_allocated (message: variable_strings) return natural is
 begin
   return message.size;
 end length_allocated;

 function same (left, right: variable_strings) return boolean is
 begin
   is_okay (left);
   is_okay(right);
   return left.length=right.length and then
          left.list(1..left.length) = right.list(1..left.length);
 end same;

 function same   (left: variable_strings; right: string) return boolean is
 begin
   is_okay (left);
   return left.length=right'length and then
          left.list(1..left.length) = right;
 end same;

 procedure set_element (message: in out variable_strings;
                        col: natural;
                        value: character) is
   varstring_set_element_index_out_of_range: exception;
   varstring_set_element_index_way_out_of_range: exception;
 begin
   is_okay (message);
   if    col > message.size then
     raise varstring_set_element_index_way_out_of_range;
   elsif col = message.length+1 then
     message.length     := message.length + 1;
     message.list (col) := value;
   elsif col > message.length then
     raise varstring_set_element_index_out_of_range;
   else
     message.list (col) := value;
   end if;
 end set_element;

 procedure set_length (message: in out variable_strings;
                       new_length: natural) is
   hold_length: integer := message.length;
   varstring_set_length_too_long: exception;
 begin
   if hold_length > message.size then
     raise varstring_set_length_too_long;
   end if;
   message.length := new_length;
   if hold_length < 0 then
     for i in 1..message.size loop
       message.list (i) := ' ';
     end loop;
   end if;
   if    hold_length > 0 then
     for i in hold_length+1 .. new_length loop
       message.list (i) := ' ';
     end loop;
   end if;
 end set_length;

 function slice (message: variable_strings;
                 start, finish: natural) return string is
   varstring_slice_start_out_of_range: exception;
   varstring_slice_finish_out_of_range: exception;
 begin
   is_okay (message);
   if    start not in 1..message.length then
     raise varstring_slice_start_out_of_range;
   elsif finish not in 0..message.length then
     raise varstring_slice_finish_out_of_range;
   end if;
   if finish < start then
     return "";
   else
     declare
       hold: constant string (1..finish+1-start) :=
                        message.list(start..finish);
     begin
       return hold;
     end;
   end if;
 end slice;

 function substr (message: variable_strings;
                  start, length: natural) return string is
 begin
   is_okay (message);
   return slice (message, start, start+length-1);
 end substr;

 function substr (message: variable_strings;
                  start: natural)
                  return string is
 begin
   is_okay (message);
   return slice (message, start, message.length);
 end substr;

end variable_string_control;
with system;
package hand is
  pragma elaborate_body;

  --  Purpose:
  --
  --    Provide OS binding to file open, read, write, position, close
  --
  --  Warning: To compute the system.address do this: message(1)'address
  --
  --
  --  Architecture:
  --
  --     ADO (Abstract Data Object)
  --     SIS (Semantically Independent Specification)

  type handles is range -1..32;
  for handles'size use 16;

  null_handle:     constant handles := 0;
  broken_handle:   constant handles := -1; -- File does not exist.
  standard_input:  constant handles := 0;
  standard_output: constant handles := 1;
  standard_error:  constant handles := 2;

  type    open_methods   is (read_open, write_open, append_open);
  type    seek_methods   is (from_BOF, from_current, from_EOF);
  type    file_positions is range -2147483648 .. 2147483647;
  subtype string_8       is string (1..8);
  subtype string_12      is string (1..12);

  already_internally_open:      exception;
  could_not_check:              exception;
  could_not_create:             exception;
  could_not_open:               exception;
  could_not_read:               exception;
  could_not_reposition:         exception;
  could_not_seek:               exception;
  missing_slash_at_end_of_path: exception;

  procedure close         (handle: handles);
  procedure commit        (handle: handles);
  function  create        (name:   string)
                           return handles;
  procedure create_unique (path: string;
                           name:   out string;
                           handle: out handles);
  function  image         (handle: handles)
                           return string;
  function  is_standard_input (handle: handles)
                           return boolean;
  function  is_standard_output (handle: handles)
                           return boolean;
  function  open          (name: string;
                           open_method: open_methods)
                           return handles;
  function  position      (handle: handles)
                           return file_positions;
  procedure read          (whereto: system.address;
                           length: in out file_positions;
                           handle: handles);
  function  seek          (handle: handles;
                           position: file_positions;
                           seek_method: seek_methods)
                           return file_positions;
  function  size          (handle: handles)
                           return file_positions;
  procedure write         (whereto: system.address;
                           length:  in out file_positions;
                           handle:  handles);
end hand;


with Ada.IO_exceptions;
with Ada.streams.stream_io;
with Ada.text_io.text_streams;
with variable_string_control;
package body hand is
  -- compiler_this_package_is_dependent_on: constant string := "any Ada 95";
  use Ada.streams.stream_io;

  directory_separator: constant character := '\'; -- change to '/' for Linux

  type unique_counts is mod 4;
  unique_count: unique_counts := 0;

  -- Streams

  type selfs is record
    soul:       file_type;
    incarnated: boolean:=false;
  end record;

  subtype usable_handles is handles range 3 .. handles'last;
  type universes is array (usable_handles) of selfs;
  self: universes;
  handle_is_not_incarnated: exception;

  procedure check (handle: handles; message: string) is
  begin
    if handle in usable_handles then
      if not self (handle).incarnated then
        raise handle_is_not_incarnated;
      end if;
    end if;
  end check;

  function stream (handle: handles) return stream_access is
    broken_handle_detected: exception;
  begin
    case handle is
      when standard_input=>
        return Ada.streams.stream_io.stream_access(
          Ada.text_io.text_streams.stream(Ada.text_io.standard_input));
      when standard_output=>
        return Ada.streams.stream_io.stream_access(
          Ada.text_io.text_streams.stream(Ada.text_io.standard_output));
      when standard_error =>
        return Ada.streams.stream_io.stream_access(
          Ada.text_io.text_streams.stream(Ada.text_io.standard_error));
      when broken_handle=>
        raise broken_handle_detected;
      when usable_handles=>
        return stream (self (handle).soul);
    end case;
  end stream;

  function available return handles is
  begin
    for handle in usable_handles loop
      if not self (handle).incarnated then
        self (handle).incarnated := true;
        return handle;
      end if;
    end loop;
    raise could_not_create;
  end available;

  procedure commit (handle: handles) is
  begin
    check (handle, "commit");
    if handle in usable_handles then
      flush (self (handle).soul);
    else
      null;
    end if;
  end commit;

  procedure close (handle: handles) is
  begin
    if handle in usable_handles then
        -- Handle is not checked, so failed-open handles can be closed.
      if self (handle).incarnated then
        close (self (handle).soul);
        self (handle).incarnated := false;
      end if;
    end if;
  exception
    when Ada.IO_exceptions.status_error =>
      self (handle).incarnated := false;
  end close;

  function image (handle: handles) return string is
  begin
    return handles'image (handle);
  end image;

  function is_standard_input (handle: handles) return boolean is
  begin
    return handle=standard_input;
  end is_standard_input;

  function is_standard_output (handle: handles) return boolean is
  begin
    return handle=standard_output;
  end is_standard_output;

  function create (name: string) return handles is
    handle: handles;
    could_neither_create_it_nor_open_it_for_output: exception;
    use variable_string_control;
  begin
    if name'length=0 then
      handle := standard_output;
    else
      handle := available;
      create (self (handle).soul, out_file, name);
    end if;
    return handle;
  exception
    when Ada.IO_exceptions.name_error =>
      open (self (handle).soul, out_file, name);
      return handle;
    when Ada.IO_exceptions.use_error =>
      begin
        open (self (handle).soul, out_file, name);
        return handle;
      exception
        when Ada.IO_exceptions.use_error =>
          raise could_neither_create_it_nor_open_it_for_output;
          return broken_handle;
      end;
  end create;

  procedure create_unique (path: string;
                           name: out string;
                           handle: out handles) is

    unique_image: string:=unique_counts'image(unique_count);
    random_string: constant string := "tempxxx" &
        unique_image(unique_image'first + 1) & ".tmp";  -- 9 only ?
    -- random_string: constant string := "tempxxxx.tmp";
    full_path: string := path & random_string;

  begin
    unique_count := unique_count + 1;
    if path'length /= 0 and then
       path (path'last) /= directory_separator then
      raise missing_slash_at_end_of_path;
    end if;
    handle := create (full_path);
    name   := full_path (path'length+1 .. path'length+random_string'length);
  end create_unique;

  function open (name: string;
                 open_method: open_methods)
                 return handles is

    handle:        handles;
    file_position: file_positions := 0;
    use variable_string_control;
  begin
    if name'length=0 then
      case open_method is
        when read_open =>
          handle := standard_input;
        when write_open =>
          handle := standard_output;
        when append_open=>
          handle := standard_output;
      end case;
    else
      handle := available;
      case open_method is
        when read_open =>
          open (self (handle).soul, in_file, name);
        when write_open =>
          open (self (handle).soul, out_file, name);
        when append_open=>
          open (self (handle).soul, append_file, name);
          file_position := seek (handle, 0, from_EOF);
          -- redundant because of bug in gnat 3.10. Needed in gnat3.11?
      end case;
    end if;
    return handle;
  exception
    when Ada.IO_exceptions.name_error =>
      self (handle).incarnated := false;
      return broken_handle;
  end open;

  function position (handle: handles) return file_positions is
    standard_handles_cannot_be_positioned: exception;
  begin
    check (handle, "position");
    if handle not in usable_handles then
      raise standard_handles_cannot_be_positioned;
    end if;
    return file_positions (index (self(handle).soul)) - 1;
  end position;

  procedure read (whereto: system.address;
                  length: in out file_positions;
                  handle: handles) is

    use Ada.streams;
    subtype buffers is stream_element_array(1..stream_element_offset(length));
    buffer: buffers;
    for buffer use at whereto;
    seo: stream_element_offset:=stream_element_offset(length);
  begin
    check (handle, "read");
    read(stream (handle).all, buffer, seo);
    length:=file_positions(seo);
  end read;

  function is_keyboard_device (handle: handles) return boolean is
  begin
    return false; --?
  end is_keyboard_device;

  function seek (handle: handles;
                 position: file_positions;
                 seek_method: seek_methods)
                 return file_positions is

    cannot_seek_standard_handles: exception;
    p: constant file_positions := position + 1;
    here: constant file_positions := hand.position (handle);
  begin
    check (handle, "seek");
    if handle in usable_handles then
      declare
        file: file_type renames self(handle).soul;
      begin
        case seek_method is
          when from_BOF=>
            set_index (file, positive_count (p));
          when from_EOF=>
            set_index (file, positive_count (file_positions(size(file)) + p));
          when from_current=>
            set_index (file, positive_count (here + P));
        end case;
        return file_positions(index (file))-1;
      end;
    else
      raise cannot_seek_standard_handles;
    end if;
  end seek;

  function size (handle: handles) return file_positions is
    my_size: count;
    signed_size: file_positions;
  begin
    check (handle, "size");
    if handle in usable_handles then
      my_size := size (self (handle).soul);
      signed_size := file_positions(my_size);
      return signed_size;
    else
      return 0;
    end if;
  end size;

  procedure write (whereto: system.address;
                   length:  in out file_positions;
                   handle:  handles) is
    use Ada.streams;
    subtype buffers is stream_element_array(1..stream_element_offset(length));
    buffer: buffers;
    for buffer use at whereto;
  begin
    check (handle, "write");
    write (stream (handle).all, buffer);
  end write;

end hand;

-------------------------------------------------------------------------------





^ permalink raw reply	[relevance 2%]

* Re: Size of 0..255 is not 8 bits?
    1998-05-14  0:00  5%       ` Simon Pilgrim
@ 1998-05-15  0:00  6%       ` Markus Kuhn
  1998-05-15  0:00  0%         ` Samuel T. Harris
  1 sibling, 1 reply; 115+ results
From: Markus Kuhn @ 1998-05-15  0:00 UTC (permalink / raw)



Robert Dewar wrote:
> It is indeed a bug in a compiler if a Size clause for an object does not
> result in the object tkaing the indicated nnumber of bits. But perhaps
> you had better post the EXACT code that leads you to that conclusion.

Ok, here comes the exact code and the execution result of what
confuses me.

Environment: gnat-3.10p-i386-linux-bin
             Linux kernel 2.0.29
             libc.so.5.3.12.

---------------------------------------------------------------------
with Ada.Text_IO.Text_Streams, Ada.Text_IO, Ada.Integer_Text_IO;
use  Ada.Text_IO.Text_Streams, Ada.Text_IO, Ada.Integer_Text_IO;

procedure Strange2 is

   type Value is range 0..255;
   for Value'Size use 8;

   V: Value;
   for V'Size use 8;

begin
   for X in 1..5 loop
      Value'Read(Stream(Standard_Input), V);
      Put(Integer(V));
      New_Line;
   end loop;
end Strange2;
---------------------------------------------------------------------
$ echo "ABCDEFGHIJK" | ./strange2
         65
         67
         69
         71
         73
---------------------------------------------------------------------
PROBLEM: Although I have been very explicit about that I want V
to be 8 bits large, and although GNAT generated no errors or
warnings when compiling the above, Value'Read clearly eats 16-bit
chunks per call, but stores only the first 8 bits, which I consider
highly surprising.
I would have expected to see either an output like
         65
         66
         67
         68
         69
or to get a compiler error message telling me that the "use 8"
representation clause for "range 0..255" cannot be used. 
---------------------------------------------------------------------


And here is a related problem if I use streams on range 0..255
Arrays:

---------------------------------------------------------------------
with Ada.Text_IO.Text_Streams, Ada.Text_IO, Ada.Integer_Text_IO;
use  Ada.Text_IO.Text_Streams, Ada.Text_IO, Ada.Integer_Text_IO;

procedure Strange3 is

   type Value is range 0..255;
   for Value'Size use 8;

   type Value_Array is array(1..5) of Value;
   for Value_Array'Component_Size use 8;
   pragma Pack(Value_Array);

   VA: Value_Array;

begin
   Put(Value_Array'Size);
   Value_Array'Read(Stream(Standard_Input), VA);
   Put_Line("Read Success");
   for X in 1..5 loop
      Put(Integer(VA(X)));
      New_Line;
   end loop;
end Strange3;
---------------------------------------------------------------------
$ echo "ABCDEFGHIJK" | ./strange2
         40

raised CONSTRAINT_ERROR
---------------------------------------------------------------------
PROBLEM: Why do I get a CONSTRAINT_ERROR here?
---------------------------------------------------------------------

This looks like a GNAT 3.10p bug to me. If I replace "range 0..255"
with "mod 256", then everything works nicely.

Markus

-- 
Markus G. Kuhn, Security Group, Computer Lab, Cambridge University, UK
email: mkuhn at acm.org,  home page: <http://www.cl.cam.ac.uk/~mgk25/>




^ permalink raw reply	[relevance 6%]

* Re: Size of 0..255 is not 8 bits?
  1998-05-15  0:00  6%       ` Markus Kuhn
@ 1998-05-15  0:00  0%         ` Samuel T. Harris
  0 siblings, 0 replies; 115+ results
From: Samuel T. Harris @ 1998-05-15  0:00 UTC (permalink / raw)



Markus Kuhn wrote:
> 
> Robert Dewar wrote:
> > It is indeed a bug in a compiler if a Size clause for an object does not
> > result in the object tkaing the indicated nnumber of bits. But perhaps
> > you had better post the EXACT code that leads you to that conclusion.
> 
> Ok, here comes the exact code and the execution result of what
> confuses me.
> 
> Environment: gnat-3.10p-i386-linux-bin
>              Linux kernel 2.0.29
>              libc.so.5.3.12.
> 
> ---------------------------------------------------------------------
> with Ada.Text_IO.Text_Streams, Ada.Text_IO, Ada.Integer_Text_IO;
> use  Ada.Text_IO.Text_Streams, Ada.Text_IO, Ada.Integer_Text_IO;
> 
> procedure Strange2 is
> 
>    type Value is range 0..255;
>    for Value'Size use 8;
> 
>    V: Value;
>    for V'Size use 8;
> 
> begin
>    for X in 1..5 loop
>       Value'Read(Stream(Standard_Input), V);
>       Put(Integer(V));
>       New_Line;
>    end loop;
> end Strange2;
> ---------------------------------------------------------------------
> $ echo "ABCDEFGHIJK" | ./strange2
>          65
>          67
>          69
>          71
>          73
> ---------------------------------------------------------------------
> PROBLEM: Although I have been very explicit about that I want V
> to be 8 bits large, and although GNAT generated no errors or
> warnings when compiling the above, Value'Read clearly eats 16-bit
> chunks per call, but stores only the first 8 bits, which I consider
> highly surprising.
> I would have expected to see either an output like
>          65
>          66
>          67
>          68
>          69
> or to get a compiler error message telling me that the "use 8"
> representation clause for "range 0..255" cannot be used.
> ---------------------------------------------------------------------

This really isn't a 'size issue. The size of V is 8 bits.
If the stream was reading 16 bits and shoving all of them into
variable V then I'd expect a constraint_error!

The ARM states in section 13.13.2
Stream-Oriented Attributes:

For every subtype S of a specific type T, the follow attributes
are defined.

S'Write    S'Write denotes a procedure witht he following
           specification:

           procedure S'Write (Stream : access
                              Ada.Streams.Root_Stream_Type'Class;
                              Item   : in T)

           S'Write writes the value of Item to Stream.

S'Read     S'Read denotes a procedure with the following
           specification:

           procedure S'Read (Stream : access
                             Ada.Streams.Root_Stream_Type'Class;
                             Item : out T)

           S'Read reads the value of Item from Stream.

It is vitally important to note that 'Read and 'Write DO NOT
operate on Items of subtype S, but on type T. In the above code,
Value is the first subtype S of a base type T. Because it is
a signed integer type, it must be reflexive around 0. This means
the base type T MUST larger than 8 bits. Indeed, most compilers
are limited to machine supported sizes (means byte sized things)
so the base type T is 16 bits which is the next largest available
supported signed integer type. The Read and Write operations are
all occuring on objects of type T (16 bits) and not type S (Value
which is 8 bits).

So the stream is reading 16 bits into an Item of type T
which is 16 bits. Since the variable V is used in the call,
I'd expect some sort of type conversion to accomodate
the actual representation of the variable. It appears GNAT
is simply fitting the lower 8 bits into the 8 bit sized
variable V. This is unexpected behavior. I expect such a
type conversion and assignment of the out varible to
raise a constraint error since the 16 bit values are
outside of the range of V.

> 
> This looks like a GNAT 3.10p bug to me. If I replace "range 0..255"
> with "mod 256", then everything works nicely.

Of course it does. Modulo types are unsigned. They do not reflect
about 0. The base type does not need to be larger to accomodate
the extra values. A mod 256 type fits naturally into 8-bits so
both type Value and its base type T are 8 bits. The 'Read and 'Write
operations still operation on items of the base type T, which is
of 8 bits so everything works as expected. This goes to show
modulo types are the preferred types to use for such representations.

> 
> Markus
> 
> --
> Markus G. Kuhn, Security Group, Computer Lab, Cambridge University, UK
> email: mkuhn at acm.org,  home page: <http://www.cl.cam.ac.uk/~mgk25/>

-- 
Samuel T. Harris, Principal Engineer
Raytheon Training Incorporated
"If you can make it, We can fake it!"




^ permalink raw reply	[relevance 0%]

* Re: Size of 0..255 is not 8 bits?
  @ 1998-05-14  0:00  5%       ` Simon Pilgrim
  1998-05-15  0:00  6%       ` Markus Kuhn
  1 sibling, 0 replies; 115+ results
From: Simon Pilgrim @ 1998-05-14  0:00 UTC (permalink / raw)



Robert Dewar wrote:
> 
> <<This did not change anything, V is still a 16-bit integer. I get
> no difference whether the 'Size clause is for the type, the object,
> both or none at all. Only
> >>
> 
> It is indeed a bug in a compiler if a Size clause for an object does not
> result in the object tkaing the indicated nnumber of bits. But perhaps
> you had better post the EXACT code that leads you to that conclusion.

After reading one of your posts in another thread on 'size, I took
Markus' code and added some lines to display the sizes:

----------------------------------
   with Ada.Text_IO.Text_Streams, Ada.Text_IO, Ada.Integer_Text_IO;
   use  Ada.Text_IO.Text_Streams, Ada.Text_IO, Ada.Integer_Text_IO;

   procedure Strange2 is
      type ValueType is range 0..255;
      for ValueType'Object_Size use 8;
      V: ValueType;
   begin
      Put ("          ValueType'last:");
      Put (Integer(ValueType'last));
      New_line;
      Put ("          ValueType'size:");
      Put (Integer(ValueType'size));
      New_line;
      Put ("   ValueType'object_size:");
      Put (Integer(ValueType'object_size));
      New_line;
      Put ("                  V'size:");
      Put (Integer(V'size));
      New_line;

      for X in 1..5 loop
         ValueType'Read(Stream(Standard_Input), V);
         Put(Integer(V));
      end loop;
   end Strange2;
----------------------------------

I compiled and ran this with GNAT 3.10p on WinNT4 and got the following:

 >echo ABCDEFGHIJKLMNOP | ./strange2
          ValueType'last:        255
          ValueType'size:          8
   ValueType'object_size:          8
                  V'size:          8
         65         67         69         71         73
This appears to be reading 8 bit chunks from the stream, but every other
byte.

If I changed the range of ValueType to 0..127 and rebuilt, I got the
following:

  >echo ABCDEFGHIJKLMNOP | ./strange2
          ValueType'last:        127
          ValueType'size:          7
   ValueType'object_size:          8
                  V'size:          8
         65         66         67         68         69
This works as I expect.

Regards,

Simon Pilgrim




^ permalink raw reply	[relevance 5%]

* Size of 0..255 is not 8 bits?
@ 1998-05-14  0:00  5% Markus Kuhn
    0 siblings, 1 reply; 115+ results
From: Markus Kuhn @ 1998-05-14  0:00 UTC (permalink / raw)



Gnat-3.10p on Linux reads 2 bytes from a stream for an object of
type range 0..255 that was forced with a 'Size representation clause
to be 8 bits long.

Example:

-----------------------------------------------------------------
with Ada.Text_IO.Text_Streams, Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO.Text_Streams, Ada.Text_IO, Ada.Integer_Text_IO;

procedure Strange2 is

   type Value is range 0..255;
   for Value'Size use 8;

   V: Value;

begin
   for X in 1..5 loop
      Value'Read(Stream(Standard_Input), V);
      Put(Integer(V));
      New_Line;
   end loop;
end Strange2;
-----------------------------------------------------------------

$ echo ABCDEFGHIJKLMNOP | ./strange2 
         65
         67
         69
         71
         73


Did I missunderstand something and is S'Size not usable for enforcing
the number of bits allocated for a type?
Is 0..255 a type for signed 16-bit arithmetic and not a type for
(as I had naturally assumed) 8-bit unsigned arithmetic?
Do I have to use Unsigned_8 instead if I want to have a guarantee
to get an 8-bit word (which doesn't provide arithmetic overflow
checks)?

Markus

-- 
Markus G. Kuhn, Security Group, Computer Lab, Cambridge University, UK
email: mkuhn at acm.org,  home page: <http://www.cl.cam.ac.uk/~mgk25/>




^ permalink raw reply	[relevance 5%]

* How to implement I/O using Streams
@ 1997-04-01  0:00  3% Matthew Heaney
  0 siblings, 0 replies; 115+ results
From: Matthew Heaney @ 1997-04-01  0:00 UTC (permalink / raw)



The package Ada.Streams.Stream_IO is example of using a stream to do
(heterogeneous) file I/O.  I want to do network I/O - using BSD Sockets,
say - and use a streams interface to do it.

How do I do this?  The example in RM95 shows how a file object gives the
client a pointer to a stream (through which the I/O is performed), but is
silent about how the stream and file connect to each other.  How does the
stream know about the file? 

If I have a socket descriptor, how can I use a stream to do the I/O over
the socket?

How do I implement the Read and Write operations of my type that derives
from Root_Stream?

declare
   sd : int;  -- or perhaps I'll use a higher-level abstraction
   The_Stream : Stream_Access;
   The_Data : My_Record;
begin
   <create socket and connect to server>

   The_Stream := <get a stream connected to the socket descriptor sd>; -- ???

   My_Record'Write (The_Stream, The_Data);  -- more or less done for me
end;

Does anyone know how the implement that middle line?  Has anyone
implemented a streams interface, ie used something other than
Ada.Streams.Stream_IO or Ada.Text_IO.Text_Streams?

Here's a trial attempt:

type My_Stream (sd : access int) is
   new Root_Stream_Type with null record;

procedure Read (Stream ...);
-- reads from the socket descriptor discriminent

procedure Write (Stream ...);
-- writes to the socket descriptor discriminent

Suppose I built a higher-level abstraction.  Would this work:

   type Socket_File is limited private;

   type Stream_Access is access all Root_Stream_Type'Class;

   function Stream (File : Socket_File) return Stream_Access;
...
private
 
   type My_Stream (File : access Socket_File) is
      new Root_Stream_Type with null record;

   type Socket_File is limited
      record
         sd : int;
         Stream : aliased My_Stream (Socket_File'Access);
      end record;

   procedure Read (Stream : in out My_Stream...);
   procedure Write (Stream : in out My_Stream ...);

end;

Well, is that the way?  Is that how the language designers intended a
stream to be implemented?

Thank you much!
Matt

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[relevance 3%]

* Re: Two ideas for the next Ada standard
  @ 1996-08-31  0:00  4%       ` Robert A Duff
  1996-08-31  0:00  4%         ` Robert Dewar
  0 siblings, 1 reply; 115+ results
From: Robert A Duff @ 1996-08-31  0:00 UTC (permalink / raw)



>Michael F Brenner <mfb@mbunix.mitre.org> wrote:
>>(1h) A FAST, mandatory, standarized way to put a stream of bytes out to
>>a file, with no intermediate packages or code between the
>>Ada call and the underlying file system WRITE and READ commands,
>>giving random access to standard_input and the same I/O speed as
>>competing languages, which now requires compiler dependent code.

It seems to me that Ada.Streams.Stream_IO and Ada.Text_IO.Text_Streams
address the issue.  They provide a very low-level I/O interface
(transfer an array of bytes to a file, and so forth).  The latter allows
access to standard input and output files.

- Bob




^ permalink raw reply	[relevance 4%]

* Re: Two ideas for the next Ada standard
  1996-08-31  0:00  4%       ` Robert A Duff
@ 1996-08-31  0:00  4%         ` Robert Dewar
  0 siblings, 0 replies; 115+ results
From: Robert Dewar @ 1996-08-31  0:00 UTC (permalink / raw)



iBob Duff said

"It seems to me that Ada.Streams.Stream_IO and Ada.Text_IO.Text_Streams
address the issue.  They provide a very low-level I/O interface
(transfer an array of bytes to a file, and so forth).  The latter allows
access to standard input and output files."

Yes and no, if your idea is that C is nice because you can call fread and
fwrite directly with not one instruction in between, then I think the
proper Ada response is that in Ada you can call fread and fwrite directly
with not one instructoin in between!





^ permalink raw reply	[relevance 4%]

* Re: Reading sequential data from Ada.Text_Io.Standard_Input?
  @ 1996-07-09  0:00  6% ` Michael Paus
  1996-07-09  0:00  4% ` Robert A Duff
  1 sibling, 0 replies; 115+ results
From: Michael Paus @ 1996-07-09  0:00 UTC (permalink / raw)



davidf@worf.mks.com (David J. Fiander) wrote:
> So, I want to read from standard input, using Ada.Sequential_Io.
> 
[...]
> So, what, if anything, is the magic incantation to read raw data
> from standard input?

The key to this kind of problem is to use the new Ada 95 streams
facility. Have a look at "A.12 Stream Input-Output". You can get
a stream access value which is associated with Standard_Input with
a declaration like this:

  S  : Ada.Text_IO.Text_Streams.Stream_Access
       := Ada.Text_IO.Text_Streams.Stream(Ada.Text_IO.Standard_Input);

You will need to with 
Ada.Text_IO, Ada.Text_IO.Text_Streams and Ada.Streams.Stream_IO
in order to get that working.

Have fun

Michael

PS: If you are interested I can send you a little example with a writer
application which writes a data structure to a stream which is
associated with standard output and a reader application which recreates
this data structure from a stream which is connected to standard input.
On UNIX you might then execute these apps like

> writer | reader

which means that the data produced by writer is piped into reader.

-- 
------------------------------------------------------------------------
--Dipl.-Ing. Michael Paus   (Member: Team Ada)
--University of Stuttgart, Inst. of Flight Mechanics and Flight Control
--Forststrasse 86, 70176 Stuttgart, Germany
--Phone: (+49) 711-121-1434  FAX: (+49) 711-634856
--Email: Michael.Paus@ifr.luftfahrt.uni-stuttgart.de (NeXT-Mail welcome)





^ permalink raw reply	[relevance 6%]

* Re: Reading sequential data from Ada.Text_Io.Standard_Input?
    1996-07-09  0:00  6% ` Michael Paus
@ 1996-07-09  0:00  4% ` Robert A Duff
  1 sibling, 0 replies; 115+ results
From: Robert A Duff @ 1996-07-09  0:00 UTC (permalink / raw)



In article <4rsibv$2mo@ia.mks.com>,
David J. Fiander <davidf@worf.mks.com> wrote:
>So, what, if anything, is the magic incantation to read raw data
>from standard input?

Try Ada.Text_IO.Text_Streams (or whatever it's called).

- Bob




^ permalink raw reply	[relevance 4%]

* Re: Motivating inheritance and dyn. poly.
  @ 1994-11-21 15:33  1% ` Norman H. Cohen
  0 siblings, 0 replies; 115+ results
From: Norman H. Cohen @ 1994-11-21 15:33 UTC (permalink / raw)


In article <3ai9g8$5e6@israel-info.datasrv.co.il>,
benari@zeus.datasrv.co.il (Moti Ben-Ari) writes: 

|> I believe that the normative use of variants is to represent
|> true alternates, e.g. a message which can take dozens of forms.
|> On the other hand, many try to use it to save a couple of words
|> of memory as if we were still programming for the dear,
|> departed 16K PDP-11.
|>
|> The example in the Highlight section of the Rat. is typical.
|> There is no reason why a simple record could not be used: 
|>
|>   type Alert is
|>     record
|>       P: Priority;
|>       Time_of...
|>       Message...
|>       Action...
|>       Ring...
|>     end;
|>
|> with null values or pointers used for non-relevant fields.
|> Processing can be done using __non-nested__ if's or case's: 
|>
|>   if (A.Priority = Medium) or (A.Priority = High) then
|>     ...
|>   end if;
|>   if (A.Priority = High) then
|>     Display...
|>     Set_Alarm...
|>   end if;
|>
|> This is trivial to understand and maintain, and the time and
|> space overhead is minimal.

I agree that the example in Section I-2.3 of the 9X Rationale is
peculiar.  It has a tall, thin inheritance hierarchy
(with branching factor 1): 

   Base_Alert
       |
    Low_Alert
       |
  Medium_Alert
       |
   High_Alert

Technically, this IS equivalent to an Ada-83 variant type, but a rather
ugly one: 

   type Alert_Tag is
      (Base_Alert, Normal_Alert, Medium_Alert, High_Alert);

   type Alert (Tag: Alert_Tag) is
      record
         case Tag is
            when Base_Alert =>
               null;
            when Normal_Alert .. High_Alert =>
               Time_Of_Arrival : Calendar.Time;
               Message         : Text;
               case Tag is
                  when Medium_Alert .. High_Alert =>
                     Action_Officer: Person;
                     case Tag is
                        when High_Alert =>
                           Ring_Alarm_At: Calendar.Time;
                        when others =>
                           null;
                     end case;
                  when others =>
                     null;
               end case;
         end case;
      end record;

However, I think the flattened alternative Moti proposes is far worse.
I've maintained code (not written in Ada) that uses "implicit variants"
of this sort, and it's a nightmare.  The code provides no clear clue that
a structure comes in a number of forms, that certain components determine
which form a given instance of the structure holds, and that certain
components only have meaningful values in certain forms.  As the program
was modified over the years by people who did not understand the implicit
variant structure as well as the original programmers understood it, we
find that code to copy an instance of the structure would copy even the
currently inactive components, to be on the safe side.  We find bugs that
were introduced by programmers apparently assuming that since the
structure appeared to be initialized, all of its components must have
meaningful values.  These bugs were repaired by fixing the most proximate
symptom--stuffing a value into a component that belongs to a logically
inactive variant, thus destroying the original programmers' notion of
distinct variants and creating a much more complicated set of rules about
when components have meaningful values.  Inevitably, programmers needing
to add more components to the structure for use during a particular phase
of the program noticed that certain components were unused during that
phase of the program, and decided that rather than waste storage, they
would "reuse" the existing component, using the same component (or, worse
yet, a differently typed component overlaid with that component) for a
completely different purpose.  This made it great fun trying to figure
out what kind of data was held in a particular component at a particular
point in the program.

It would have been much better if the original programmer had written an
Ada record with a variant part.  A particular component of the record
would have been clearly identified as a discriminant, it would have
been clearly documented that the record has a finite number of forms, and
the variant part would clearly have indicated which components are
present in which forms.  A maintenance programmer trying to reference a
component in an inactive variant would have been alerted by a
Constraint_Error (or perhaps even a compile-time warning) that he was
doing something fundamentally meaningless, and would have redesigned his
modifications accordingly rather than breaking the original
data-structure design.  The compiler would automatically take care of
storage mapping, overlaying a new component for one variant with storage
used for other components in other variants, while allowing the
programmer to remain oblivious to the overlay and preserving the logical
view that the new component is distinct from all other components.

I short, I am firmly convinced that explicit variants controlled by
discriminants are a signficant advance over flat records in which the
current validity of each component is controlled by programmer
convention.

Returning to Moti's request for a more convincing example of type
extension, consider streams, introduced Section 13.13 on RM9X.
Ada.Streams.Root_Stream_Type is an abstract type with Read and Write
operations.  Streams are, from an abstract point of view, sinks and
sources of raw binary data.  Among the possible "variants" of streams are
streams implemented as files, streams implemented as in-memory buffers,
and streams implemented as communications ports.  Packages
Ada.Streams.Stream_IO and Ada.Text_IO.Text_Streams provide functions that
offer access to a stream corresponding to an open file; although the
implementation of these streams is not specified by the RM, a stream
implemented as a file seems to be the only reasonable choice.  The
Distributed Systems Annex package System.RPC defines an extension of
Root_Stream_Type named Params_Stream_Type, most likely implemented as a
memory buffer or, on a distributed system without shared memory, as a
communications port.

The strength of the OOP approach for streams lies in the fact that one
can write subprograms with Root_Stream_Type'Class parameters using only
the abstract Read and Write operations of streams, without regard to how
streams are implemented.  (Most notable among these are the T'Read and
T'Write subprograms for translating complex data structures, perhaps
containing access values, to and from streams of bytes whose meaning is
independent of the addresses implied by the access values.)  Furthermore,
if other implementations of streams are later conceived, new extensions
of stream types can be declared with versions of Read and Write that are
implemented accordingly.  All software previously designed to work with
streams will then work with the new kind of stream.  Calls on Read and
Write from within this software will automatically be "dispatched" to the
versions of these procedures for the "variant" of streams currently being
manipulated.

Tagged types are, in effect, like Ada-83 types with variants in which the
case statements examining discriminants are implicit in dispatching calls
and in which new variants can be added without modifying old source.

--
Norman H. Cohen    ncohen@watson.ibm.com



^ permalink raw reply	[relevance 1%]

Results 1-115 of 115 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
1994-11-18 13:16     Motivating inheritance and dyn. poly Moti Ben-Ari
1994-11-21 15:33  1% ` Norman H. Cohen
1996-07-09  0:00     Reading sequential data from Ada.Text_Io.Standard_Input? David J. Fiander
1996-07-09  0:00  6% ` Michael Paus
1996-07-09  0:00  4% ` Robert A Duff
1996-08-28  0:00     Two ideas for the next Ada standard Van Snyder
1996-08-30  0:00     ` Michael F Brenner
1996-08-30  0:00       ` Robert A Duff
1996-08-30  0:00         ` Robert Dewar
1996-08-31  0:00  4%       ` Robert A Duff
1996-08-31  0:00  4%         ` Robert Dewar
1997-04-01  0:00  3% How to implement I/O using Streams Matthew Heaney
1998-05-14  0:00  5% Size of 0..255 is not 8 bits? Markus Kuhn
1998-05-13  0:00     ` Matthew Heaney
1998-05-14  0:00       ` Markus Kuhn
1998-05-14  0:00         ` Robert Dewar
1998-05-14  0:00  5%       ` Simon Pilgrim
1998-05-15  0:00  6%       ` Markus Kuhn
1998-05-15  0:00  0%         ` Samuel T. Harris
1998-09-24  0:00     Image processing File I/O Jeong, Laehyung
1998-09-24  0:00     ` Dale Stanbrough
1998-09-24  0:00  2%   ` Michael F Brenner
1999-02-07  0:00  6% Streams - copying stdin to stdout Chris Miller
1999-02-09  0:00     ` Stephen Leake
1999-02-10  0:00  5%   ` David Brown
1999-02-10  0:00  0%     ` rdt
1999-07-20  0:00  2% Type mess in Ada standard library Markus Kuhn
1999-07-20  0:00  0% ` Michael F. Yoder
1999-07-23  0:00  0% ` Tucker Taft
2000-07-28  0:00     'Read for pointers Stephen Leake
2000-07-28  0:00  6% ` tmoran
2000-09-23  0:00  6% GNAT bug or expectations problem with Text_Io.Text_Streams Jeff Creem
2000-09-24  0:00  0% ` Preben Randhol
2000-09-24  0:00  0%   ` Preben Randhol
2000-09-24  0:00  0% ` David C. Hoos, Sr.
     [not found]     <n5su6.24687$CL6.767652@telenews.teleline.es>
2001-03-26 14:08     ` Binary Data File - PLEASE HELP Sergio
2001-03-26 14:55  4%   ` Marin David Condic
2001-08-05 22:18     implementation question about writing and reading from files Francis Crick
2001-08-05 22:43     ` tmoran
2001-08-09 23:19       ` Francis Crick
2001-08-10 14:49  4%     ` Ted Dennison
2001-08-10 15:44  0%       ` Warren W. Gay VE3WWG
2002-02-25 17:08     reading from a file Deepie
2002-02-25 17:23     ` John McCabe
2002-02-25 20:30       ` Deepie
2002-02-25 20:46  5%     ` sk
2002-08-14 19:34     Fill string with multiple lines from standard_input Vincent Smeets
2002-08-14 20:37     ` Stephen Leake
2002-08-15 17:57       ` Vincent Smeets
2002-08-15 20:47         ` Stephen Leake
2002-08-19 19:39           ` Vincent Smeets
2002-08-20 15:01             ` Stephen Leake
2002-08-20 18:26  4%           ` Vincent Smeets
2002-08-20 19:46  0%             ` tmoran
2002-08-21 12:50  4%             ` Jean-Pierre Rosen
2002-08-21 19:19  3%             ` Randy Brukardt
2002-08-15  2:30  7% ` SteveD
2002-08-15 18:02  5%   ` Vincent Smeets
2002-08-15 19:07  4%   ` Vincent Smeets
2002-08-15 21:49         ` chris.danx
2002-08-16 19:30  4%       ` Ted Dennison
2002-08-17  2:26  4%         ` Randy Brukardt
2002-08-17 10:24  4%         ` Robert Dewar
2002-08-19 13:40  0%           ` Ted Dennison
2002-10-15 16:50     New to Ada..need some help regarding Binary Conversion?? Paula
2002-10-15 17:48  4% ` sk
2002-10-16 11:09  0%   ` Paula
2002-11-04 22:34     Can I treat Current_Output as a file of bytes? Bj�rn Persson
2002-11-05 14:30  4% ` Ted Dennison
2002-11-05 16:01  0%   ` Bj�rn Persson
2002-11-05 18:13  0%     ` Warren W. Gay VE3WWG
2002-11-05 22:27  0%     ` Ted Dennison
2002-11-06 23:40  0%       ` Randy Brukardt
2002-11-07  0:44  0%       ` Bj�rn Persson
2003-07-12 14:03     Terminating a task kat-Zygfryd
2003-07-12 14:37     ` kat-Zygfryd
2003-07-14  9:34       ` Craig Carey
2003-07-14 23:45         ` Matthew Heaney
2003-07-15 17:49           ` Craig Carey
2003-07-15 18:30  6%         ` David C. Hoos
2003-07-15 20:13     Ada.Streams.Stream_IO.File_Type tmoran
2003-07-17 15:10  0% ` Ada.Streams.Stream_IO.File_Type Craig Carey
2003-07-17 16:42  0%   ` Ada.Streams.Stream_IO.File_Type Nick Roberts
2003-09-29  8:45     procedure Create(file : in out File_Type; from : in Stream_Access); ? Lutz Donnerhacke
2003-09-29 15:14     ` Stephen Leake
2003-09-29 19:29       ` Lutz Donnerhacke
2003-09-30 12:34  4%     ` Jean-Pierre Rosen
2003-09-30 13:27  0%       ` Lutz Donnerhacke
2003-09-30 14:24  0%         ` Jean-Pierre Rosen
2003-10-01  0:10  5%           ` sk
2003-10-01  7:34  5%             ` Jean-Pierre Rosen
2003-10-01 12:32  0%               ` Lutz Donnerhacke
2003-10-14 14:42  5% [Fwd: Re: SEQUENTIA_IO and stdin/stdout] Marius Amado Alves
2005-03-19 16:22     Ada bench Pascal Obry
2005-03-19 16:55     ` Dr. Adrian Wrigley
2005-03-19 21:32       ` Michael Bode
2005-03-20  9:20         ` Pascal Obry
2005-03-21 23:27           ` Georg Bauhaus
2005-03-22  1:16             ` Ada bench : count words Marius Amado Alves
2005-03-22 10:59               ` Dmitry A. Kazakov
2005-03-22 12:22  6%             ` Jeff C
2005-03-22 19:49  6%           ` tmoran
2005-03-22 21:51  0%             ` Dmitry A. Kazakov
2005-03-22 22:33  0%             ` Marius Amado Alves
     [not found]                 ` <00b362390273e6c04844dd4ff1885ee0@netcabo.pt>
2005-03-23 15:09  6%               ` Marius Amado Alves
2005-03-30 16:08  0%                 ` Andre
2005-03-23 19:00     tmoran
2005-03-23 19:54     ` Tapio Kelloniemi
2005-03-23 20:39  5%   ` Ada bench : word frequency Marius Amado Alves
2005-03-23 21:26         ` Isaac Gouy
2005-03-24  1:24  5%       ` Marius Amado Alves
2005-03-23 19:30     Ada bench : count words tmoran
2005-03-23 21:38  5% ` tmoran
2005-03-26 13:53     Gnat 3.15p & Windows & Hyperthreading Q Marin David Condic
2005-03-26 18:36  5% ` tmoran
2005-03-28 13:16  0%   ` Marin David Condic
2005-08-10 17:01     Using fwrite in Ada Makhno
2005-08-10 17:28  5% ` Georg Bauhaus
2005-08-11 17:01  3% ` tmoran
2005-10-13  0:49  4% Newbie Question: using Text_IO.Open() to read from standard input pamela.lum
2005-10-13  3:15  0% ` Steve
2006-11-21 15:11     I/O streaming with custom data transport Maciej Sobczak
2006-11-21 17:51     ` Alex R. Mosteo
2006-11-22  9:16  6%   ` Maciej Sobczak
2006-11-22 13:50         ` Robert A Duff
2006-11-22 14:37           ` Maciej Sobczak
2006-11-22 16:11  4%         ` Georg Bauhaus
2007-12-18 12:28     newline in a simple program Paul
2007-12-18 13:11  6% ` Dmitry A. Kazakov
2007-12-18 19:26  6% Auto new line Jeffrey R. Carter
2009-02-16 20:36     C getchar() functionality in Ada Thomas Locke
2009-02-16 21:43  4% ` Jeffrey R. Carter
2009-02-17  7:23  5%   ` Thomas Locke
2009-02-17  8:16  6%     ` Niklas Holsti
2009-02-17 13:01  0%       ` Georg Bauhaus
2009-08-01 12:21     Ada Shootout program for K-Nucleotide (patches) Georg Bauhaus
2009-08-01 15:21     ` Ludovic Brenta
2009-08-02 12:55  6%   ` Georg Bauhaus
2009-08-03  8:56       ` Jacob Sparre Andersen
2009-08-03 11:43         ` Georg Bauhaus
2009-08-03 12:36           ` Jacob Sparre Andersen
2009-08-03 18:31             ` Isaac Gouy
2009-08-03 20:29               ` Robert A Duff
2009-08-04 15:43                 ` Isaac Gouy
2009-08-04 16:06                   ` Isaac Gouy
2009-08-04 17:08                     ` Georg Bauhaus
2009-08-05 15:58                       ` Isaac Gouy
2009-08-05 21:18                         ` Georg Bauhaus
2009-08-05 22:04  6%                       ` Ludovic Brenta
2009-08-05 22:31  0%                         ` Georg Bauhaus
2009-08-06  7:51  0%                           ` Dmitry A. Kazakov
2009-10-24 22:07     Preferred way to do binray I/O on standard input/output stream Hibou57 (Yannick Duchêne)
2009-10-24 22:57  5% ` Jeffrey R. Carter
2009-10-24 23:22  0%   ` Hibou57 (Yannick Duchêne)
2009-10-27  0:34  0%   ` Hibou57 (Yannick Duchêne)
2009-10-27  1:14  6%     ` John B. Matthews
2009-10-27  2:36  0%       ` Hibou57 (Yannick Duchêne)
2009-10-27 16:13  5%         ` John B. Matthews
2010-05-06 17:10     for S'Image use Func?? Warren
2010-05-06 18:14     ` Yannick Duchêne (Hibou57)
2010-05-06 20:04       ` Warren
2010-05-06 20:19         ` Robert A Duff
2010-05-06 20:56           ` Yannick Duchêne (Hibou57)
2010-05-06 21:11             ` Robert A Duff
2010-05-07  8:40               ` J-P. Rosen
2010-05-07 12:21                 ` Robert A Duff
2010-05-07 13:37                   ` Georg Bauhaus
2010-05-07 14:25                     ` Robert A Duff
2010-05-10 15:48                       ` Warren
2010-05-10 16:31                         ` Dmitry A. Kazakov
2010-05-10 16:52                           ` Warren
2010-05-10 17:55                             ` Dmitry A. Kazakov
2010-05-10 20:56                               ` Maciej Sobczak
2010-05-10 22:39  5%                             ` Yannick Duchêne (Hibou57)
2010-05-07  1:02  5% Why is not Stream_Access defined Ada.Streams ? Yannick Duchêne (Hibou57)
2010-05-07  2:24  0% ` Randy Brukardt
2010-12-27 17:23  4% Newbie-ish question about generics and Ada.Streams Brian Drummond
2011-01-20 20:21     problems with interfacing c Stoik
2011-01-20 20:56  5% ` Dmitry A. Kazakov
2011-01-20 21:31  0%   ` Yannick Duchêne (Hibou57)
2011-01-20 23:03  0%     ` Dmitry A. Kazakov
2011-01-28  0:39  0%   ` Stoik
2011-01-28  9:41  5%     ` Ludovic Brenta
2011-02-03  5:52     How do I write directly to a memory address? Syntax Issues
2011-02-07  9:00     ` Ludovic Brenta
2011-02-07 13:43       ` Georg Bauhaus
2011-02-07 13:56         ` Ludovic Brenta
2011-02-07 14:58           ` Georg Bauhaus
2011-02-07 16:54             ` Ludovic Brenta
2011-02-07 17:55               ` Georg Bauhaus
2011-02-08  8:04                 ` Ludovic Brenta
2011-02-08 10:10                   ` Georg Bauhaus
2011-02-08 10:14                     ` Ludovic Brenta
2011-02-08 18:30                       ` Jeffrey Carter
2011-02-08 18:47                         ` Hyman Rosen
2011-02-08 20:11                           ` Shark8
2011-02-08 20:27                             ` Hyman Rosen
2011-02-08 20:52  4%                           ` Shark8
2011-02-28 17:00     Ann: Little tutorial about streams mockturtle
2011-02-28 20:32  4% ` Ludovic Brenta
2011-06-05 16:20  6% Reading the while standard input into a String Natasha Kerensikova
2011-06-06  1:49  6% ` robin
2013-01-15 21:52     Algorithms Homework Help?!?! willmann817
2013-01-15 23:43  4% ` Shark8
2013-02-27 17:36     reading from a pipe milouz
2013-02-27 19:22  7% ` Eryndlia Mavourneen
2013-03-28 17:34  3% Interresting, possibly buggy behavior in GNAT generics w/ expression function Shark8
2013-08-16  1:02  5% What's the cause of extra new line with Text_IO when program exit Zhu, Qun-Ying
2014-03-25 21:41     Your wish list for Ada 202X Stoik
2014-04-23 12:55     ` björn lundin
2014-04-23 14:06       ` Dmitry A. Kazakov
2014-04-23 14:44         ` björn lundin
2014-04-23 20:28           ` Randy Brukardt
2014-04-24 10:31             ` björn lundin
2014-04-25  1:22               ` Randy Brukardt
2014-04-25  2:19                 ` Shark8
2014-04-25  7:31  4%               ` Dmitry A. Kazakov
2015-01-04  0:58     How to use read-only variables? hreba
2015-01-04  2:55  4% ` Shark8
2019-10-14 19:41     How to transfer Class-Wide object to a Task ? William FRANCK
2019-10-14 20:21     ` William FRANCK
2019-10-14 21:57  4%   ` Shark8
2019-10-15  5:43  0%     ` William FRANCK
2020-07-30 20:21     Ada.Text_IO.File_Type object with user defined Get and Put subprograms Blady
2020-07-31 18:19     ` Shark8
2020-08-01  7:46       ` Blady
2020-08-01 17:23  6%     ` Shark8
2021-05-17 18:44     Better way to fill Storage_IO? Michael Hardeman
2021-05-17 19:14     ` Simon Wright
2021-05-17 19:23  4%   ` Michael Hardeman
2021-05-18 20:39  0%     ` Simon Wright
2021-05-19  6:24  0%       ` Dmitry A. Kazakov
2021-06-10  2:17     Is it possible to redirect text output to a String or Unbounded_String? Jerry
2021-06-10  6:50  5% ` Simon Wright
2021-06-10 21:12  6% ` Shark8

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox