comp.lang.ada
 help / color / mirror / Atom feed
* AdaYY wish list from current projects
@ 2001-02-20 20:50 Lutz Donnerhacke
  2001-02-22 11:08 ` Florian Weimer
  0 siblings, 1 reply; 17+ messages in thread
From: Lutz Donnerhacke @ 2001-02-20 20:50 UTC (permalink / raw)


I have three sad problems (and a bonus problem) from my current projects.
If they can fixed by a compiler it would be very fine:

Problem 1: Pointer of component => Pointer to aggregate

  In order to mixin a generic list with head nodes not mixed into any other
  user defined structure I'd need to link not the base data but the mixin
  itself. Doing so I need to regenerate the whole aggregate pointer from
  a pointer of a component. Current (not tested) implementation:
  
with System.Address_To_Access_Conversions;

generic
   type Base is tagged limited private;
   type Mixin is tagged limited private;
package Unchecked_Upconversion is
   type Mixed is new Base with record
      mix : aliased Mixin;
   end record;
   
   package Mixin_P is new System.Address_To_Access_Conversions (Mixin);
   package Mixed_P is new System.Address_To_Access_Conversions (Mixed);
   
   Call_To_Mix_First : exception;
   function To_Base (mix : Mixin_P.Object_Pointer)
     return Mixed_P.Object_Pointer;
   function To_Mix (mixed : Mixed_P.Object_Pointer)
     return Mixin_P.Object_Pointer;
end Unchecked_Upconversion;

with System.Storage_Elements;
use System, System.Storage_Elements;

package body Unchecked_Upconversion is
   offset_found : Boolean := False;
   offset : Storage_Offset;
   
   use Mixed_P, Mixin_P;
   
   function To_Base (mix : Mixin_P.Object_Pointer)
     return Mixed_P.Object_Pointer is
   begin
      if not offset_found then
         raise Call_To_Mix_First;
      end if;
      return To_Pointer (To_Address (mix) - offset);
   end To_Base;
   
   function To_Mix (mixed : Mixed_P.Object_Pointer)
     return Mixin_P.Object_Pointer is
   begin
      if not offset_found then
	 offset := To_Address(mixed) -
	           To_Address(mixed.mix'Access);
         offset_found := true;
      end if;
      return mixed.mix'Access;
   end To_Mix;      
end Unchecked_Upconversion;

   It's clearly a workaround to fix a missing language feature. Even other
   solutions (i.e. using Base'Size) are only workarounds which may fail in
   complex situations (pragma Pack) even more likely.
   
   Of course this Conversion may return a Pointer to an invalid aggregate.
\f
Problem 2: Defining Byte_Order of record representations

   My low level networking application has to deal with low and big endian
   values on the net I want to handle with record representations clauses
   in order to get the benefits of compiler generated I/O functions.
   
   Unfortunly only the numeration of bits in the data may be specified.
   Values crossing a Storage_Element boundery can not be handled portably.
   Even worse Storage_Element'Size might not be a multiple of eight. So it's
   impossible to write portable programs.
   
   At the moment I use constructs like the following (introducing new error
   sources, because they are likely forgotten and a lot of legacy code):
      for xxx use (
         addr1 at 0 range 0 .. 7;
         addr2 at 1 range 0 .. 7;
      );
      ...
      addr : Address_Type := Unchecked_Conversion_To_Address (
                               to_uint16(x.addr1, x.addr2));
      if not addr'Valid then ...
      case addr is ...

      function to_uint16(low, high : uint8) return uint16 is
      begin
         if System.Default_Bit_Order = System.Low_Order_First then
	    return Unchecked_Conversion_To_U16 ((low, high));
	 else
	    return Unchecked_Conversion_To_U16 ((high, low));
	 end if;
      end to_uint16;
    
   I'd like to see a additional Byte_Order type and attribute to specify the
   most common byte orders indepenent from the used bit order. This attribute
   must include the conversions above in order to generate better code.
   Several CPUs does have a maschine language prefix to specify the byte and
   the bit order (in)depenty, It's only a bunch of hard wired gatters on the
   chip which should be usable from AdaYY.
\f
Problem 3: Static expressions of discriminants in record representations

   Trying to may a simple data structure like a Pascal string is not possible
   with Ada95. This is even worse in enviroments where memory mapped I/O
   contains such structures and must be handled using Atomic and Volatile
   Pragmas.
   
   It would be fine to use the following:
      type pascal_length is 0 .. 255;
      type pascal_string(len : pascal_length) is record
         data : String (1 .. len);
      end record;
      for pascal_string use record
         len  at 0 range 0 .. 7;
	 data at 1 range 0 .. 8*len - 1;
      end record;

   Additional suggestions are:
      - limit the restriction to specify discriminats at the very beginning.
      - limit the restriction to specify discriminats at statically known
        positions. Allow discriminant dependant discriminant positions.
      - limit the restriction of cycle free position specifications.
      - extend this concept to tagged records.
\f
Problem 4: Single task packages

   Several algorithms require hard work to deal with multitasking. Most of
   those algorithms consist of small and short running functions and
   procedures. On many CPUs those calls can be implemented very efficently
   using self modifying code. In order to generate such code the compiler
   has to determine which parts are single task and which might be
   interrupted. In order to ease this allow the following syntactic shugar
   constructs:
       protected package xxx ...
       protected procedure xxx ...
       protected function xxx ...
   which are similar but stronger than:
       proteced type yyy is
          procedure xxx;
       end yyy;
       y : constant yyy;   -- Singleton
       procedurce xxx is begin y.xxx; end xxx; 
   



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: AdaYY wish list from current projects
  2001-02-20 20:50 AdaYY wish list from current projects Lutz Donnerhacke
@ 2001-02-22 11:08 ` Florian Weimer
  2001-02-22 13:02   ` Lutz Donnerhacke
  0 siblings, 1 reply; 17+ messages in thread
From: Florian Weimer @ 2001-02-22 11:08 UTC (permalink / raw)


lutz@belenus.iks-jena.de (Lutz Donnerhacke) writes:

> I have three sad problems (and a bonus problem) from my current projects.
> If they can fixed by a compiler it would be very fine:
> 
> Problem 1: Pointer of component => Pointer to aggregate
> 
>   In order to mixin a generic list with head nodes not mixed into any other
>   user defined structure I'd need to link not the base data but the mixin
>   itself. Doing so I need to regenerate the whole aggregate pointer from
>   a pointer of a component. Current (not tested) implementation:

For limited types, there is another approach:

   generic
      type Base is tagged limited private;

   package Mix_In is

      type Mixed is new Base with private;

      type Mix_In_Type (Ref : access Mixed) is tagged limited private;

      type Mix_In_Access is access all Mix_In_Type'Class;
      function Cast (B : Mixed) return Mix_In_Access;

   private

      type Mix_In_Type (Ref : access Mixed) is tagged limited record
         null;
      end record;

      type Mixed is new Base with record
         Mix_In : aliased Mix_In_Type (Mixed'Access);
      end record;

   end Mix_In;

   package body Mix_In is

      function Cast (B : Mixed) return Mix_In_Access is
      begin
         return B.Mix_In.Ref.Mix_In'Access;
      end Cast;

   end Mix_In;


It appears that Ada is not suitable for this kind of design.

> Problem 2: Defining Byte_Order of record representations
> 
>    My low level networking application has to deal with low and big endian
>    values on the net I want to handle with record representations clauses
>    in order to get the benefits of compiler generated I/O functions.

For my OpenPGP implementation, I've written my own stream I/O
functions.  That's certainly the way to go if you don't need a
specific in-memory representation.

I don't think an additional attribute is really necessary.  Instead,
vendors could provide packages like Interfaces.Little_Endian and
Interfaces.Big_Endian which contain the Integer_* and Unsigned_*
types from package Interfaces, with the corresponding in-memory and
stream representation.  If you make these types private and provide
conversion functions, you can implement these packages even yourself.

> Problem 3: Static expressions of discriminants in record representations
> 
>    Trying to may a simple data structure like a Pascal string is not possible
>    with Ada95.

The following seems to work in some cases.

   subtype Pascal_Length is Integer range 0 .. 255;

   type Pascal_String (Length : Pascal_Length) is record
      Data : String (1 .. Length);
   end record;
   pragma Pack (Pascal_String);



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: AdaYY wish list from current projects
  2001-02-22 11:08 ` Florian Weimer
@ 2001-02-22 13:02   ` Lutz Donnerhacke
  2001-02-23  9:30     ` Florian Weimer
  0 siblings, 1 reply; 17+ messages in thread
From: Lutz Donnerhacke @ 2001-02-22 13:02 UTC (permalink / raw)


* Florian Weimer wrote:
>lutz@belenus.iks-jena.de (Lutz Donnerhacke) writes:
>> I have three sad problems (and a bonus problem) from my current projects.
>> If they can fixed by a compiler it would be very fine:
>> 
>> Problem 1: Pointer of component => Pointer to aggregate
>> 
>>   In order to mixin a generic list with head nodes not mixed into any other
>>   user defined structure I'd need to link not the base data but the mixin
>>   itself. Doing so I need to regenerate the whole aggregate pointer from
>>   a pointer of a component. Current (not tested) implementation:
>
>For limited types, there is another approach:
>
>      type Mix_In_Type (Ref : access Mixed) is tagged limited private;

Unfortunly this does increase the space requirments significantly. OTOH it
does not address the problem, because I'd like to have a small RAM area
containing only list heads. So I'd instantiate
  head : Mix_In_Type(Null);
or anything like this? Hmm. Seems to work using additional pointers :-(

>It appears that Ada is not suitable for this kind of design.

Very bad. I'd like to suggest a language feature in order to solve this.

>> Problem 2: Defining Byte_Order of record representations
>>
>>    My low level networking application has to deal with low and big endian
>>    values on the net I want to handle with record representations clauses
>>    in order to get the benefits of compiler generated I/O functions.
>
>For my OpenPGP implementation, I've written my own stream I/O
>functions.  That's certainly the way to go if you don't need a
>specific in-memory representation.

Unfortunly I have to deal with memory mapped I/O (i.e. network cards)

>I don't think an additional attribute is really necessary.  Instead,
>vendors could provide packages like Interfaces.Little_Endian and
>Interfaces.Big_Endian which contain the Integer_* and Unsigned_*
>types from package Interfaces, with the corresponding in-memory and
>stream representation.  If you make these types private and provide
>conversion functions, you can implement these packages even yourself.

You miss the point. Providing such packages does not allow the compiler to
generate good maschine code.

function t return Boolean is
   type Uplevel_Discriminator is (Bla, Blubb);
   for Uplevel_Discriminator use (Bla => 16#732#, Blubb => 16#7791#);
   
   type example is record
      port : Uplevel_Discriminator;
   end record;
   for example use record
      port at 17 range 0 .. 15;
   end record;
   for example'Bit_Order use Low_Order_First;  -- bit numbering
   for example'Byte_Order use Little_Endian;   -- bit chunk order
   for example'Address use 16#A00000#;
begin
   case example.port is
      when Bla   => return true;
      when Blubb => return false;
   end case;
end t;

May result in the following (hypothetic) code:
.t
  FF FE 43 11 00 A0 00 32 07    LE CMP (A00011), 732
  02                            NEG Z
  BE 0B                         JNZ t_fin
  FF FE 43 11 00 A0 00 91 77    LE CMP (A00011), 7791
  BE 01                         JZ t_error
.t_fin  
  99                            RET
.t_error  
  .. Exception handling ..

Without Byte_Order = Big_Endian the following code might appear:
.t
  43 00 A0 00 11 07 32          CMP (A00011), 732
  02                            NEG Z
  BE 0B                         JNZ t_fin
  43 00 A0 00 11 77 91          CMP (A00011), 7791
  BE 01                         JZ t_error
.t_fin  
  99                            RET
.t_error  
  .. Exception handling ..

Using a conversion package the code would look like this:
with Endianess, Unchecked_Conversion;
function t return Boolean is
   type Uplevel_Discriminator is (Bla, Blubb);
   for Uplevel_Discriminator use (Bla => 16#732#, Blubb => 16#7791#);
   
   function To_UpDisc is new Unchecked_Conversion (Endianess.Uint16,
                                                   Uplevel_Discriminator);
   
   type example is record
      port : Endianess.Uint16;
   end record;
   for example use record
      port1 at 17 range 0 .. 15;
   end record;
   --  Avoid specification of Bit_Order to enshure compiling
   for example'Address use 16#A00000#;
begin
   case To_UpDisc ( Endianess.From_Low (example.port)) is
      when Bla   => return true;
      when Blubb => return false;
   end case;
end t;

resulting in the (inlined) code:
.t
  PUSH A1
  COPY (A00011), A1
  EXCH A1
  CMP A1, 732
  ...

which might be optimized (due to the use of constants) to:
.t
  PUSH A1
  COPY (A00011), A1
  CMP A1, 3207
  ...

which might be optimized further to:
.t
  CMP (A00011), 3207
  ...

which is similar to the original (unoptimized) code, but quite harder to get.
It's always better to generate good code in the first place instead of
trying to deduct it from a bad one.
  
>> Problem 3: Static expressions of discriminants in record representations
>> 
>>    Trying to may a simple data structure like a Pascal string is not
>>    possible with Ada95.
>
>The following seems to work in some cases.
>
>   subtype Pascal_Length is Integer range 0 .. 255;
>
>   type Pascal_String (Length : Pascal_Length) is record
>      Data : String (1 .. Length);
>   end record;
>   pragma Pack (Pascal_String);

*Gna* And now remove the limitation, that the discriminants have to appear
first.

Even better: Try to write a program, which derivates the type from a pointer.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: AdaYY wish list from current projects
  2001-02-22 13:02   ` Lutz Donnerhacke
@ 2001-02-23  9:30     ` Florian Weimer
  2001-02-23 10:12       ` Lutz Donnerhacke
  0 siblings, 1 reply; 17+ messages in thread
From: Florian Weimer @ 2001-02-23  9:30 UTC (permalink / raw)


lutz@iks-jena.de (Lutz Donnerhacke) writes:

> Unfortunly this does increase the space requirments significantly. OTOH it
> does not address the problem, because I'd like to have a small RAM area
> containing only list heads. So I'd instantiate
>   head : Mix_In_Type(Null);
> or anything like this? Hmm. Seems to work using additional pointers :-(

I think you would have to use an access value instead (that's the same
with your proposed approach).

> >It appears that Ada is not suitable for this kind of design.
> 
> Very bad. I'd like to suggest a language feature in order to solve this.

Perhaps general introspection? ;-)

To be honest, I don't think that access-to-component variables can be
added to Ada as transparently as it is possible in, say C++.  The
involved offset might not be constant for types with discriminants,
which makes implementations of this feature quite complicated.

> >> Problem 2: Defining Byte_Order of record representations

> Unfortunly I have to deal with memory mapped I/O (i.e. network cards)

You didn't mention this...

> You miss the point. Providing such packages does not allow the compiler to
> generate good maschine code.

You need the conversion package anyway, at least that's my experience.
Otherwise, your code is quite unportable, as you're passing around
invalid values.

> >> Problem 3: Static expressions of discriminants in record representations

> *Gna* And now remove the limitation, that the discriminants have to appear
> first.

Aha, this was the intent of your comment (I thought you were talking
about the source code location).  Are trailing size specifies really
common?  To me, they don't make much sense.

> Even better: Try to write a program, which derivates the type from a pointer.

Sorry, what do you want to do?



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: AdaYY wish list from current projects
  2001-02-23  9:30     ` Florian Weimer
@ 2001-02-23 10:12       ` Lutz Donnerhacke
  2001-02-23 13:54         ` Florian Weimer
  2001-02-23 19:06         ` tmoran
  0 siblings, 2 replies; 17+ messages in thread
From: Lutz Donnerhacke @ 2001-02-23 10:12 UTC (permalink / raw)


* Florian Weimer wrote:
>lutz@iks-jena.de (Lutz Donnerhacke) writes:
[Regenerating the access to an aggregate from an access to a component]
>> Very bad. I'd like to suggest a language feature in order to solve this.
>
>Perhaps general introspection? ;-)

Not yet. I'd like to obtain it from Objective-Ada.

>To be honest, I don't think that access-to-component variables can be
>added to Ada as transparently as it is possible in, say C++.  The involved
>offset might not be constant for types with discriminants, which makes
>implementations of this feature quite complicated.

That's why I want to add it to the compiler, because only it can decide how
to determine it or reject it completly for such reasons. I can only write my
generic package, distribute it, and fail a few years later in a complicated
production enviroment (usually a few hours before deadline).

>>>> Problem 2: Defining Byte_Order of record representations
>
>> Unfortunly I have to deal with memory mapped I/O (i.e. network cards)
>
>You didn't mention this...

Sorry, I shortend the problem a bit.

>> You miss the point. Providing such packages does not allow the compiler to
>> generate good maschine code.
>
>You need the conversion package anyway, at least that's my experience.
>Otherwise, your code is quite unportable, as you're passing around
>invalid values.

If my suggestion is part of the AdaYY specification, it would be perfectly
portable. Currently only packed bit fields can be used to address
representation issues correctly in a portable way.

>> >> Problem 3: Static expressions of discriminants in record representations
>
>> *Gna* And now remove the limitation, that the discriminants have to appear
>> first.
>
>Aha, this was the intent of your comment (I thought you were talking
>about the source code location).  Are trailing size specifies really
>common?  To me, they don't make much sense.
>
>> Even better: Try to write a program, which derivates the type from a pointer.
>
>Sorry, what do you want to do?

The problem escaped from a 'multiprotocol router'. Please try to map a IPv4
header incl. payload and IP-header options.
 
    head_len at 0 range 0 .. 3; -- or 4 .. 7 depending on the bit order.
    ...
    payload at head_len*4 range 0 .. packet_len - 32*head_len;



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: AdaYY wish list from current projects
  2001-02-23 10:12       ` Lutz Donnerhacke
@ 2001-02-23 13:54         ` Florian Weimer
  2001-02-23 14:16           ` Lutz Donnerhacke
  2001-02-23 19:06         ` tmoran
  1 sibling, 1 reply; 17+ messages in thread
From: Florian Weimer @ 2001-02-23 13:54 UTC (permalink / raw)


lutz@iks-jena.de (Lutz Donnerhacke) writes:

> >You need the conversion package anyway, at least that's my experience.
> >Otherwise, your code is quite unportable, as you're passing around
> >invalid values.
> 
> If my suggestion is part of the AdaYY specification, it would be perfectly
> portable.

I think you've missed the point.  If you use enumeration
representation clauses which are sparse (i.e. not every representation
has a corresponding enumeration literal), you're dealing with invalid
representations.  If you never, ever copy any such values and always
check using the Valid attribute that the representation is not invalid
before using it in computations, you might actually have portable
code.  If you do not follow these rules, you end up with code which
depends heavily on the Ada implementation (even on the compiler flags
used), and which is probably less robust than it could be.

So I still claim that little endian/big endian integers are sufficient
for most (almost all?) applications and it's not necessary to an
endian property to enumeration types, or to add even more complexity
to representation clauses.

> >> Even better: Try to write a program, which derivates the type from a pointer.
> >
> >Sorry, what do you want to do?

Sorry, I still do not understand what you mean by 'derivates the type
from a pointer'.

> The problem escaped from a 'multiprotocol router'. Please try to map a IPv4
> header incl. payload and IP-header options.

Ah.  Well, obviously, you can't use a single record in this case.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: AdaYY wish list from current projects
  2001-02-23 13:54         ` Florian Weimer
@ 2001-02-23 14:16           ` Lutz Donnerhacke
  2001-02-23 15:04             ` Florian Weimer
  2001-02-23 19:06             ` tmoran
  0 siblings, 2 replies; 17+ messages in thread
From: Lutz Donnerhacke @ 2001-02-23 14:16 UTC (permalink / raw)


* Florian Weimer wrote:
>lutz@iks-jena.de (Lutz Donnerhacke) writes:
>> >You need the conversion package anyway, at least that's my experience.
>> >Otherwise, your code is quite unportable, as you're passing around
>> >invalid values.
>> 
>> If my suggestion is part of the AdaYY specification, it would be perfectly
>> portable.
>
>I think you've missed the point.

Yep. I talk about values crossing a storage_element boundary and you talk
about invalid values.

>If you use enumeration representation clauses which are sparse (i.e. not
>every representation has a corresponding enumeration literal), you're
>dealing with invalid representations.

The same is true for all subtypes I use:
  subtype Header_Length is Integer range 5 .. 15;

>If you never, ever copy any such values and always check using the Valid
>attribute that the representation is not invalid before using it in
>computations, you might actually have portable code.

Full ACK. But it's a difference between:
    if not data'Valid then ...
and
    declare
       data1 : Component_Type_1 := Endianess_Conversion_1 (data.f1);
       data2 : Component_Type_2 := Endianess_Conversion_2 (data.f2);
       data3 : Component_Type_3 := Endianess_Conversion_3 (data.f3);
       data4 : Component_Type_4 := Endianess_Conversion_4 (data.f4);
    begin
       if not data1'Valid or else not data2'Valid or else
          not data3'Valid or else not data4'Valid then
	   ...
       end if;
    end;

>So I still claim that little endian/big endian integers are sufficient
>for most (almost all?) applications and it's not necessary to an
>endian property to enumeration types, or to add even more complexity
>to representation clauses.

I do not talk about endianess of enumeration types but of repesentation
issues of record types.

>Sorry, I still do not understand what you mean by 'derivates the type
>from a pointer'.

procedure t is
   type pstring(len : Integer) is record
      data : String (1 .. len);
   end record;
   pragma Pack (pstring); --  record representation clause not possible
   
   ex : pstring;  --  Won't work;
   for ex'Address use 16#00000#;
begin
   Put_Line (Integer'Image (ex.len) & " => " & ex.data);
end t;

Using Address_To_Access_Conversions does solve the problem but is really ugly.

>> The problem escaped from a 'multiprotocol router'. Please try to map a IPv4
>> header incl. payload and IP-header options.
>
>Ah.  Well, obviously, you can't use a single record in this case.

So I'm stuck to implement gather-scatter from the beginning. ;-/



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: AdaYY wish list from current projects
  2001-02-23 14:16           ` Lutz Donnerhacke
@ 2001-02-23 15:04             ` Florian Weimer
  2001-02-23 15:15               ` Lutz Donnerhacke
  2001-02-23 19:06             ` tmoran
  1 sibling, 1 reply; 17+ messages in thread
From: Florian Weimer @ 2001-02-23 15:04 UTC (permalink / raw)


lutz@iks-jena.de (Lutz Donnerhacke) writes:

> Yep. I talk about values crossing a storage_element boundary and you
> talk about invalid values.

Oh, sorry.

I still have to see some code which shows that record representation
clauses are practicall even if the components occupy multiple storage
elements. ;-)

> procedure t is
>    type pstring(len : Integer) is record
>       data : String (1 .. len);
>    end record;
>    pragma Pack (pstring); --  record representation clause not possible
>    
>    ex : pstring;  --  Won't work;
>    for ex'Address use 16#00000#;
> begin
>    Put_Line (Integer'Image (ex.len) & " => " & ex.data);
> end t;

Perhaps you want to use a constrained integer type in conjunction with
a record discriminant with a default expression?

> >> The problem escaped from a 'multiprotocol router'. Please try to map a IPv4
> >> header incl. payload and IP-header options.
> >
> >Ah.  Well, obviously, you can't use a single record in this case.
> 
> So I'm stuck to implement gather-scatter from the beginning. ;-/

Why that?  You can still have the records in consecutive storage
locations, but you have to do some manual address calculations.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: AdaYY wish list from current projects
  2001-02-23 15:04             ` Florian Weimer
@ 2001-02-23 15:15               ` Lutz Donnerhacke
  2001-02-23 16:21                 ` Florian Weimer
  0 siblings, 1 reply; 17+ messages in thread
From: Lutz Donnerhacke @ 2001-02-23 15:15 UTC (permalink / raw)


* Florian Weimer wrote:
>I still have to see some code which shows that record representation
>clauses are practicall even if the components occupy multiple storage
>elements. ;-)

Try to map an ARP packet. Have fun.
Try to map an Pascal String with a 16bit length field.

>lutz@iks-jena.de (Lutz Donnerhacke) writes:
>> procedure t is
>>    type pstring(len : Integer) is record
>>       data : String (1 .. len);
>>    end record;
>>    pragma Pack (pstring); --  record representation clause not possible
>>    
>>    ex : pstring;  --  Won't work;
>>    for ex'Address use 16#00000#;
>> begin
>>    Put_Line (Integer'Image (ex.len) & " => " & ex.data);
>> end t;
>
>Perhaps you want to use a constrained integer type in conjunction with
>a record discriminant with a default expression?

  ex : pstring(x); for ex'Address use 16#00000#;
will compile, but ex.len is always x and not correlated to (16#00000#).

>>>> The problem escaped from a 'multiprotocol router'. Please try to
>>>> map a IPv4 header incl. payload and IP-header options.
>>>
>>>Ah.  Well, obviously, you can't use a single record in this case.
>>
>> So I'm stuck to implement gather-scatter from the beginning. ;-/
>
>Why that?  You can still have the records in consecutive storage
>locations, but you have to do some manual address calculations.

And than store those results in some meta data records called 'Packet.IP.v4'.
http://www.iks-jena.de/mitarb/lutz/ada/net/



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: AdaYY wish list from current projects
  2001-02-23 15:15               ` Lutz Donnerhacke
@ 2001-02-23 16:21                 ` Florian Weimer
  2001-02-23 16:31                   ` Lutz Donnerhacke
  0 siblings, 1 reply; 17+ messages in thread
From: Florian Weimer @ 2001-02-23 16:21 UTC (permalink / raw)


lutz@iks-jena.de (Lutz Donnerhacke) writes:

> >Perhaps you want to use a constrained integer type in conjunction with
> >a record discriminant with a default expression?
> 
>   ex : pstring(x); for ex'Address use 16#00000#;
> will compile, but ex.len is always x and not correlated to (16#00000#).

If there's a default expression, you can write 'ex : psring;'.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: AdaYY wish list from current projects
  2001-02-23 16:21                 ` Florian Weimer
@ 2001-02-23 16:31                   ` Lutz Donnerhacke
  2001-02-23 17:25                     ` Florian Weimer
  0 siblings, 1 reply; 17+ messages in thread
From: Lutz Donnerhacke @ 2001-02-23 16:31 UTC (permalink / raw)


* Florian Weimer wrote:
>lutz@iks-jena.de (Lutz Donnerhacke) writes:
>> >Perhaps you want to use a constrained integer type in conjunction with
>> >a record discriminant with a default expression?
>> 
>>   ex : pstring(x); for ex'Address use 16#00000#;
>> will compile, but ex.len is always x and not correlated to (16#00000#).
>
>If there's a default expression, you can write 'ex : psring;'.

If there would exists a default expression, ex.len would always be equal to
it.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: AdaYY wish list from current projects
  2001-02-23 16:31                   ` Lutz Donnerhacke
@ 2001-02-23 17:25                     ` Florian Weimer
  2001-02-26 11:22                       ` Lutz Donnerhacke
  0 siblings, 1 reply; 17+ messages in thread
From: Florian Weimer @ 2001-02-23 17:25 UTC (permalink / raw)


lutz@iks-jena.de (Lutz Donnerhacke) writes:

[record discriminants]

> >If there's a default expression, you can write 'ex : psring;'.
> 
> If there would exists a default expression, ex.len would always be equal to
> it.

No, it wouldn't, see 3.7.(28) (I wonder where this is more more
formally specified in the RM, however).



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: AdaYY wish list from current projects
  2001-02-23 10:12       ` Lutz Donnerhacke
  2001-02-23 13:54         ` Florian Weimer
@ 2001-02-23 19:06         ` tmoran
  2001-02-26 11:21           ` Lutz Donnerhacke
  1 sibling, 1 reply; 17+ messages in thread
From: tmoran @ 2001-02-23 19:06 UTC (permalink / raw)


>   head_len at 0 range 0 .. 3; -- or 4 .. 7 depending on the bit order.
>   ...
>   payload at head_len*4 range 0 .. packet_len - 32*head_len;
  I would expect the compiler to generate code for a static layout, but
surely the code for the above is asking a lot.  The compiler does a
lot for you, but there are limits.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: AdaYY wish list from current projects
  2001-02-23 14:16           ` Lutz Donnerhacke
  2001-02-23 15:04             ` Florian Weimer
@ 2001-02-23 19:06             ` tmoran
  2001-02-26 11:20               ` Lutz Donnerhacke
  1 sibling, 1 reply; 17+ messages in thread
From: tmoran @ 2001-02-23 19:06 UTC (permalink / raw)


What's wrong with:
   subtype String_Lengths is integer range 1 .. 32767;
   type pstring(len : String_Lengths) is record
      data : String (String_Lengths);
   end record;
   for pstring use record
     len at 0 range 0 .. 15;
   end record;

   ex : pstring(Max_Length_Of_This_String);
   for ex'Address use 16#00000#;
Yes, the compiler won't do your subscript range checking for you, but
you are going to import/export this data object to a non-Ada program
anyway.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: AdaYY wish list from current projects
  2001-02-23 19:06             ` tmoran
@ 2001-02-26 11:20               ` Lutz Donnerhacke
  0 siblings, 0 replies; 17+ messages in thread
From: Lutz Donnerhacke @ 2001-02-26 11:20 UTC (permalink / raw)


* tmoran@acm.org wrote:
>What's wrong with:
>   subtype String_Lengths is integer range 1 .. 32767;
>   type pstring(len : String_Lengths) is record
>      data : String (String_Lengths);
>   end record;
>   for pstring use record
>     len at 0 range 0 .. 15;
>   end record;

It's not portable, len should be little endian.

:   raw  : constant String := "\0\4Test";
:   test : pstring (String_Lengths'Last);
:   for test'Address use raw'Address;

warning: default initialization of "test" may modify "raw"
warning: use pragma Import for "test" to suppress initialization (RM B.1(24))

>Yes, the compiler won't do your subscript range checking for you, but

Even worse: Put_Line ("Len:" & plen'Image (test.len)); results in "Len: 1000".
And of course
   Put ("Data: >");
   for i in test.data'Range loop
      Put (test.data(i));
   end loop;
   Put_Line ("<");
will print the whole 1000 chars.

>you are going to import/export this data object to a non-Ada program
>anyway.

Ok, pragma Import does suppress the initialization:
with Ada.Text_IO, System; use Ada.Text_IO;

procedure t is
   subtype plen is Natural range 0 .. 1000;
   type pstring (len : plen := plen'Last) is record
      data : String (1 .. len);
   end record;
   for pstring use record
      len at 0 range 0 .. 15;
   end record;
   for pstring'Bit_Order use System.Low_Order_First;
   
   raw : constant String := ASCII.EOT & ASCII.NUL & "Test";
   test : pstring;
   for test'Address use raw'Address;
   pragma Import(Ada, test);
begin
   Put_Line ("Len:" & plen'Image (test.len));
   
   Put ("Data: >");
   for i in test.data'Range loop
      Put (test.data(i));
   end loop;
   Put_Line ("<");
end t;

compiles without warning and results in:
Len: 4
Data: >Test<

Great!

Using the opposite endianess causes:
t.adb:9:11: warning: multi-byte field specified with non-standard Bit_Order
t.adb:9:11: warning: bytes are not reversed (component is little-endian)

*Barf*



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: AdaYY wish list from current projects
  2001-02-23 19:06         ` tmoran
@ 2001-02-26 11:21           ` Lutz Donnerhacke
  0 siblings, 0 replies; 17+ messages in thread
From: Lutz Donnerhacke @ 2001-02-26 11:21 UTC (permalink / raw)


* tmoran@acm.org wrote:
>>   head_len at 0 range 0 .. 3; -- or 4 .. 7 depending on the bit order.
>>   ...
>>   payload at head_len*4 range 0 .. packet_len - 32*head_len;

>  I would expect the compiler to generate code for a static layout, but
>surely the code for the above is asking a lot.  The compiler does a
>lot for you, but there are limits.

So please add my 'wish' to the list. It's only ten month to Christmas.



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: AdaYY wish list from current projects
  2001-02-23 17:25                     ` Florian Weimer
@ 2001-02-26 11:22                       ` Lutz Donnerhacke
  0 siblings, 0 replies; 17+ messages in thread
From: Lutz Donnerhacke @ 2001-02-26 11:22 UTC (permalink / raw)


* Florian Weimer wrote:
>lutz@iks-jena.de (Lutz Donnerhacke) writes:
>[record discriminants]
>> >If there's a default expression, you can write 'ex : psring;'.
>> 
>> If there would exists a default expression, ex.len would always be equal to
>> it.
>
>No, it wouldn't,

Tested and found, that the initialization code will overwrite the given
value with the default expression unless I use pragma Import.



^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2001-02-26 11:22 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-02-20 20:50 AdaYY wish list from current projects Lutz Donnerhacke
2001-02-22 11:08 ` Florian Weimer
2001-02-22 13:02   ` Lutz Donnerhacke
2001-02-23  9:30     ` Florian Weimer
2001-02-23 10:12       ` Lutz Donnerhacke
2001-02-23 13:54         ` Florian Weimer
2001-02-23 14:16           ` Lutz Donnerhacke
2001-02-23 15:04             ` Florian Weimer
2001-02-23 15:15               ` Lutz Donnerhacke
2001-02-23 16:21                 ` Florian Weimer
2001-02-23 16:31                   ` Lutz Donnerhacke
2001-02-23 17:25                     ` Florian Weimer
2001-02-26 11:22                       ` Lutz Donnerhacke
2001-02-23 19:06             ` tmoran
2001-02-26 11:20               ` Lutz Donnerhacke
2001-02-23 19:06         ` tmoran
2001-02-26 11:21           ` Lutz Donnerhacke

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox