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: project euler 26
  2023-09-07  9:02  2%                               ` Dmitry A. Kazakov
@ 2023-09-08  1:32  0%                                 ` Ben Bacarisse
  0 siblings, 0 replies; 200+ results
From: Ben Bacarisse @ 2023-09-08  1:32 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

> On 2023-09-07 01:32, Ben Bacarisse wrote:
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
>> 
>>> On 2023-09-06 17:16, Ben Bacarisse wrote:
>>>
>>>> I am curious to know how reusable this is.  Can the packages be
>>>> instantiated in such a way that the argument ranges over the elements
>>>> of, say, and Ordered_Map?
>>>
>>> Sure:
>>>
>>>     with Ada.Containers.Ordered_Maps;
>>>
>>>     package Integer_Maps is
>>>        new Ada.Containers.Ordered_Maps (Integer, Integer);
>>>     use Integer_Maps;
>>>     package Cursor_Arguments is new Generic_Arguments (Cursor);
>> Ah!  So the arguments correspond to the "with" functions in the order
>> listed, and, since Cursor already has Next, there no need to specify
>> anything.
>
> Yes, because the formal argument is
>
>    with function Next (Value : Argument_Type)
>       return Argument_Type is <>;
>
> If it were
>
>    with function Next (Value : Argument_Type)
>       return Argument_Type;
>
> You would have to specify the actual. The part "is <>" tells to match a
> visible function Next.

Thanks.  I remember that now.  Given Ada's preference for words, it's a
mysterious choice.

>> There are a couple of details that prevent your Maximum_At function from
>> working properly in this case though.  First, we can't have an empty
>> map, because X.Last can't be compared with X.First when either is
>> No_Element, so the test for Right < Left fails before the desired error
>> can be raised.
>
> Yes, cursors is bad idea, in the end they all are pointers. No_Element is
> an equivalent of null which shows.
>
> However Maximum_At will propagate Constraint_Error if either of the bounds
> is No_Element. So the implementation would work.

Sure, but ideally we want the error we decided on for this situation.
Since the intent is to be generic, it's a shame to get one error with
some instantiations and a different one with others.

>> Second, if I try to use a Vector rather than an Ordered_Map, I am told
>> that:
>> test2.adb:97:05: error: instantiation error at line 12
>> test2.adb:97:05: error: no visible subprogram matches the specification for "<"
>> It would seem that vector cursors can't be compared using < (at least by
>> default).  Maybe the installation needs more arguments.
>
> Vector has a proper index type. All you have to do is. Given
>
>    package Integer_Vectors is
>       new Ada.Containers.Vectors (Integer, Integer);
>
> Wrap Element into a function:
>
>    V : Integer_Vectors.Vector;
>    function Element (Index : Integer) return Integer is
>    begin
>       return V.Element (Index);
>    end Element;
>    ...
>
> and use the wrapper.

Sure, but the hope was to write something that does not need new
code for new situations.  That's what makes it reusable.

>> Anyway, I am still not sure how to write a generic test for an empty
>> range.
>
> The problem is that the implementation of Cursor that breaks
> abstraction. The abstraction of an argument does not permit ideal
> non-values. Cursors and pointers have non-values. So if you want to test
> for non-values ahead, instead of surprising the function, you need to add a
> test for value validity to the abstraction:
>
> generic
>    -- Ordered argument
>    type Argument_Type is private;
>    with function Valid (Value : Argument_Type) return Boolean is <>;
>    ...
> package Generic_Arguments is
>
> Then you would pass Has_Element for it. For integers you would use wrapped
> X'Valid (there is no Integer'Valid, unfortunately. Only X'Valid where X is
> an object).

It's definitely getting what I call cumbersome.

>> It's possible I was not clear about what I was aiming for.  I was hoping
>> to be able to find the maximum of some arbitrary function, taking the
>> function's arguments from any sequential collection.
>
> That is a different abstraction. You need a generic collection instead of
> generic ordered values. E.g.
>
> generic
>    with package Arguments is new Ada.Containers.Ordered_Sets (<>);
>    with package Values is new Generic_Values (<>);
> package Generic_Comparable_Valued is
>    use Arguments, Values;
>    function Maximum_At
>             (  Domain : Set;
>                Func : access function (Argument : Element_Type)
>                       return Value_Type
>             )  return Value_Type;
>    -- Other useless functions
> end Generic_Comparable_Valued;
>
> package body Generic_Comparable_Valued is
>    function Maximum_At
>             (  Domain : Set;
>                Func : access function (Argument : Element_Type)
>                       return Value_Type
>             )  return Value_Type is
>       Max      : Value_Type;
>       Value    : Value_Type;
>       Position : Cursor;
>    begin
>       if Domain.Is_Empty then
>          raise Constraint_Error with "Empty set";
>       end if;
>       Position := Domain.First;
>       Max := Func (Element (Position));
>       while Position /= Domain.Last loop
>          Position := Next (Position);
>          Value := Func (Element (Position));
>          if Max < Value then
>             Max := Value;
>          end if;
>       end loop;
>       return Max;
>    end Maximum_At;
> end Generic_Comparable_Valued;
>
>> Either a simple
>> range of values, an array or vector of values, a list of values or even
>> an ordered map of values -- any ordered list of values.
>
> In practice such abstraction have too much physical and mental
> overhead. E.g. large sets of values implemented differently from
> Ada.Containers.Ordered_Sets depending on the operations required. For
> example, let you need a set complement? Usually programmers simply stick
> with software patterns instead. Too much reliance of libraries make
> programs incoherent.

The core of my Haskell solution is just a function decimalRepeatLength
that returns the repeat length given a divisor.  But once I'd got the
answer (by applying it to 2 to 999 and getting the maximum) I wondered
what would happen if the numbers were not in a simple range.  Is it easy
to write a `maximisedOver` function that finds the maximum of some
function over any ordered collection (technically, a "foldable" type in
Haskell).

Well, yes, it is easy:

  function `maximisedOver` anything = maximum (fmap function anything)

so the solution to the project Euler problem is just

  decimalRepeatLength `maximisedOver` [2..999]

but I can also find the maximum of this (or any other suitable) function
over an array, a hash map, a vector... whatever.  No code changes
anywhere.  It even works with arrays of any number of dimensions
regardless of the index bounds.

maximisedOver is genuinely generic and reusable.

I don't think this is incoherent.  The Haskell libraries ensure that any
collection that is logically foldable is indeed foldable.

>> The bottom line is the last argument should be something very general
>> like the Period function.
>> A fix (though it's not really ideal) would be to use function
>> composition here (inventing . as the composition operator):
>>    Map_Functions.Maximum_At (X.First, X.Last, Period'Access
>> . Element'Access)
>> but I don't think Ada has a function composition operator, does it?
>
> No as it would require closures.

What closure is required for a function composition?  There is no
environment to "close over".

> So you can have a generic composition
> operator, no problem, but not a first-class one. However you can simply add
> Maximum_At with four arguments to the package.

This may be the closest we can get with Ada.

>> Another solution would be to write Maximum_At so that it knows it has a
>> cursor argument, but then I don't think it would work for native arrays,
>> would it?  And we'd loose plain ranges altogether.
>
> You can write a generic package creating array cursors:
>
> generic
>    type Index_Type is (<>);
>    type Element_Type is private;
>    type Array_Type is array (Index_Type range <>) of Element_Type;
> package Array_Cursors is
>    type Cursor is private;
>    function First (Container : Array_Type) return Cursor;
>    function Element (Position : Cursor) return Element_Type;
>    function "<" (Left, Right : Cursor) return Boolean;
>    ...
> private
>    package Dirty_Tricks is
>       new System.Address_To_Access_Conversions (Array_Type);
>    use Dirty_Tricks;
>    type Cursor is record
>       Domain : Object_Pointer;
>       Index  : Index_Type;
>    end record;
> end Array_Cursors;
>
> package body Array_Cursors is
>    function "<" (Left, Right : Cursor) return Boolean is
>    begin
>       if Left.Domain = null or else Left.Domain /= Right.Domain then
>          raise Constraint_Error with "Incomparable cursors";
>       end if;
>       return Left.Index < Right.Index;
>    end "<";
>
>    function Element (Position : Cursor) return Element_Type is
>    begin
>       if Position.Domain = null or else
>          Position.Index not in Position.Domain'Range
>       then
>          raise Constraint_Error with "Invalid cursor";
>       else
>          return Position.Domain (Position.Index);
>       end if;
>    end Element;
>
>    function First (Container : Array_Type) return Cursor is
>    begin
>       if Container'Length = 0 then
>          raise Constraint_Error with "Empty array";
>       else
>          return (To_Pointer (Container'Address), Container'First);
>       end if;
>    end First;
>
> end Array_Cursors;

That's a lot just to use something that is supposed to be reusable.

>> You seem to be on your own as far as helping out is concerned!
>
> Because it started as a numeric puzzle. You should have asked directly
> about generics or tagged types instead.

It only occurred to me after writing the non-generic solution.  I
remember Ada as being something of a pioneer in it's attempt to provide
generic solutions, so I wondered how far things had come.  I don't think
something really widely reusable is possible in this case.

-- 
Ben.

^ permalink raw reply	[relevance 0%]

* Re: project euler 26
  @ 2023-09-07  9:02  2%                               ` Dmitry A. Kazakov
  2023-09-08  1:32  0%                                 ` Ben Bacarisse
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2023-09-07  9:02 UTC (permalink / raw)


On 2023-09-07 01:32, Ben Bacarisse wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> On 2023-09-06 17:16, Ben Bacarisse wrote:
>>
>>> I am curious to know how reusable this is.  Can the packages be
>>> instantiated in such a way that the argument ranges over the elements
>>> of, say, and Ordered_Map?
>>
>> Sure:
>>
>>     with Ada.Containers.Ordered_Maps;
>>
>>     package Integer_Maps is
>>        new Ada.Containers.Ordered_Maps (Integer, Integer);
>>     use Integer_Maps;
>>     package Cursor_Arguments is new Generic_Arguments (Cursor);
> 
> Ah!  So the arguments correspond to the "with" functions in the order
> listed, and, since Cursor already has Next, there no need to specify
> anything.

Yes, because the formal argument is

    with function Next (Value : Argument_Type)
       return Argument_Type is <>;

If it were

    with function Next (Value : Argument_Type)
       return Argument_Type;

You would have to specify the actual. The part "is <>" tells to match a 
visible function Next.

> There are a couple of details that prevent your Maximum_At function from
> working properly in this case though.  First, we can't have an empty
> map, because X.Last can't be compared with X.First when either is
> No_Element, so the test for Right < Left fails before the desired error
> can be raised.

Yes, cursors is bad idea, in the end they all are pointers. No_Element 
is an equivalent of null which shows.

However Maximum_At will propagate Constraint_Error if either of the 
bounds is No_Element. So the implementation would work.

> Second, if I try to use a Vector rather than an Ordered_Map, I am told
> that:
> 
> test2.adb:97:05: error: instantiation error at line 12
> test2.adb:97:05: error: no visible subprogram matches the specification for "<"
> 
> It would seem that vector cursors can't be compared using < (at least by
> default).  Maybe the installation needs more arguments.

Vector has a proper index type. All you have to do is. Given

    package Integer_Vectors is
       new Ada.Containers.Vectors (Integer, Integer);

Wrap Element into a function:

    V : Integer_Vectors.Vector;
    function Element (Index : Integer) return Integer is
    begin
       return V.Element (Index);
    end Element;
    ...

and use the wrapper.

> Anyway, I am still not sure how to write a generic test for an empty
> range.

The problem is that the implementation of Cursor that breaks 
abstraction. The abstraction of an argument does not permit ideal 
non-values. Cursors and pointers have non-values. So if you want to test 
for non-values ahead, instead of surprising the function, you need to 
add a test for value validity to the abstraction:

generic
    -- Ordered argument
    type Argument_Type is private;
    with function Valid (Value : Argument_Type) return Boolean is <>;
    ...
package Generic_Arguments is

Then you would pass Has_Element for it. For integers you would use 
wrapped X'Valid (there is no Integer'Valid, unfortunately. Only X'Valid 
where X is an object).

> It's possible I was not clear about what I was aiming for.  I was hoping
> to be able to find the maximum of some arbitrary function, taking the
> function's arguments from any sequential collection.

That is a different abstraction. You need a generic collection instead 
of generic ordered values. E.g.

generic
    with package Arguments is new Ada.Containers.Ordered_Sets (<>);
    with package Values is new Generic_Values (<>);
package Generic_Comparable_Valued is
    use Arguments, Values;
    function Maximum_At
             (  Domain : Set;
                Func : access function (Argument : Element_Type)
                       return Value_Type
             )  return Value_Type;
    -- Other useless functions
end Generic_Comparable_Valued;

package body Generic_Comparable_Valued is
    function Maximum_At
             (  Domain : Set;
                Func : access function (Argument : Element_Type)
                       return Value_Type
             )  return Value_Type is
       Max      : Value_Type;
       Value    : Value_Type;
       Position : Cursor;
    begin
       if Domain.Is_Empty then
          raise Constraint_Error with "Empty set";
       end if;
       Position := Domain.First;
       Max := Func (Element (Position));
       while Position /= Domain.Last loop
          Position := Next (Position);
          Value := Func (Element (Position));
          if Max < Value then
             Max := Value;
          end if;
       end loop;
       return Max;
    end Maximum_At;
end Generic_Comparable_Valued;

> Either a simple
> range of values, an array or vector of values, a list of values or even
> an ordered map of values -- any ordered list of values.

In practice such abstraction have too much physical and mental overhead. 
E.g. large sets of values implemented differently from 
Ada.Containers.Ordered_Sets depending on the operations required. For 
example, let you need a set complement? Usually programmers simply stick 
with software patterns instead. Too much reliance of libraries make 
programs incoherent.

> The bottom line is the last argument should be something very general
> like the Period function.
> 
> A fix (though it's not really ideal) would be to use function
> composition here (inventing . as the composition operator):
> 
>    Map_Functions.Maximum_At (X.First, X.Last, Period'Access . Element'Access)
> 
> but I don't think Ada has a function composition operator, does it?

No as it would require closures. So you can have a generic composition 
operator, no problem, but not a first-class one. However you can simply 
add Maximum_At with four arguments to the package.

> Another solution would be to write Maximum_At so that it knows it has a
> cursor argument, but then I don't think it would work for native arrays,
> would it?  And we'd loose plain ranges altogether.

You can write a generic package creating array cursors:

generic
    type Index_Type is (<>);
    type Element_Type is private;
    type Array_Type is array (Index_Type range <>) of Element_Type;
package Array_Cursors is
    type Cursor is private;
    function First (Container : Array_Type) return Cursor;
    function Element (Position : Cursor) return Element_Type;
    function "<" (Left, Right : Cursor) return Boolean;
    ...
private
    package Dirty_Tricks is
       new System.Address_To_Access_Conversions (Array_Type);
    use Dirty_Tricks;
    type Cursor is record
       Domain : Object_Pointer;
       Index  : Index_Type;
    end record;
end Array_Cursors;

package body Array_Cursors is
    function "<" (Left, Right : Cursor) return Boolean is
    begin
       if Left.Domain = null or else Left.Domain /= Right.Domain then
          raise Constraint_Error with "Incomparable cursors";
       end if;
       return Left.Index < Right.Index;
    end "<";

    function Element (Position : Cursor) return Element_Type is
    begin
       if Position.Domain = null or else
          Position.Index not in Position.Domain'Range
       then
          raise Constraint_Error with "Invalid cursor";
       else
          return Position.Domain (Position.Index);
       end if;
    end Element;

    function First (Container : Array_Type) return Cursor is
    begin
       if Container'Length = 0 then
          raise Constraint_Error with "Empty array";
       else
          return (To_Pointer (Container'Address), Container'First);
       end if;
    end First;

end Array_Cursors;

> But then (I think) the only function one could pass would be something
> like Element as in you example above.  Using an ordered set of integers
> would not allow
> 
>    Map_Functions.Maximum_At (Set.First, Set.Last, Period'Access)
> 
> would it?

Ordered_Set cursors are ordered like Ordered_Map ones, so it should work.

>>> I am asking you but I am also the group.  I appreciate your help,
>>> but don't want you to feel any obligation to keep helping!
>>
>> No problem.
> 
> You seem to be on your own as far as helping out is concerned!

Because it started as a numeric puzzle. You should have asked directly 
about generics or tagged types instead.

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

^ permalink raw reply	[relevance 2%]

* Re: GtkAda callback and event
  2021-09-05 15:12  0%           ` Dmitry A. Kazakov
@ 2021-09-05 15:20  0%             ` DrPi
  0 siblings, 0 replies; 200+ results
From: DrPi @ 2021-09-05 15:20 UTC (permalink / raw)


Le 05/09/2021 à 17:12, Dmitry A. Kazakov a écrit :
> On 2021-09-05 17:04, DrPi wrote:
>> Le 05/09/2021 à 16:58, DrPi a écrit :
>>> Le 05/09/2021 à 16:48, Dmitry A. Kazakov a écrit :
>>>> On 2021-09-05 15:50, DrPi wrote:
>>>>> Le 05/09/2021 à 00:29, Dmitry A. Kazakov a écrit :
>>>>
>>>>> With "Gtk.Arguments.Unchecked_To_Gdk_Event_Motion (Params, 1);" , I 
>>>>> get an error :
>>>>> expected private type "C_GValues" defined at glib-values.ads:53
>>>>> found private type "GValues" defined at glib-values.ads:48
>>>>
>>>> I see, then you must to implement it yourself. It could be something 
>>>> like this (not tested):
>>>>
>>>>     package Conversions is
>>>>        new System.Address_To_Access_Conversions (Gdk_Event_Motion);
>>>>
>>>>     Event : Gdk_Event_Motion renames
>>>>             Conversions.To_Pointer (Get_Address (Nth (Params, 1))).all;
>>>>
>>>
>>> So, Gtk.Arguments.Unchecked_To_Gdk_Event_Motion is useless ?
>> Like all subprograms accepting C_GValues as a parameter ?
> 
> It is a part of GValues object. But you could create a child package 
> that would have access to the internals of GValue and get access to 
> C_GValues in GValue.
> 
I didn't know I can create a  child Package of a GtkAda Package myself.

Thanks for all these explanations Dmitry.

Regards,
Nicolas

^ permalink raw reply	[relevance 0%]

* Re: GtkAda callback and event
  2021-09-05 15:04  0%         ` DrPi
@ 2021-09-05 15:12  0%           ` Dmitry A. Kazakov
  2021-09-05 15:20  0%             ` DrPi
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2021-09-05 15:12 UTC (permalink / raw)


On 2021-09-05 17:04, DrPi wrote:
> Le 05/09/2021 à 16:58, DrPi a écrit :
>> Le 05/09/2021 à 16:48, Dmitry A. Kazakov a écrit :
>>> On 2021-09-05 15:50, DrPi wrote:
>>>> Le 05/09/2021 à 00:29, Dmitry A. Kazakov a écrit :
>>>
>>>> With "Gtk.Arguments.Unchecked_To_Gdk_Event_Motion (Params, 1);" , I 
>>>> get an error :
>>>> expected private type "C_GValues" defined at glib-values.ads:53
>>>> found private type "GValues" defined at glib-values.ads:48
>>>
>>> I see, then you must to implement it yourself. It could be something 
>>> like this (not tested):
>>>
>>>     package Conversions is
>>>        new System.Address_To_Access_Conversions (Gdk_Event_Motion);
>>>
>>>     Event : Gdk_Event_Motion renames
>>>             Conversions.To_Pointer (Get_Address (Nth (Params, 1))).all;
>>>
>>
>> So, Gtk.Arguments.Unchecked_To_Gdk_Event_Motion is useless ?
> Like all subprograms accepting C_GValues as a parameter ?

It is a part of GValues object. But you could create a child package 
that would have access to the internals of GValue and get access to 
C_GValues in GValue.

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

^ permalink raw reply	[relevance 0%]

* Re: GtkAda callback and event
  2021-09-05 14:58  0%       ` DrPi
@ 2021-09-05 15:04  0%         ` DrPi
  2021-09-05 15:12  0%           ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: DrPi @ 2021-09-05 15:04 UTC (permalink / raw)


Le 05/09/2021 à 16:58, DrPi a écrit :
> Le 05/09/2021 à 16:48, Dmitry A. Kazakov a écrit :
>> On 2021-09-05 15:50, DrPi wrote:
>>> Le 05/09/2021 à 00:29, Dmitry A. Kazakov a écrit :
>>
>>> With "Gtk.Arguments.Unchecked_To_Gdk_Event_Motion (Params, 1);" , I 
>>> get an error :
>>> expected private type "C_GValues" defined at glib-values.ads:53
>>> found private type "GValues" defined at glib-values.ads:48
>>
>> I see, then you must to implement it yourself. It could be something 
>> like this (not tested):
>>
>>     package Conversions is
>>        new System.Address_To_Access_Conversions (Gdk_Event_Motion);
>>
>>     Event : Gdk_Event_Motion renames
>>             Conversions.To_Pointer (Get_Address (Nth (Params, 1))).all;
>>
> 
> So, Gtk.Arguments.Unchecked_To_Gdk_Event_Motion is useless ?
Like all subprograms accepting C_GValues as a parameter ?

^ permalink raw reply	[relevance 0%]

* Re: GtkAda callback and event
  2021-09-05 14:48  5%     ` Dmitry A. Kazakov
@ 2021-09-05 14:58  0%       ` DrPi
  2021-09-05 15:04  0%         ` DrPi
  0 siblings, 1 reply; 200+ results
From: DrPi @ 2021-09-05 14:58 UTC (permalink / raw)


Le 05/09/2021 à 16:48, Dmitry A. Kazakov a écrit :
> On 2021-09-05 15:50, DrPi wrote:
>> Le 05/09/2021 à 00:29, Dmitry A. Kazakov a écrit :
> 
>> With "Gtk.Arguments.Unchecked_To_Gdk_Event_Motion (Params, 1);" , I 
>> get an error :
>> expected private type "C_GValues" defined at glib-values.ads:53
>> found private type "GValues" defined at glib-values.ads:48
> 
> I see, then you must to implement it yourself. It could be something 
> like this (not tested):
> 
>     package Conversions is
>        new System.Address_To_Access_Conversions (Gdk_Event_Motion);
> 
>     Event : Gdk_Event_Motion renames
>             Conversions.To_Pointer (Get_Address (Nth (Params, 1))).all;
> 

So, Gtk.Arguments.Unchecked_To_Gdk_Event_Motion is useless ?

^ permalink raw reply	[relevance 0%]

* Re: GtkAda callback and event
  @ 2021-09-05 14:48  5%     ` Dmitry A. Kazakov
  2021-09-05 14:58  0%       ` DrPi
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2021-09-05 14:48 UTC (permalink / raw)


On 2021-09-05 15:50, DrPi wrote:
> Le 05/09/2021 à 00:29, Dmitry A. Kazakov a écrit :

> With "Gtk.Arguments.Unchecked_To_Gdk_Event_Motion (Params, 1);" , I get 
> an error :
> expected private type "C_GValues" defined at glib-values.ads:53
> found private type "GValues" defined at glib-values.ads:48

I see, then you must to implement it yourself. It could be something 
like this (not tested):

    package Conversions is
       new System.Address_To_Access_Conversions (Gdk_Event_Motion);

    Event : Gdk_Event_Motion renames
            Conversions.To_Pointer (Get_Address (Nth (Params, 1))).all;

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

^ permalink raw reply	[relevance 5%]

* Re: Printing the address
       [not found]     <609a5eaf$0$20558$e4fe514c@news.kpn.nl>
@ 2021-05-11 12:35  6% ` Maxim Reznik
  0 siblings, 0 replies; 200+ results
From: Maxim Reznik @ 2021-05-11 12:35 UTC (permalink / raw)


Actually, you don't need the address image to find if it is null. You can print instead

Put_Line (Boolean'Image (Boxes (n) = null));

When you really need the address image you can use

function System.Address_Image (A : Address) return String;

and an instantiation of

System.Address_To_Access_Conversions

generic package to convert Box_Acces value to System.Address.

PS. BTW, I would use a debugger in such cases.

^ permalink raw reply	[relevance 6%]

* Re: Record initialisation question
  2021-01-12 15:01  0%         ` Shark8
@ 2021-01-14 21:32  0%           ` Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2021-01-14 21:32 UTC (permalink / raw)


Shark8 <onewingedshark@gmail.com> writes:

> On Tuesday, January 12, 2021 at 4:38:24 AM UTC-7, Simon Wright wrote:
>> Shark8 writes: 
>> 
>> >> I'll try it but I've just faced another problem where a component of 
>> >> another record is the address of the record itself. 
>> > 
>> > Type Example; 
>> > Function To_Address( Input : Access Example ) return System.Address 
>> > with Inline; 
>> > 
>> > Type Example is limited record 
>> > Addr : System.Address := To_Address(Example'Access); 
>> > End record; 
>> > 
>> > Package Cvt is new System.Address_To_Access_Conversions(Example); 
>> > Function To_Address( Input : Access Example ) return System.Address is 
>> > ( Cvt.To_Address( Input.all'Access ) );

>> (what is it with this weird casing "convention" you use? makes the code 
>> quite hard to read ...)
> Really?
> How so?

Just looking at the first line, I see

   Type Example;

and I don't recognise it as Ada; I think that this is a textual comment
saying that this is an example relating in some way to types. Similar,
but a little less distracting, with other keywords throughout.

What is the convention? Is it perhaps that the first word on a line gets
capitalised? but then, in the second line, we have

   ... Input : Access Example ) return ...

and the third line starts with "with".

So it's just some keywords that get capitalised.

Basically, I find it jarring and distracting.

We would disagree about spacing round parentheses as well.

De gustibus ...!

^ permalink raw reply	[relevance 0%]

* Re: Record initialisation question
  2021-01-11 21:48  6%     ` Shark8
  2021-01-12 11:38  0%       ` Simon Wright
@ 2021-01-14 12:58  5%       ` DrPi
  1 sibling, 0 replies; 200+ results
From: DrPi @ 2021-01-14 12:58 UTC (permalink / raw)


Le 11/01/2021 à 22:48, Shark8 a écrit :
>> I'll try it but I've just faced another problem where a component of
>> another record is the address of the record itself.
> 
>      Type Example;
>      Function To_Address( Input : Access Example ) return System.Address
>         with Inline;
>      
>      Type Example is limited record
>          Addr : System.Address := To_Address(Example'Access);
>      End record;
>      
>      Package Cvt is new System.Address_To_Access_Conversions(Example);
>      Function To_Address( Input : Access Example ) return System.Address is
>        ( Cvt.To_Address( Input.all'Access ) );
> 

System.Address_To_Access_Conversions() is not compatible with 
No_Elaboration_Code_All pragma.

No elaboration code is mandatory since the structure of data go in FLASH 
memory.

^ permalink raw reply	[relevance 5%]

* Re: Record initialisation question
  2021-01-12 11:38  0%       ` Simon Wright
@ 2021-01-12 15:01  0%         ` Shark8
  2021-01-14 21:32  0%           ` Simon Wright
  0 siblings, 1 reply; 200+ results
From: Shark8 @ 2021-01-12 15:01 UTC (permalink / raw)


On Tuesday, January 12, 2021 at 4:38:24 AM UTC-7, Simon Wright wrote:
> Shark8 writes: 
> 
> >> I'll try it but I've just faced another problem where a component of 
> >> another record is the address of the record itself. 
> > 
> > Type Example; 
> > Function To_Address( Input : Access Example ) return System.Address 
> > with Inline; 
> > 
> > Type Example is limited record 
> > Addr : System.Address := To_Address(Example'Access); 
> > End record; 
> > 
> > Package Cvt is new System.Address_To_Access_Conversions(Example); 
> > Function To_Address( Input : Access Example ) return System.Address is 
> > ( Cvt.To_Address( Input.all'Access ) );
> OP wanted to place the data structures in ROM, the chance of this 
> working looks pretty remote 
Yeah, it does, if ROM's the target... but it might work.
The "right way" would be to have an Address-typed parameter on the record, defaulting with Record_Type'Address (using the same Name_in_Definition'Access trick to get the address of the component being created), but we cannot declare discriminants which are not non-scalar or non-access. The other way to do this might be a bit-vector sized as an address, then using Unchecked conversion as the default value.

> (what is it with this weird casing "convention" you use? makes the code 
> quite hard to read ...)
Really?
How so?

^ permalink raw reply	[relevance 0%]

* Re: Record initialisation question
  2021-01-11 21:48  6%     ` Shark8
@ 2021-01-12 11:38  0%       ` Simon Wright
  2021-01-12 15:01  0%         ` Shark8
  2021-01-14 12:58  5%       ` DrPi
  1 sibling, 1 reply; 200+ results
From: Simon Wright @ 2021-01-12 11:38 UTC (permalink / raw)


Shark8 <onewingedshark@gmail.com> writes:

>> I'll try it but I've just faced another problem where a component of 
>> another record is the address of the record itself. 
>
>     Type Example;
>     Function To_Address( Input : Access Example ) return System.Address
>        with Inline;
>     
>     Type Example is limited record
>         Addr : System.Address := To_Address(Example'Access);
>     End record;
>     
>     Package Cvt is new System.Address_To_Access_Conversions(Example);
>     Function To_Address( Input : Access Example ) return System.Address is
>       ( Cvt.To_Address( Input.all'Access ) );

OP wanted to place the data structures in ROM, the chance of this
working looks pretty remote

(what is it with this weird casing "convention" you use? makes the code
quite hard to read ...)

^ permalink raw reply	[relevance 0%]

* Re: Record initialisation question
  @ 2021-01-11 21:48  6%     ` Shark8
  2021-01-12 11:38  0%       ` Simon Wright
  2021-01-14 12:58  5%       ` DrPi
  0 siblings, 2 replies; 200+ results
From: Shark8 @ 2021-01-11 21:48 UTC (permalink / raw)


> I'll try it but I've just faced another problem where a component of 
> another record is the address of the record itself. 

    Type Example;
    Function To_Address( Input : Access Example ) return System.Address
       with Inline;
    
    Type Example is limited record
        Addr : System.Address := To_Address(Example'Access);
    End record;
    
    Package Cvt is new System.Address_To_Access_Conversions(Example);
    Function To_Address( Input : Access Example ) return System.Address is
      ( Cvt.To_Address( Input.all'Access ) );

^ permalink raw reply	[relevance 6%]

* Re: Messing with access types...
  @ 2020-12-28 11:43  6%   ` Marek
  0 siblings, 0 replies; 200+ results
From: Marek @ 2020-12-28 11:43 UTC (permalink / raw)


On 28.12.2020 11:14, Dmitry A. Kazakov wrote:
> 
> What are you trying to achieve? Because the code does not make much
> sense to me.
> 
> P.S. If you are trying to do some C bindings flat arrays are easier
> choice than Interfaces.C.Pointers. C has no arrays, but pointers. Ada's
> arrays are never compatible with any pointers, except when flat.
> Therefore using access to String would be wrong in most, if not all, cases.
> 

Code is a fragment some plugin framework for host written in C. When
plugin is initialized it receives pointer to host features. Then I can
scan them to find concrete feature (Id) and retrieve data.
Problem is with instantiation generic function Get_Data, more precisely
in line:

   return T_Access (ATA.To_Pointer (F.Data));

OK, some changes to code to clear view:

with System;

package Util is

   type Feature is record
      Id  : Integer;
      Data : System.Address;
   end record;

   type Feature_Access is access all Feature;

   Null_Feature : constant Feature := (0, System.Null_Address);

   type Feature_Array is array (Natural range <>) of aliased Feature;

   generic
      type T is private;
      type T_Access is access all T;
   function Get_Data (H : access Feature; Id : Integer) return T_Access;

   generic
      type T is private;
      type T_Access is access all T;
   function Get_Query
     (H        : access Feature; Id : Integer; Data : in out T_Access;
      Required : Boolean) return Integer;

end Util;

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

pragma Ada_2012;

with Interfaces.C.Pointers;

with System.Address_To_Access_Conversions;

package body Util is

   package Ptr is new Interfaces.C.Pointers
     (Index              => Natural,
      Element            => Feature,
      Element_Array      => Feature_Array,
      Default_Terminator => Null_Feature);

   use Ptr;

   --------------
   -- Get_Data --
   --------------

   function Get_Data (H : access Feature; Id : Integer) return T_Access
   is
      Pointer : Ptr.Pointer := Ptr.Pointer (H);

      package ATA is new System.Address_To_Access_Conversions (T);

   begin
      if H /= null then
         loop
            declare
               F : access Feature := Pointer;
            begin
               if Id = F.Id then
                  return T_Access (ATA.To_Pointer (F.Data));
               end if;
            end;

            Ptr.Increment (Pointer);

            exit when Pointer = null;

         end loop;
      end if;

      return null;
   end Get_Data;

   ---------------
   -- Get_Query --
   ---------------

   function Get_Query
     (H        : access Feature; Id : Integer; Data : in out T_Access;
      Required : Boolean) return Integer
   is
      function Get is new Get_Data (T, T_Access);
   begin

      Data := Get (H, Id);

      if Required and (Data /= null) then
         return Id;
      end if;

      return 0;
   end Get_Query;

end Util;

^ permalink raw reply	[relevance 6%]

* Messing with access types...
@ 2020-12-28  9:44  5% Marek
    0 siblings, 1 reply; 200+ results
From: Marek @ 2020-12-28  9:44 UTC (permalink / raw)


Hello,

I have some code:

- util.ads:

with System;

package Util is

   type Handle is record
      Str  : access String;
      Data : System.Address;
   end record;

   type Handle_Access is access all Handle;

   Null_Handle : constant Handle := (null, System.Null_Address);

   type Handle_Array is array (Natural range <>) of aliased Handle;

   generic
      type T is private;
      type T_Access is access all T;
   function Get_Data (H : access Handle; Str : access String) return
T_Access;

   generic
      type T is private;
      type T_Access is access all T;
   function Get_Query
     (H        : access Handle; Str : access String; Data : in out T_Access;
      Required : Boolean) return access String;

end Util;

- util.adb

pragma Ada_2012;

with Interfaces.C.Pointers;

with System.Address_To_Access_Conversions;

package body Util is

   package Ptr is new Interfaces.C.Pointers
     (Index              => Natural,
      Element            => Handle,
      Element_Array      => Handle_Array,
      Default_Terminator => Null_Handle);

   use Ptr;

   --------------
   -- Get_Data --
   --------------

   function Get_Data (H : access Handle; Str : access String) return
T_Access
   is
      Pointer : Ptr.Pointer := Ptr.Pointer (H);

      package ATA is new System.Address_To_Access_Conversions (T);

   begin
      if H /= null then
         loop
            declare
               F : access Handle := Pointer;
            begin
               if Str.all = F.Str.all then
                  return T_Access (ATA.To_Pointer (F.Data));
               end if;
            end;

            Ptr.Increment (Pointer);

            exit when Pointer = null;

         end loop;
      end if;

      return null;
   end Get_Data;

   ---------------
   -- Get_Query --
   ---------------

   function Get_Query
     (H        : access Handle; Str : access String; Data : in out T_Access;
      Required : Boolean) return access String
   is
      function Get is new Get_Data (T, T_Access);
   begin

      Data := Get (H, Str);

      if Required and (Data /= null) then
         return Str;
      end if;

      return null;
   end Get_Query;

end Util;

- test.adb

pragma Ada_2012;

with Util;

procedure Test is
   use Util;

   type Some_Record is record
      Foo : Integer;
   end record;

   type Some_Record_Access is access all Some_Record;

   Test_Record : Some_Record_Access;

   H : access Handle := null;

   Str : access String := new String'("Test");

   function Query is new Get_Query (Some_Record, Some_Record_Access);

   Result : access String := Query (H, Str, Test_Record, False);
begin
   null;
end Test;

When I try to compile test.adb I get some warnings:

Compile
   [Ada]          test.adb
test.adb:20:04: warning: in instantiation at util.adb:34
test.adb:20:04: warning: in instantiation at util.adb:56
test.adb:20:04: warning: accessibility check failure
test.adb:20:04: warning: "Program_Error" will be raised at run time
test.adb:20:04: warning: in instantiation at util.adb:34
test.adb:20:04: warning: in instantiation at util.adb:56
test.adb:20:04: warning: cannot convert local pointer to non-local
access type
test.adb:20:04: warning: Program_Error will be raised at run time
   [Ada]          util.adb
Bind
   [gprbind]      test.bexch
   [Ada]          test.ali
Link
   [link]         test.adb
[2020-12-28 10:30:50] process terminated successfully, elapsed time: 00.92s

I tried also to move every local (to Test procedure) variables to global
scope but result is the same.

What is going on? Can you explain where is the problem?
thanks in advance

Marek

^ permalink raw reply	[relevance 5%]

* Re: How can one record component be local and another not?
  @ 2020-05-06 19:31  3%       ` hreba
  0 siblings, 0 replies; 200+ results
From: hreba @ 2020-05-06 19:31 UTC (permalink / raw)


On 5/5/20 9:08 PM, Niklas Holsti wrote:
> 
> I don't understand -- System.Address is not an access type; why do you 
> need to use an access type to produce this parameter? Do you need a 
> pointer to the "params" component?
> 
> Perhaps you can show a bit more of the actual code that has the problem?
> 

Ok, I'll try to make it comprehensible without throwing a lot of code at 
you.

I am writing a thick binding to the GSL library odeiv2 for numerically 
integrating ODEs (ordinary differential equations). I already have the 
thin binding gsl_odeiv2_h.ads. For initialization, I have to call the 
following subprogram of the thin binding:

    function gsl_odeiv2_driver_alloc_y_new
      (sys : access constant gsl_odeiv2_system;
       T : access constant gsl_odeiv2_step_type;
       hstart : double;
       epsabs : double;
       epsrel : double) return access gsl_odeiv2_driver;
    pragma Import (C, gsl_odeiv2_driver_alloc_y_new, 
"gsl_odeiv2_driver_alloc_y_new");

Parameter sys defines the ODE; its type is

    type gsl_odeiv2_system is record
       c_function : access function
            (arg1 : double;
             arg2 : access double;
             arg3 : access double;
             arg4 : System.Address) return int;
       jacobian : access function
            (arg1 : double;
             arg2 : access double;
             arg3 : access double;
             arg4 : access double;
             arg5 : System.Address) return int;
       dimension : aliased size_t;
       params : System.Address;
    end record;
    pragma Convention (C_Pass_By_Copy, gsl_odeiv2_system);

Later, during integration, c_function() and jacobian() will be called 
with parameters of type System.Address (arg4 and arg5 resp.). These 
parameters must be passed as params inside sys to 
gsl_odeiv2_driver_alloc_y_new().

Now to my own code (most of the thin binding was created automatically 
with g++ -c -fdump-ada-spec-slim). Dglsys_P corresponds to c_function in 
the thin binding, The package is essentially

generic
    dim:	Positive;
    type Float is digits<>;
package odeiv2 is

      err_noInit,	-- Init_Solve() has not been called
      err_Precision,	-- precision of C.double used in GSL not sufficient
      err_Method,	-- integration method not implemented
      err_SolveAgain:	-- Solve_Again() call without former Solve()
Exception;

    type Float_Array is array (1..dim) of Float;
    type Float_Matrix is array (1..dim, 1..dim) of Float;
    type Par_Array is array (Positive range <>) of Float;
    type Method is (RK8PD);
    type Solver is limited private;

    type Dglsys_P is not null access procedure
      (t:	Float;			-- independent variable
       y:	Float_Array;		-- dependent variables at t
       dydt:	out Float_Array;	-- 1. ordinary derivatives at t
       params:	Par_Array		-- any parameters
      );

    -- omitted: type Jacobi_P is access procedure...

    procedure Init_Solve
      -- Init. a dglsys, must be called once before calling
      -- (once or repeatedly) Solve() or Solve_Again().
      -- The resulting sol must be an access type because of the internal
      -- interface to the GSL library.
      (Dglsys:	Dglsys_P;		-- the system of diff. equ.
       Jacobi:	Jacobi_P;		-- the jacobi calc., if avail.
       pars:	access constant Par_Array;	-- the parameters
       met:	Method;			-- the solve method
       h_start:	Float;			-- initial step size
       epsabs:	Float;			-- absolute error tolerance
       epsrel:	Float;			-- relative error tolerance
       sol:	aliased in out Solver
      );

private

    package C renames Interfaces.C;
    package Ode renames gsl_odeiv2_h;

    type C_Array is array (Integer range <>) of aliased C.double;
    pragma Convention (C, C_Array);

    type Parameters is record
       dglpars:		access constant Par_Array;	-- pars of dglsys
       Dglsys:		Dglsys_P;			-- dglsys calc.
       Jacobi:		Jacobi_P;			-- Jacobi calc.
    end record;
    pragma Convention (C, Parameters);
    type Parameters_Ptr is access all Parameters;

    package Parameters_Conv is new
      System.Address_To_Access_Conversions (Parameters);

    type Solver is limited record
       initialized:	Boolean:= false;	-- Init_Solve() has been called
       firstcall_done:	Boolean;		-- first call done
       store_y:		Boolean;		-- copy y to ya
       ya:		C_Array (1..dim);	-- values of last Solve call
       sys:		aliased Ode.gsl_odeiv2_system;
       driver:		access Ode.gsl_odeiv2_driver;
       all_pars:		aliased Parameters;
       all_pp:		Parameters_Conv.Object_Pointer;
    end record;

end odeiv2;


In the package body I have to define the c_function above (thin binding 
spec.), which will call the corresponding function of type Dglsys_P 
(thick binding), and it finds this in the parameters. then I define the 
initialization subprogram.


package body odeiv2 is

    package C_Arrays is new
      Interfaces.C.Pointers (Integer, C.double, C_Array, 0.0);

    function func (t: C.double; y,f: access C.double; params: 
System.Address)	 return C.int;
    pragma Convention (C, func);

    function func (t: C.double; y,f: access C.double; params: 
System.Address)	 return C.int
      -- GSL version of Dglsys
    is
       use type System.Address;
       all_pars:	Parameters_Conv.Object_Pointer;
       yf, dydt:	Float_Array;
       y0:	C_Arrays.Pointer:= C_Arrays.Pointer(y);
       f0:	C_Arrays.Pointer:= C_Arrays.Pointer(f);
    begin
       all_pars:= Parameters_Conv.To_Pointer (params);
       for i in 1..dim loop
	 yf(i):= Float(y0.all);
	 C_Arrays.Increment (y0);
       end loop;
       all_pars.Dglsys (Float(t), yf, dydt, all_pars.dglpars.all);
       for i in 1..dim loop
	 f0.all:= C.double(dydt(i));
	 C_Arrays.Increment (f0);
       end loop;
       return gsl_errno_h.GSL_SUCCESS;
    end func;


    procedure Init_Solve
      (Dglsys:	Dglsys_P;		-- the system of diff.equ.
       Jacobi:	Jacobi_P;		-- jacobi calc., if available
       pars:	access constant Par_Array;	-- the parameters
       met:	Method;			-- the solve method
       h_start:	Float;			-- initial step size
       epsabs:	Float;			-- absolute error tolerance
       epsrel:	Float;			-- relative error tolerance
       sol:	aliased in out Solver
      )
    is
       gsl_met:	access constant Ode.gsl_odeiv2_step_type;
    begin
       -- set all_pars
       -- sol: flags for calling logic
       sol.Initialized:= true;
       sol.firstcall_done:= false;
       sol.store_y:= true;
       sol.all_pars.dglpars:= pars;
       sol.all_pars.Dglsys:= Dglsys;
       sol.all_pars.Jacobi:= Jacobi;
       -- transform integration method to GSL format
       case met is
	 when RK8PD =>	gsl_met:= Ode.gsl_odeiv2_step_rk8pd;
	 when others =>
	    raise err_Method
	      with "forgot to implement integration method";
       end case;
       -- build sys and driver
       sol.all_pp:= sol.all_pars'Unchecked_Access;
       sol.sys:=
	(func'Access, jac'Access, C.size_t(dim),
	 Parameters_Conv.To_Address (sol.all_pp));
       sol.driver:= Ode.gsl_odeiv2_driver_alloc_y_new
	(sol.sys'Access, gsl_met,
	 C.double(h_start), C.double(epsabs), C.double(epsrel));
       end Init_Solve;

    -- %< -------------
end odeiv2;


The above version compiles. At first I didn't have the Solver component 
all_pp, but passed app_pars'Address to the call of 
gsl_odeiv2_driver_alloc_y_new at the end of Init_Solve. It too compiled.

But whatever I try, I don't get rid of the runtime error

raised CONSTRAINT_ERROR : odeiv2.ads:92:4 access check failed

It accuses the line

    type Parameters is record


-- 
Frank Hrebabetzky, Kronach	+49 / 9261 / 950 0565

^ permalink raw reply	[relevance 3%]

* Re: Calling a record type's methods (functions or procedure) when record is in an array
  2020-01-23 15:00  6%     ` joakimds
@ 2020-01-23 20:15  0%       ` Optikos
  0 siblings, 0 replies; 200+ results
From: Optikos @ 2020-01-23 20:15 UTC (permalink / raw)


On Thursday, January 23, 2020 at 9:00:18 AM UTC-6, joak...@kth.se wrote:
> > And now, you could change the type of the components to Point to Integer, remove the type-casts,
> > and recompile the package Example **without having to recompile  dependent packages** because
> > they are dependent only on the visible portion of the package.
> 
> Using Taft types introduced in Ada95 it is possible to add new components to a record type without
> recompilation of dependent packages. Here is an Ada 2005 example:
> 
> private with System.Storage_Elements;
> 
> package Cars is
> 
>    type Any_Car (<>) is limited private;
>    --  This type is defined with unknown discriminant in order to make
>    --  sure instances are properly initialized by allocator function.
> 
>    function Allocate_Car return Any_Car;
>    --  The allocator function.
> 
>    type Car_Passenger_Count is range 0 .. 5;
>    
>    function Passenger_Count (Car : Any_Car) return Car_Passenger_Count;
> 
>    procedure Set_Passenger_Count
>      (Car   : in out Any_Car;
>       Value : Car_Passenger_Count);
> 
> private
> 
>    type Taft_Car;
> 
>    type Taft_Car_Ptr is access all Taft_Car;
> 
>    type Any_Car
>      (Offset : System.Storage_Elements.Storage_Offset)
>    is limited record
>       Allocated_Memory : aliased
>         System.Storage_Elements.Storage_Array (1 .. Offset);
>       Reference : Taft_Car_Ptr;
>    end record;
> 
> end Cars;
> 
> 
> 
> with System.Address_To_Access_Conversions;
> 
> package body Cars is
> 
>    type Taft_Car is record
>       Passenger_Count : Car_Passenger_Count;
>    end record;
> 
>    package Conversions is new System.Address_To_Access_Conversions
>      (Object => Taft_Car);
> 
>    function Allocate_Car return Any_Car is
>       Default : constant Any_Car
>         := (Offset           => Taft_Car'Max_Size_In_Storage_Elements,
>             Allocated_Memory => (others => 0),
>             Reference        => null);
>    begin
>       return Car : Any_Car (Taft_Car'Max_Size_In_Storage_Elements) do
>          declare
>             First_Index : constant System.Storage_Elements.Storage_Offset
>               := Car.Allocated_Memory'First;
>          begin
>             Car.Reference := Conversions.To_Pointer
>               (Car.Allocated_Memory (First_Index)'Address).all'Access;
>          end;
>       end return;
>    end Allocate_Car;
> 
>    function Passenger_Count (Car : Any_Car) return Car_Passenger_Count is
>    begin
>       return Car.Reference.Passenger_Count;
>   end Passenger_Count;
> 
>    procedure Set_Passenger_Count
>      (Car   : in out Any_Car;
>       Value : Car_Passenger_Count) is
>    begin
>       Car.Reference.all.Passenger_Count := Value;
>    end Set_Passenger_Count;
>    
> end Cars;
> 
> 
> with Ada.Text_IO;
> 
> with Cars;
> use  Cars;
> 
> procedure Main is
>    Car : Cars.Any_Car := Cars.Allocate_Car;
> begin
>    Set_Passenger_Count (Car, 3);
>    Ada.Text_IO.Put_Line (Passenger_Count (Car)'Image);
> end Main;
> 
> Does somebody have a better implementation of Taft types where heap allocations are not used?
> 
> Perhaps this example is something to add to documentation on Ada on the internet like for example:
> https://en.wikibooks.org/wiki/Ada_Programming/Tips
> 
> Anything wrong or could be improved with the implementation above?
> 
> Best regards,
> Joakim

Background on "Taft types" (a.k.a. Ichbiah's name "Taft-amendment types" or the generic/language-independent name "opaque pointers" or the C++ jargon "pimpl").
https://groups.google.com/forum/#!msg/comp.lang.ada/KelH3y5WzEA/z3pyInm_hqgJ


^ permalink raw reply	[relevance 0%]

* Re: Calling a record type's methods (functions or procedure) when record is in an array
  @ 2020-01-23 15:00  6%     ` joakimds
  2020-01-23 20:15  0%       ` Optikos
  0 siblings, 1 reply; 200+ results
From: joakimds @ 2020-01-23 15:00 UTC (permalink / raw)


> And now, you could change the type of the components to Point to Integer, remove the type-casts, and recompile the package Example **without having to recompile  dependent packages** because they are dependent only on the visible portion of the package.

Using Taft types introduced in Ada95 it is possible to add new components to a record type without recompilation of dependent packages. Here is an Ada 2005 example:

private with System.Storage_Elements;

package Cars is

   type Any_Car (<>) is limited private;
   --  This type is defined with unknown discriminant in order to make
   --  sure instances are properly initialized by allocator function.

   function Allocate_Car return Any_Car;
   --  The allocator function.

   type Car_Passenger_Count is range 0 .. 5;
   
   function Passenger_Count (Car : Any_Car) return Car_Passenger_Count;

   procedure Set_Passenger_Count
     (Car   : in out Any_Car;
      Value : Car_Passenger_Count);

private

   type Taft_Car;

   type Taft_Car_Ptr is access all Taft_Car;

   type Any_Car
     (Offset : System.Storage_Elements.Storage_Offset)
   is limited record
      Allocated_Memory : aliased
        System.Storage_Elements.Storage_Array (1 .. Offset);
      Reference : Taft_Car_Ptr;
   end record;

end Cars;



with System.Address_To_Access_Conversions;

package body Cars is

   type Taft_Car is record
      Passenger_Count : Car_Passenger_Count;
   end record;

   package Conversions is new System.Address_To_Access_Conversions
     (Object => Taft_Car);

   function Allocate_Car return Any_Car is
      Default : constant Any_Car
        := (Offset           => Taft_Car'Max_Size_In_Storage_Elements,
            Allocated_Memory => (others => 0),
            Reference        => null);
   begin
      return Car : Any_Car (Taft_Car'Max_Size_In_Storage_Elements) do
         declare
            First_Index : constant System.Storage_Elements.Storage_Offset
              := Car.Allocated_Memory'First;
         begin
            Car.Reference := Conversions.To_Pointer
              (Car.Allocated_Memory (First_Index)'Address).all'Access;
         end;
      end return;
   end Allocate_Car;

   function Passenger_Count (Car : Any_Car) return Car_Passenger_Count is
   begin
      return Car.Reference.Passenger_Count;
  end Passenger_Count;

   procedure Set_Passenger_Count
     (Car   : in out Any_Car;
      Value : Car_Passenger_Count) is
   begin
      Car.Reference.all.Passenger_Count := Value;
   end Set_Passenger_Count;
   
end Cars;


with Ada.Text_IO;

with Cars;
use  Cars;

procedure Main is
   Car : Cars.Any_Car := Cars.Allocate_Car;
begin
   Set_Passenger_Count (Car, 3);
   Ada.Text_IO.Put_Line (Passenger_Count (Car)'Image);
end Main;

Does somebody have a better implementation of Taft types where heap allocations are not used?

Perhaps this example is something to add to documentation on Ada on the internet like for example:
https://en.wikibooks.org/wiki/Ada_Programming/Tips

Anything wrong or could be improved with the implementation above?

Best regards,
Joakim


^ permalink raw reply	[relevance 6%]

* Re: Examining individual bytes of an integer
  @ 2018-10-15  7:49  5%   ` Niklas Holsti
  0 siblings, 0 replies; 200+ results
From: Niklas Holsti @ 2018-10-15  7:49 UTC (permalink / raw)


On 18-10-15 00:04 , Niklas Holsti wrote:
> On 18-10-14 22:15 , Henrik Härkönen wrote:
>> I'd like to examine individual bytes of larger (in bit size)
>> integer type. In C would probably move byte pointer etc. Also
>> I'd need to have a way to construct the integer from individual bytes.

Adding a little to my earlier answer:

> If you really want to inspect the structure of integers in memory,
> address by address, then I think the only way is the same as in C: make
> an octet pointer to the memory representation and read octet by octet.
> (But note that the Storage_Unit for some strange machines may not be 8
> bits.)

If you want to use the above method, the tools are in 
System.Storage_Elements (address arithmetic) and 
System.Address_To_Access_Conversions (convert an address into an access 
value).

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


^ permalink raw reply	[relevance 5%]

* Re: Strange crash on custom iterator
  2018-07-02 19:42  3%                   ` Simon Wright
@ 2018-07-03 14:08  5%                     ` Lucretia
  0 siblings, 0 replies; 200+ results
From: Lucretia @ 2018-07-03 14:08 UTC (permalink / raw)


On Monday, 2 July 2018 20:42:59 UTC+1, Simon Wright  wrote:

> This worked for me ..

Thanks, needed the extra in Has_Element as well.

But there are other issues as well:

1) Cannot pass an array which has been declared and initialised to an aliased parameter:

procedure Mem is
   type Unicode_String is array (Positive range <>) of Integer;

   procedure Inner (B : aliased in out Unicode_String) is null;

   S : aliased Unicode_String(1..10) := (others => Integer'First);
--   S : aliased Unicode_String := (1..10 => Integer'First);
begin
   Inner (S);
end Mem;

2) raised STORAGE_ERROR : stack overflow or erroneous memory access, when using "'Access" instead of "package Convert is new System.Address_To_Access_Conversions (Unicode_String);" and "'Address"

^ permalink raw reply	[relevance 5%]

* Re: Strange crash on custom iterator
  @ 2018-07-02 19:42  3%                   ` Simon Wright
  2018-07-03 14:08  5%                     ` Lucretia
  0 siblings, 1 reply; 200+ results
From: Simon Wright @ 2018-07-02 19:42 UTC (permalink / raw)


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

Luke A. Guest <laguest@archeia.com> writes:

> Simon Wright <> wrote:
>
>>> You don't need to make it tagged, to pass it by reference.  It is enough
>>> to make the formal parameter aliased.
>> 
>> Yes, that works (except you have to make the container you're iterating
>> over aliased too).
>
> I had to make the iterate for nation take “aliased in out” and make the
> array aliased, but it still does in the same place.

This worked for me ..


[-- Attachment #2: gnatchop-me --]
[-- Type: text/plain, Size: 9880 bytes --]

--  Copyright 2018, Luke A. Guest
--  License TBD.

with Ada.Characters.Latin_1;
with Ada.Text_IO; use Ada.Text_IO;
with UCA.Encoding;
with UCA.Iterators;

procedure Test is
   package L1 renames Ada.Characters.Latin_1;

   package Octet_IO is new Ada.Text_IO.Modular_IO (UCA.Octets);
   use Octet_IO;

   --  D  : UCA.Octets         := Character'Pos ('Q');
   --  A  : UCA.Unicode_String := UCA.To_Array (D);
   --  A2 : UCA.Unicode_String := UCA.Unicode_String'(1, 0, 0, 0, 0, 0, 1, 0);
   --  D2 : UCA.Octets         := UCA.To_Octet (A2);

   --  package OA_IO is new Ada.Text_IO.Integer_IO (Num => UCA.Bits);

   use UCA.Encoding;
   A : aliased UCA.Unicode_String :=
     +("ᚠᛇᚻ᛫ᛒᛦᚦ᛫ᚠᚱᚩᚠᚢᚱ᛫ᚠᛁᚱᚪ᛫ᚷᛖᚻᚹᛦᛚᚳᚢᛗ" & L1.LF &
         "Hello, world" & L1.LF &
         "Sîne klâwen durh die wolken sint geslagen," & L1.LF &
         "Τη γλώσσα μου έδωσαν ελληνική" & L1.LF &
         "मैं काँच खा सकता हूँ और मुझे उससे कोई चोट नहीं पहुंचती." & L1.LF &
         "میں کانچ کھا سکتا ہوں اور مجھے تکلیف نہیں ہوتی");
   B : aliased UCA.Unicode_String :=
     (225, 154, 160, 225, 155, 135, 225, 154, 187, 225, 155, 171, 225, 155, 146, 225, 155, 166, 225,
      154, 166, 225, 155, 171, 225, 154, 160, 225, 154, 177, 225, 154, 169, 225, 154, 160, 225, 154,
      162, 225, 154, 177, 225, 155, 171, 225, 154, 160, 225, 155, 129, 225, 154, 177, 225, 154, 170,
      225, 155, 171, 225, 154, 183, 225, 155, 150, 225, 154, 187, 225, 154, 185, 225, 155, 166, 225,
      155, 154, 225, 154, 179, 225, 154, 162, 225, 155, 151,
      10,
      72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100,
      10,
      83, 195, 174, 110, 101, 32, 107, 108, 195, 162, 119, 101, 110, 32, 100, 117, 114, 104, 32, 100,
      105, 101, 32, 119, 111, 108, 107, 101, 110, 32, 115, 105, 110, 116, 32, 103, 101, 115, 108, 97,
      103, 101, 110, 44,
      10,
      206, 164, 206, 183, 32, 206, 179, 206, 187, 207, 142, 207, 131, 207, 131, 206, 177, 32, 206, 188,
      206, 191, 207, 133, 32, 206, 173, 206, 180, 207, 137, 207, 131, 206, 177, 206, 189, 32, 206, 181,
      206, 187, 206, 187, 206, 183, 206, 189, 206, 185, 206, 186, 206, 174,
      10,
      224, 164, 174, 224, 165, 136, 224, 164, 130, 32, 224, 164, 149, 224, 164, 190, 224, 164, 129, 224,
      164, 154, 32, 224, 164, 150, 224, 164, 190, 32, 224, 164, 184, 224, 164, 149, 224, 164, 164, 224,
      164, 190, 32, 224, 164, 185, 224, 165, 130, 224, 164, 129, 32, 224, 164, 148, 224, 164, 176, 32,
      224, 164, 174, 224, 165, 129, 224, 164, 157, 224, 165, 135, 32, 224, 164, 137, 224, 164, 184, 224,
      164, 184, 224, 165, 135, 32, 224, 164, 149, 224, 165, 139, 224, 164, 136, 32, 224, 164, 154, 224,
      165, 139, 224, 164, 159, 32, 224, 164, 168, 224, 164, 185, 224, 165, 128, 224, 164, 130, 32, 224,
      164, 170, 224, 164, 185, 224, 165, 129, 224, 164, 130, 224, 164, 154, 224, 164, 164, 224, 165, 128, 46,
      10,
      217, 133, 219, 140, 218, 186, 32, 218, 169, 216, 167, 217, 134, 218, 134, 32, 218, 169, 218, 190,
      216, 167, 32, 216, 179, 218, 169, 216, 170, 216, 167, 32, 219, 129, 217, 136, 218, 186, 32, 216,
      167, 217, 136, 216, 177, 32, 217, 133, 216, 172, 218, 190, 219, 146, 32, 216, 170, 218, 169, 217,
      132, 219, 140, 217, 129, 32, 217, 134, 219, 129, 219, 140, 218, 186, 32, 219, 129, 217, 136, 216,
      170, 219, 140);
begin
--   Put_Line ("A => " & To_UTF_8_String (A));
   Put_Line ("A => " & L1.LF & String (+A));

   Put_Line ("A => ");
   Put ('(');

   for E of A loop
      Put (Item => E, Base => 2);
      Put (", ");
   end loop;

   Put (')');
   New_Line;

   Put_Line ("B => " & L1.LF & String (+B));

   Put_Line ("A (Iterated) => ");

   for I in UCA.Iterators.Iterate (A) loop
      Put (UCA.Iterators.Element (I));       --  ERROR! Dies in Element, Data has nothing gdb => p position - $1 = (data => (), index => 1)
   end loop;

   New_Line;
end Test;

with Ada.Strings.UTF_Encoding;
with Ada.Unchecked_Conversion;

package UCA is
   use Ada.Strings.UTF_Encoding;

   type Octets is mod 2 ** 8 with
     Size => 8;

   type Unicode_String is array (Positive range <>) of Octets with
     Pack => True;

   type Unicode_String_Access is access all Unicode_String;

   --  This should match Wide_Wide_Character in size.
   type Code_Points is mod 2 ** 32 with
     Static_Predicate => Code_Points in 0 .. 16#0000_D7FF# or Code_Points in 16#0000_E000# .. 16#0010_FFFF#,
     Size             => 32;

private
   type Bits is range 0 .. 1 with
     Size => 1;

   type Bit_Range is range 0 .. Octets'Size - 1;
end UCA;

with Ada.Finalization;
with Ada.Iterator_Interfaces;
private with System.Address_To_Access_Conversions;

package UCA.Iterators is
   ---------------------------------------------------------------------------------------------------------------------
   --  Iteration over code points.
   ---------------------------------------------------------------------------------------------------------------------
   type Cursor is private;
   pragma Preelaborable_Initialization (Cursor);

   function Has_Element (Position : in Cursor) return Boolean;

   function Element (Position : in Cursor) return Octets;

   package Code_Point_Iterators is new Ada.Iterator_Interfaces (Cursor, Has_Element);

   function Iterate (Container : aliased in Unicode_String) return Code_Point_Iterators.Forward_Iterator'Class;
   function Iterate (Container : aliased in Unicode_String; Start : in Cursor) return
     Code_Point_Iterators.Forward_Iterator'Class;

   ---------------------------------------------------------------------------------------------------------------------
   --  Iteration over grapheme clusters.
   ---------------------------------------------------------------------------------------------------------------------
private
   use Ada.Finalization;

   package Convert is new System.Address_To_Access_Conversions (Unicode_String);

   type Cursor is
      record
         Data  : Convert.Object_Pointer := null;
         Index : Positive               := Positive'Last;
      end record;

   type Code_Point_Iterator is new Limited_Controlled and Code_Point_Iterators.Forward_Iterator with
      record
         Data  : Convert.Object_Pointer := null;
      end record;

   overriding
   function First (Object : in Code_Point_Iterator) return Cursor;

   overriding
   function Next  (Object : in Code_Point_Iterator; Position : Cursor) return Cursor;

end UCA.Iterators;

with Ada.Text_IO; use Ada.Text_IO;

package body UCA.Iterators is
   package Octet_IO is new Ada.Text_IO.Modular_IO (UCA.Octets);
   use Octet_IO;

   use type Convert.Object_Pointer;

   function Has_Element (Position : in Cursor) return Boolean is
   begin
      return Position.Index in Position.Data'Range;
   end Has_Element;

   function Element (Position : in Cursor) return Octets is
   begin
      if Position.Data = null then
         raise Constraint_Error with "Fuck!";
      end if;
      Put ("<< Element - " & Positive'Image (Position.Index) & " - ");
      Put (Position.Data (Position.Index));
      Put_Line (" >>");

      return Position.Data (Position.Index);
   end Element;

   function Iterate (Container : aliased in Unicode_String) return Code_Point_Iterators.Forward_Iterator'Class is
   begin
      Put_Line ("<< iterate >>");
      return I : Code_Point_Iterator := (Limited_Controlled with
        Data => Convert.To_Pointer (Container'Address)) do
         if I.Data = null then
            Put_Line ("Data => null");
         else
            Put_Line ("Data => not null - Length: " & Positive'Image (I.Data'Length));
         end if;
         null;
      end return;
   end Iterate;

   function Iterate (Container : aliased in Unicode_String; Start : in Cursor) return
     Code_Point_Iterators.Forward_Iterator'Class is
   begin
      Put_Line ("<< iterate >>");
      return I : Code_Point_Iterator := (Limited_Controlled with
        Data => Convert.To_Pointer (Container'Address)) do
         if I.Data = null then
            Put_Line ("Data => null");
         else
            Put_Line ("Data => not null");
         end if;
         null;
      end return;
   end Iterate;

   ---------------------------------------------------------------------------------------------------------------------
   --  Iteration over grapheme clusters.
   ---------------------------------------------------------------------------------------------------------------------
   overriding
   function First (Object : in Code_Point_Iterator) return Cursor is
   begin
      return (Data => Object.Data, Index => Positive'First);
   end First;

   overriding
   function Next  (Object : in Code_Point_Iterator; Position : Cursor) return Cursor is
   begin
      return (Data => Object.Data, Index => Position.Index + 1);
   end Next;
end UCA.Iterators;

--  Copyright © 2018, Luke A. Guest
with Ada.Unchecked_Conversion;

package body UCA.Encoding is
   function To_Unicode_String (Str : in String) return Unicode_String is
      Result : Unicode_String (1 .. Str'Length) with
        Address => Str'Address;
   begin
      return Result;
   end To_Unicode_String;

   function To_String (Str : in Unicode_String) return String is
      Result : String (1 .. Str'Length) with
        Address => Str'Address;
   begin
      return Result;
   end To_String;
end UCA.Encoding;

package UCA.Encoding is
   use Ada.Strings.UTF_Encoding;

   function To_Unicode_String (Str : in String) return Unicode_String;
   function To_String (Str : in Unicode_String) return String;

   function "+" (Str : in String) return Unicode_String renames To_Unicode_String;
   function "+" (Str : in Unicode_String) return String renames To_String;
end UCA.Encoding;

^ permalink raw reply	[relevance 3%]

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-09  8:28  0%           ` Dmitry A. Kazakov
@ 2018-03-11  0:31  0%             ` Jere
  0 siblings, 0 replies; 200+ results
From: Jere @ 2018-03-11  0:31 UTC (permalink / raw)


On Friday, March 9, 2018 at 3:28:43 AM UTC-5, Dmitry A. Kazakov wrote:
> On 09/03/2018 01:52, Jere wrote:
> 
> > Example:
> > with Ada.Text_IO; use Ada.Text_IO;
> > with System.Address_To_Access_Conversions;
> > 
> > procedure jdoodle is
> >      type Container is tagged null record;
> 
> Do you have control over Container? Can you derive from? Can you put it 
> into a wrapper type or use a handle to the container in the generic 
> instead of container itself.
> 
> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de

Not practically.  I'm not really allowed to change any of the specs
and there is already a lot of code using the existing containers and
the generic.


^ permalink raw reply	[relevance 0%]

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-09  0:52  6%         ` Jere
@ 2018-03-09  8:28  0%           ` Dmitry A. Kazakov
  2018-03-11  0:31  0%             ` Jere
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2018-03-09  8:28 UTC (permalink / raw)


On 09/03/2018 01:52, Jere wrote:

> Example:
> with Ada.Text_IO; use Ada.Text_IO;
> with System.Address_To_Access_Conversions;
> 
> procedure jdoodle is
>      type Container is tagged null record;

Do you have control over Container? Can you derive from? Can you put it 
into a wrapper type or use a handle to the container in the generic 
instead of container itself.

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

^ permalink raw reply	[relevance 0%]

* Re: Ada Alternatives to Unrestricted_Access
  @ 2018-03-09  0:52  6%         ` Jere
  2018-03-09  8:28  0%           ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Jere @ 2018-03-09  0:52 UTC (permalink / raw)


On Thursday, March 8, 2018 at 7:43:31 PM UTC-5, Jere wrote:
> On Thursday, March 8, 2018 at 3:27:02 AM UTC-5, Dmitry A. Kazakov wrote:
> > On 07/03/2018 23:29, Jere wrote:
> > > On Wednesday, March 7, 2018 at 3:38:13 PM UTC-5, Dmitry A. Kazakov wrote:
> > >> On 2018-03-07 21:11, Jere wrote:
> > 
> > >>> Since the Container
> > >>> implementation is unknown in the generic, I wasn't able to get a version
> > >>> of the Rosen technique to work as an alternative (same constant vs
> > >>> variable access problem).
> > >>
> > >> I am not sure I understand the problem. Why don't you pass a function
> > >> Self along with the container type:
> > >>
> > >>      generic
> > >>         type Container is tagged whatever;
> > >>         function Self (C : Container'Class)
> > >>            return not null access Container'Class;
> > >>      package Iterative_Mess is
> > > 
> > > Because the package is already in use in other code, so
> > > changing the specification would be a very time consuming
> > > change.
> > 
> > You can default Self when not used.
> > 
> > -- 
> > Regards,
> > Dmitry A. Kazakov
> > http://www.dmitry-kazakov.de
> 
> So I tried playing with this, but I still ran into the same
> problem when trying to implement the Self function.  Inside
> I needed to "un-const" the container, so I came back to this
> same problem.

Example:
with Ada.Text_IO; use Ada.Text_IO;
with System.Address_To_Access_Conversions;

procedure jdoodle is
    type Container is tagged null record;
    
    package A2A is new System.Address_To_Access_Conversions(Container);
    
    type Container_Access is access Container;
    type Container_Constant_Access is access constant Container;
    
    function Self 
        (C : Container'Class)
         return not null access Container'Class
    is begin
        --return C'Unchecked_Access;  --ERROR: access-to-variable designates constant
        --return C'Unrestricted_Access;  -- Works, but not portable, GNAT specific
        return A2A.To_Pointer(C'Address);  -- Also works, unsure if OK in portable Ada
    end Self;
     
begin
    null;
end jdoodle;


^ permalink raw reply	[relevance 6%]

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-08  3:18  4% ` gautier_niouzes
@ 2018-03-09  0:41  0%   ` Jere
  0 siblings, 0 replies; 200+ results
From: Jere @ 2018-03-09  0:41 UTC (permalink / raw)


On Wednesday, March 7, 2018 at 10:18:47 PM UTC-5, gautier wrote:
> I had the same problem for GL[U[T]] bindings (work on both GNAT and ObjectAda, and perhaps other Ada systems) [1]. A quick search with AZip (shameless plug :-) [2] leads to 
>   package A2A_double is new System.Address_To_Access_Conversions(Double);
> ...
>   procedure Vertex (v: Double_Vector_3D) is
>   begin
>     Vertex3dv(A2A_double.To_Pointer(v(0)'Address));
>     -- This method is functionally identical
>     -- to using GNAT's 'Unrestricted_Access
>   end Vertex;
> 
> Other places use an Unchecked_Conversion.
> The GNAT doc says:
> "The Unrestricted_Access attribute is similar to Access except that all accessibility and aliased view checks are omitted. This is a user-beware attribute. It is similar to Address, for which it is a desirable replacement where the value desired is an access type. In other words, its effect is identical to first applying the Address attribute and then doing an unchecked conversion to a desired access type."
> 
> ___
> 
> [1] https://globe3d.sourceforge.io/
> [2] https://azip.sourceforge.io/

Yep, that's basically the same conclusion I came to.  My doubts center
around whether it is legit in portable Ada to do so to bypass the "in"
mode.  I don't know if the language allows for a compiler to use
different representations for a constant variable and a mutable variable.
If so, what I am doing might possibly be erroneous behavior.  It would
work in GNAT based on the section you quoted, but I was curious if
it would run afoul in other compilers possibly.

^ permalink raw reply	[relevance 0%]

* Re: Ada Alternatives to Unrestricted_Access
  2018-03-07 20:11  5% Ada Alternatives to Unrestricted_Access Jere
  @ 2018-03-08  3:18  4% ` gautier_niouzes
  2018-03-09  0:41  0%   ` Jere
  1 sibling, 1 reply; 200+ results
From: gautier_niouzes @ 2018-03-08  3:18 UTC (permalink / raw)


I had the same problem for GL[U[T]] bindings (work on both GNAT and ObjectAda, and perhaps other Ada systems) [1]. A quick search with AZip (shameless plug :-) [2] leads to 
  package A2A_double is new System.Address_To_Access_Conversions(Double);
...
  procedure Vertex (v: Double_Vector_3D) is
  begin
    Vertex3dv(A2A_double.To_Pointer(v(0)'Address));
    -- This method is functionally identical
    -- to using GNAT's 'Unrestricted_Access
  end Vertex;

Other places use an Unchecked_Conversion.
The GNAT doc says:
"The Unrestricted_Access attribute is similar to Access except that all accessibility and aliased view checks are omitted. This is a user-beware attribute. It is similar to Address, for which it is a desirable replacement where the value desired is an access type. In other words, its effect is identical to first applying the Address attribute and then doing an unchecked conversion to a desired access type."

___

[1] https://globe3d.sourceforge.io/
[2] https://azip.sourceforge.io/

^ permalink raw reply	[relevance 4%]

* Ada Alternatives to Unrestricted_Access
@ 2018-03-07 20:11  5% Jere
    2018-03-08  3:18  4% ` gautier_niouzes
  0 siblings, 2 replies; 200+ results
From: Jere @ 2018-03-07 20:11 UTC (permalink / raw)


I'm currently updating a generic package that takes a container type
as an input and creates an iterative type around it.  I found quite a
few instances of GNAT's Unrestricted_Access which appear to be
necessary because of the Iterate function's container parameter of
being mode "in" and the iterator needing a non constant access to it
to supply tamper check semantics.  I tried changing the mode to
"in out" but that caused a slew of errors where Iterate was used 
inside other operations that had the Container supplied via "in"
mode parameters.  Changing those other operations doesn't make
sense (and causes other errors later), but I don't like relying
on GNAT's implementation defined attribute if I can help it.

I was able to use System.Address_To_Access_Conversions to 
achieve both compiler happiness and expected runtime execution, but
I am worried this is not legal as it is skirting kind of close
to Address overlays.  In this case the types are identical aside
from one (the Iterate "in" mode parameter) being constant and the
other (the iterators "Container_Access" component) being variable.
However, I am not fully convinced it is (relatively) safe or portable yet.

The gist of the differences being:

   Container_Access => C'Unrestricted_Access

is converted to:

   Container_Access => A2A.To_Pointer(C'Address)

where:
   
   package A2A is new System.Address_To_Access_Conversions(Container);

and the parameter mode of C is defined as:

   function Iterate
            (C : in Container)
             return Iterator_Interfaces.Forward_Iterator'Class;

and the generic formal for Container

   type Container is tagged private;

I'm working with an existing code base, so complete overhaul is 
not a great option.

If it isn't a good idea, are there alternatives?  Since the Container
implementation is unknown in the generic, I wasn't able to get a version
of the Rosen technique to work as an alternative (same constant vs
variable access problem).


^ permalink raw reply	[relevance 5%]

* Re: How to access an array using two different indexing schemes
  2017-11-26  8:58  0%           ` Dmitry A. Kazakov
@ 2017-11-26 10:31  0%             ` Jerry
  0 siblings, 0 replies; 200+ results
From: Jerry @ 2017-11-26 10:31 UTC (permalink / raw)


On Sunday, November 26, 2017 at 1:58:32 AM UTC-7, Dmitry A. Kazakov wrote:
> On 2017-11-26 02:07, Jerry wrote:
> > On Friday, November 24, 2017 at 4:38:10 PM UTC-7, Jerry wrote:
> >> I frequently allocate memory for arrays from the heap, as discussed previously on this list, like this:
> >>
> >> with Ada.Numerics.Long_Real_Arrays; use Ada.Numerics.Long_Real_Arrays;
> >> procedure Double_Array_2 is
> >>      type Real_Vector_Access is access Real_Vector;
> >>      x_Ptr : Real_Vector_Access := new Real_Vector(-4 .. 3);
> >>          x : Real_Vector renames x_Ptr.all;
> >>      y_Ptr : Real_Vector_Access := new Real_Vector(0 .. 7);
> >>          y : Real_Vector renames y_Ptr.all;
> >> begin
> >>      null;
> >> end Double_Array_2;
> >>
> >> How would I use the 'Address trick in this situation?
> >>
> > Any help here? I've spend several hours on this one. I'm not out of
> > ideas but I'm pretty challenged by this. Currently trying things with
> > System.Address_To_Access_Conversions.
> 
> Where is a problem?
> 
> with Ada.Numerics.Long_Real_Arrays; use Ada.Numerics.Long_Real_Arrays;
> procedure Double_Array_2 is
>     type Real_Vector_Access is access Real_Vector;
>     x_Ptr : Real_Vector_Access := new Real_Vector(-4 .. 3);
>     x : Real_Vector renames x_Ptr.all;
>     y : Real_Vector(0..7);
>     for y'Address use x'Address;
> begin
>     null;
> end Double_Array_2;
> 
> -- 
> Regards,
> Dmitry A. Kazakov
> http://www.dmitry-kazakov.de

Thanks, Dmitry. I kept trying to use a pointer for y. I anticipated that I would feel like an idiot when someone showed me how to do this and I was right.

Jerry


^ permalink raw reply	[relevance 0%]

* Re: How to access an array using two different indexing schemes
  2017-11-26  1:07  5%         ` Jerry
@ 2017-11-26  8:58  0%           ` Dmitry A. Kazakov
  2017-11-26 10:31  0%             ` Jerry
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2017-11-26  8:58 UTC (permalink / raw)


On 2017-11-26 02:07, Jerry wrote:
> On Friday, November 24, 2017 at 4:38:10 PM UTC-7, Jerry wrote:
>> I frequently allocate memory for arrays from the heap, as discussed previously on this list, like this:
>>
>> with Ada.Numerics.Long_Real_Arrays; use Ada.Numerics.Long_Real_Arrays;
>> procedure Double_Array_2 is
>>      type Real_Vector_Access is access Real_Vector;
>>      x_Ptr : Real_Vector_Access := new Real_Vector(-4 .. 3);
>>          x : Real_Vector renames x_Ptr.all;
>>      y_Ptr : Real_Vector_Access := new Real_Vector(0 .. 7);
>>          y : Real_Vector renames y_Ptr.all;
>> begin
>>      null;
>> end Double_Array_2;
>>
>> How would I use the 'Address trick in this situation?
>>
> Any help here? I've spend several hours on this one. I'm not out of
> ideas but I'm pretty challenged by this. Currently trying things with
> System.Address_To_Access_Conversions.

Where is a problem?

with Ada.Numerics.Long_Real_Arrays; use Ada.Numerics.Long_Real_Arrays;
procedure Double_Array_2 is
    type Real_Vector_Access is access Real_Vector;
    x_Ptr : Real_Vector_Access := new Real_Vector(-4 .. 3);
    x : Real_Vector renames x_Ptr.all;
    y : Real_Vector(0..7);
    for y'Address use x'Address;
begin
    null;
end Double_Array_2;

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

^ permalink raw reply	[relevance 0%]

* Re: How to access an array using two different indexing schemes
  @ 2017-11-26  1:07  5%         ` Jerry
  2017-11-26  8:58  0%           ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Jerry @ 2017-11-26  1:07 UTC (permalink / raw)


On Friday, November 24, 2017 at 4:38:10 PM UTC-7, Jerry wrote:
> I frequently allocate memory for arrays from the heap, as discussed previously on this list, like this:
> 
> with Ada.Numerics.Long_Real_Arrays; use Ada.Numerics.Long_Real_Arrays;
> procedure Double_Array_2 is
>     type Real_Vector_Access is access Real_Vector;
>     x_Ptr : Real_Vector_Access := new Real_Vector(-4 .. 3);
>         x : Real_Vector renames x_Ptr.all;
>     y_Ptr : Real_Vector_Access := new Real_Vector(0 .. 7);
>         y : Real_Vector renames y_Ptr.all;
> begin
>     null;
> end Double_Array_2;
> 
> How would I use the 'Address trick in this situation?
> 
Any help here? I've spend several hours on this one. I'm not out of ideas but I'm pretty challenged by this. Currently trying things with System.Address_To_Access_Conversions.

Jerry

^ permalink raw reply	[relevance 5%]

* Re: How to access an array using two different indexing schemes
  2017-11-24 11:42  4% How to access an array using two different indexing schemes Jerry
  2017-11-24 17:37  0% ` A. Cervetti
@ 2017-11-24 18:37  0% ` Per Sandberg
  1 sibling, 0 replies; 200+ results
From: Per Sandberg @ 2017-11-24 18:37 UTC (permalink / raw)


Hi a reflection.
Why the different indexing ?
/P



Den 2017-11-24 kl. 12:42, skrev Jerry:
> I want to access an array such as Real_Vector (built-in for Ada >= 2005) with two different indexing schemes. For example, I would access a Real_Vector indexed (0 .. 4) when thinking of it as a times series and the same data indexed (1 .. 5) when thinking of it as a vector. Another application would be a vector indexed (-128 .. 127) because it fits my problem domain, perhaps a spatial variable, but I need to index it as (0 .. 255) when thinking of doing a Fast Fourier Transform on it.
> 
> I could declare two arrays such as
> 
> x : Real_Vector(0 .. 4);
> y : Real_Vector(1 .. 5);
> 
> Ada then allows the assignments
> 
> y := x;
> and
> x := y;
> 
> but this has two problems. First, I have wasted memory and cycles by declaring y and copying x into it. Second, I would then have a kind of version control problem where every time I modified one, I have to copy it to the other.
> 
> I have the notion that I should be able to accomplish this using pointers but I can’t seem to crack how do to this. I’ve tried all sorts of things and am resigned to doing the above duplication if I have to. (My arrays can be _much_ larger so the overhead might be significant. They might also be two-dimensional, as in Real_Matrix or Complex_Matrix.)
> 
> I'm currently looking at System.Address_To_Access_Conversions but I thought I would query the list in the meantime.
> 
> Any ideas?
> 
> Thanks,
> Jerry
> 

^ permalink raw reply	[relevance 0%]

* Re: How to access an array using two different indexing schemes
  2017-11-24 11:42  4% How to access an array using two different indexing schemes Jerry
@ 2017-11-24 17:37  0% ` A. Cervetti
    2017-11-24 18:37  0% ` Per Sandberg
  1 sibling, 1 reply; 200+ results
From: A. Cervetti @ 2017-11-24 17:37 UTC (permalink / raw)


Il giorno venerdì 24 novembre 2017 12:42:08 UTC+1, Jerry ha scritto:

> I'm currently looking at System.Address_To_Access_Conversions but I thought I would query the list in the meantime.

use attribute 'Address:

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Float_Text_IO; use Ada.Float_Text_IO;
with Ada.Numerics.Generic_Real_Arrays;

procedure Double_Array is
   package Real_Array is new Ada.Numerics.Generic_Real_Arrays(Float);
   use Real_Array;
   
   x : Real_Vector(0 .. 4) := (1.0, 2.0, 3.0, 4.0, 5.0);
   y : Real_Vector(1 .. 5);
   for Y'Address use X'Address; -- <<<<<<<<<<<<<<<<<<<<
   
begin
   X(0) := 20.0;
   Put(X(0), 0, 0, 0); New_Line;
   Put(Y(1), 0, 0, 0); New_Line;
end Double_Array;

A.

^ permalink raw reply	[relevance 0%]

* How to access an array using two different indexing schemes
@ 2017-11-24 11:42  4% Jerry
  2017-11-24 17:37  0% ` A. Cervetti
  2017-11-24 18:37  0% ` Per Sandberg
  0 siblings, 2 replies; 200+ results
From: Jerry @ 2017-11-24 11:42 UTC (permalink / raw)


I want to access an array such as Real_Vector (built-in for Ada >= 2005) with two different indexing schemes. For example, I would access a Real_Vector indexed (0 .. 4) when thinking of it as a times series and the same data indexed (1 .. 5) when thinking of it as a vector. Another application would be a vector indexed (-128 .. 127) because it fits my problem domain, perhaps a spatial variable, but I need to index it as (0 .. 255) when thinking of doing a Fast Fourier Transform on it.

I could declare two arrays such as

x : Real_Vector(0 .. 4);
y : Real_Vector(1 .. 5); 

Ada then allows the assignments

y := x;
and
x := y;

but this has two problems. First, I have wasted memory and cycles by declaring y and copying x into it. Second, I would then have a kind of version control problem where every time I modified one, I have to copy it to the other.

I have the notion that I should be able to accomplish this using pointers but I can’t seem to crack how do to this. I’ve tried all sorts of things and am resigned to doing the above duplication if I have to. (My arrays can be _much_ larger so the overhead might be significant. They might also be two-dimensional, as in Real_Matrix or Complex_Matrix.)

I'm currently looking at System.Address_To_Access_Conversions but I thought I would query the list in the meantime.

Any ideas?

Thanks,
Jerry

^ permalink raw reply	[relevance 4%]

* Re: Convert between C "void*" pointer and an access
  2017-10-11 23:12  7%   ` Victor Porton
@ 2017-10-12  1:01  4%     ` Victor Porton
  0 siblings, 0 replies; 200+ results
From: Victor Porton @ 2017-10-12  1:01 UTC (permalink / raw)


Victor Porton wrote:

> Victor Porton wrote:
> 
>> Victor Porton wrote:
>> 
>>> What is the right way to convert between C "void*" pointer and an access
>>> to a tagged or class-wide type?
>>> 
>>> Ada.Unchecked_Conversion seems to be what I need, but the access type
>>> may be "fat" and thus have another format than void*.
>>> 
>>> I caught myself doing such unchecked conversions, but now I feel I did
>>> an error.
>>> 
>>> For example, let
>>> 
>>> type X_Type is abstract tagged null record;
>>> 
>>> How to store X_Type'Class pointer in "void*" and convert them back and
>>> forth?
>> 
>> It seems I've found a right solution of my problem. (Check if Ada RM
>> warrants that it works with every compiler!)
>> 
>> Well, why it is not a standard package?! Why I need to invent something
>> "smart" every time I need to code?
> 
> The package body was with a bug. Here there is corrected code:

[snip] (see code above in the thread)

Now I will prove that it works without errors with every conforming 
compilers.

The below will describe how my package Convert_Void works. If in doubt, 
consult the package source code.

First I should formulate the problem exactly:

Having an Ada object (we can restrict to tagged and class-wide types and 
benefit from the fact that such objects 'Address "should produce a useful 
result" (RM 13.3.16)), we need to transform it to C void pointer and pass to 
C code; the C code should be able to call Ada code (e.g. through subprogram 
access) and pass the pointer back and the Ada code should be able to work 
with the original Ada object.

In other words, we need to define two functions: To_Pointer which converts 
all access values for a certain type (tagged or class-wide, at least) into 
void pointers and To_Access which converts void pointers obtained by 
To_Pointer back into the original access value.

In other words, we need two mutually inverse bijections between every set of 
values of 'Unchecked_Access of values of a type (tagged or class-wide, at 
least) and a subset of C void pointers.

We also need map null access to NULL pointer and vice versa.

We will use chars_ptr from Interfaces.C.Strings to represent void pointers. 
It is valid because C11, 6.2.5, 28 (draft N1548): "A pointer to void shall 
have the same representation and alignment requirements as a pointer to a 
character type."

This problem is solved in my generic package Convert_Void:

-- "with" and "use" skipped
generic
    type Object(<>) is limited private;
package Convert_Void is

   package Address_Conversions is new
     System.Address_To_Access_Conversions(Object);
   
   subtype Object_Pointer is Address_Conversions.Object_Pointer;
   
   function To_Access (Void_Pointer: chars_ptr) return Object_Pointer;
   
   function To_C_Pointer (Pointer: Object_Pointer) return chars_ptr;
   
end Convert_Void;

We define in Convert_Void body:

type My_Char_Pointer is access all char with Convention=>C;
package Char_Address_Conversions is new
  System.Address_To_Access_Conversions(char);

One of the steps of implementing the functions To_Pointer and To_Access is 
to convert between chars_ptr and My_Char_Pointer. This is trivially done 
with Ada.Unchecked_Conversion because they are by definition the same C type 
char* and thus have the same representation.

So our task is reduced to conversion between My_Char_Pointer an Ada object 
access.

We do this conversion (in both directions) like:

Char_Address_Conversions.To_Pointer(Address_Conversions.To_Address(...))

Address_Conversions.To_Pointer(Char_Address_Conversions.To_Address(...))

The thing to prove is that this is an injective function from object 
pointers to My_Char_Pointer values and that backward conversion is really 
its inversion.

But it is just my understanding of "The To_Pointer and To_Address 
subprograms convert back and forth between values of types Object_Pointer 
and Address." (RM 13.7.2 5/2)

That null access are mapped into NULL pointers and vice versa is left as an 
exercise to the reader.

-- 
Victor Porton - http://portonvictor.org

^ permalink raw reply	[relevance 4%]

* Re: Convert between C "void*" pointer and an access
  2017-10-11 22:58  7% ` Victor Porton
@ 2017-10-11 23:12  7%   ` Victor Porton
  2017-10-12  1:01  4%     ` Victor Porton
  0 siblings, 1 reply; 200+ results
From: Victor Porton @ 2017-10-11 23:12 UTC (permalink / raw)


Victor Porton wrote:

> Victor Porton wrote:
> 
>> What is the right way to convert between C "void*" pointer and an access
>> to a tagged or class-wide type?
>> 
>> Ada.Unchecked_Conversion seems to be what I need, but the access type may
>> be "fat" and thus have another format than void*.
>> 
>> I caught myself doing such unchecked conversions, but now I feel I did an
>> error.
>> 
>> For example, let
>> 
>> type X_Type is abstract tagged null record;
>> 
>> How to store X_Type'Class pointer in "void*" and convert them back and
>> forth?
> 
> It seems I've found a right solution of my problem. (Check if Ada RM
> warrants that it works with every compiler!)
> 
> Well, why it is not a standard package?! Why I need to invent something
> "smart" every time I need to code?

The package body was with a bug. Here there is corrected code:


with System.Address_To_Access_Conversions;
with Interfaces.C.Strings; use Interfaces.C.Strings;

-- C11, 6.2.5, 28 (draft N1548):
-- A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.
-- So we can use chars_ptr to mean void pointer in C.

generic
    type Object(<>) is limited private;
package Convert_Void is

   package Address_Conversions is new System.Address_To_Access_Conversions(Object);

   subtype Object_Pointer is Address_Conversions.Object_Pointer;

   function To_Access (Void_Pointer: chars_ptr) return Object_Pointer;

   function To_C_Pointer (Pointer: Object_Pointer) return chars_ptr;

end Convert_Void;


with Ada.Unchecked_Conversion;

package body Convert_Void is

   type My_Char_Pointer is access all char with Convention=>C;

   function From_My_Char_Pointer is new Ada.Unchecked_Conversion(My_Char_Pointer, chars_ptr);
   function From_Chars_Ptr is new Ada.Unchecked_Conversion(chars_ptr, My_Char_Pointer);

   package Char_Address_Conversions is new System.Address_To_Access_Conversions(char);

   function To_Access (Void_Pointer: chars_ptr) return Object_Pointer is
      P: constant My_Char_Pointer := From_Chars_Ptr(Void_Pointer);
      A: constant System.Address :=
        Char_Address_Conversions.To_Address(Char_Address_Conversions.Object_Pointer(P));
   begin
      return Address_Conversions.To_Pointer(A);
   end;

   function To_C_Pointer (Pointer: Object_Pointer) return chars_ptr is
      A: constant System.Address := Address_Conversions.To_Address(Pointer);
      P: constant My_Char_Pointer :=
        My_Char_Pointer(Char_Address_Conversions.To_Pointer(A));
   begin
      return From_My_Char_Pointer(P);
   end;

end Convert_Void;

-- 
Victor Porton - http://portonvictor.org


^ permalink raw reply	[relevance 7%]

* Re: Convert between C "void*" pointer and an access
  @ 2017-10-11 22:58  7% ` Victor Porton
  2017-10-11 23:12  7%   ` Victor Porton
  0 siblings, 1 reply; 200+ results
From: Victor Porton @ 2017-10-11 22:58 UTC (permalink / raw)


Victor Porton wrote:

> What is the right way to convert between C "void*" pointer and an access
> to a tagged or class-wide type?
> 
> Ada.Unchecked_Conversion seems to be what I need, but the access type may
> be "fat" and thus have another format than void*.
> 
> I caught myself doing such unchecked conversions, but now I feel I did an
> error.
> 
> For example, let
> 
> type X_Type is abstract tagged null record;
> 
> How to store X_Type'Class pointer in "void*" and convert them back and
> forth?

It seems I've found a right solution of my problem. (Check if Ada RM
warrants that it works with every compiler!)

Well, why it is not a standard package?! Why I need to invent something
"smart" every time I need to code?

with System.Address_To_Access_Conversions;
with Interfaces.C.Strings; use Interfaces.C.Strings;

-- C11, 6.2.5, 28 (draft N1548):
-- A pointer to void shall have the same representation and alignment requirements as a pointer to a character type.
-- So we can use chars_ptr to mean void pointer in C.

generic
    type Object(<>) is limited private;
package Convert_Void is

   package Address_Conversions is new System.Address_To_Access_Conversions(Object);

   subtype Object_Pointer is Address_Conversions.Object_Pointer;

   function To_Access (Void_Pointer: chars_ptr) return Object_Pointer;

   function To_C_Pointer (Pointer: Object_Pointer) return chars_ptr;

end Convert_Void;


with Ada.Unchecked_Conversion;

package body Convert_Void is

   type My_Char_Pointer is access all char with Convention=>C;

   function From_My_Char_Pointer is new Ada.Unchecked_Conversion(My_Char_Pointer, chars_ptr);
   function From_Chars_Ptr is new Ada.Unchecked_Conversion(chars_ptr, My_Char_Pointer);

   package Char_Address_Conversions is new System.Address_To_Access_Conversions(char);

   function To_Access (Void_Pointer: chars_ptr) return Object_Pointer is
   begin
      return Address_Conversions.To_Pointer(From_Chars_Ptr(Void_Pointer)'Address);
   end;

   function To_C_Pointer (Pointer: Object_Pointer) return chars_ptr is
      A: constant System.Address := Address_Conversions.To_Address(Pointer);
      P: constant My_Char_Pointer :=
        My_Char_Pointer(Char_Address_Conversions.To_Pointer(A));
   begin
      return From_My_Char_Pointer(P);
   end;

end Convert_Void;

-- 
Victor Porton - http://portonvictor.org

^ permalink raw reply	[relevance 7%]

* Re: win32 interfacing check (SetClipboardData)
  @ 2017-09-01 12:53  5%     ` Xavier Petit
  0 siblings, 0 replies; 200+ results
From: Xavier Petit @ 2017-09-01 12:53 UTC (permalink / raw)


Le 31/08/2017 à 03:41, Randy Brukardt a écrit :
> For me, using an address clause for anything other than interfacing to
> hardware is wrong. We certainly didn't do anything like this in Claw when
> implementing the clipboard operations. We used instances of
> Unchecked_Conversion to get a pointer of the right type, and then assigned
> into that. (Nowdays, I might use an instance of
> Address_to_Access_Conversions.)
Thank you, this was my first approach (and it worked), but when I tried 
the 'Address trick, I was surprised that it worked too so I removed the 
System.Address_To_Access_Conversions;
Finally I use the To_PWSTR of Win32 (Unchecked_Conversion) which seems 
to me simpler :

AMem := GlobalLock (HMem);
pragma Assert (AMem /= Null_Address);
Length := MultiByteToWideChar (CodePage       => CP_UTF8,
                                DwFlags        => 0,
                                LpMultiByteStr => Addr (Text),
                                CchMultiByte   => -1,
                                LpWideCharStr  => To_PWSTR (Amem),
                                CchWideChar    => Length);
Thanks for the CLAW example


^ permalink raw reply	[relevance 5%]

* Re: for X'Address use - and Volatile
  @ 2016-08-31 19:36  4% ` Randy Brukardt
  0 siblings, 0 replies; 200+ results
From: Randy Brukardt @ 2016-08-31 19:36 UTC (permalink / raw)


"Maciej Sobczak" <see.my.homepage@gmail.com> wrote in message 
news:7595494c-3398-4fd9-ab4b-80a79383ae33@googlegroups.com...
Hi,

>Consider:

>X : Integer;
>Y : Integer;
>for Y'Address use X'Address;
>
>The above is a simple overlay, typically used for under-the-table type 
>conversions.

Ada does not now, nor ever has, officially supported overlays. Such code 
might work on a particular implementation, but it's not portable (even to 
another version of the same compiler).

Indeed, address clauses ought to be avoided for all but their intended 
purpose (mapping to hardware registers); for other purposes, better 
solutions exist (Unchecked_Conversion, Address_to_Access_Conversions, etc.)

In addition, since you didn't declare these objects aliased, the compiler is 
allowed to optimize them completely away.

>AARM 13.3 says:
>
>"If the Address of an object is specified [...], then the implementation 
>should not perform optimizations based on >assumptions of no aliases."
>
>Interestingly, in the above example there are two objects involved in the 
>overlay, yet only one (Y)
>is affected by this rule (becaue Address is *specified* only for Y, not for 
>X). Let's assume that
>this is an omission

It's not. You ignored the important rule, 13.3(13/3):

If an Address is specified, it is the programmer's responsibility to ensure 
that the address is valid and appropriate for the entity and its use; 
otherwise, program execution is erroneous.

The associated AARM note says that "Appropriate for the entity and its use" 
covers cases like "addresses which would force objects that are supposed to 
be independently addressable to not be". Since X and Y are independently 
addressable and there is no way to avoid that, this case *always* will cause 
erroneous execution. Compilers (obviously) don't have to protect against 
that, so any optimization on X is allowed.

Indeed, since X isn't aliased, it's not even required that X'Address is 
meaningful (it could be in a machine register).

These things *might* work on a particular implementation, but no guarantees.

The correct way to do this is something like:

    package A2A is new System.Address_to_Access_Conversions (Integer);
    X : aliased Integer;
    Y : A2A.Object_Pointer := A2A.To_Pointer (X'Addresss);

or better still, avoid Address altogther:

   type Acc_Int is access all Integer;
   X : aliased Integer;
   Y : Acc_Int := X'Access; -- Or 'Unchecked_Access if accessibility is an 
issue.

(You need the former if the types are different, the latter if not. But Ada 
doesn't really allow the case with the types being different to be portable 
in any case - Unchecked_Conversion is needed, and even that isn't certain to 
be portable depending on the types involved.)

                                          Randy.

P.S. Yes, you hit two of my pet peeves about the way some people use Ada. 
Most compilers (but not Janus/Ada 95) try to support the overlay case 
because it was common in Ada 83 code -- both of the better alternatives 
didn't exist until Ada 95. Similarly with the use of Aliased on any 
stand-alone object that you're planning to take the 'Address of.

Trying to support these things makes Ada optimization many times more 
complex and substantially less effective than it otherwise could be. I 
suppose GNAT gets away with it since C has these issues many times worse and 
thus there already is support for that in the GCC backend. People not using 
a C backend have no such (dis?)advantage. Grrrrr.



^ permalink raw reply	[relevance 4%]

* Re: Generic Embedded List Nodes
  2016-06-22 13:01  0%                               ` G.B.
@ 2016-06-23  2:30  0%                                 ` Warren
  0 siblings, 0 replies; 200+ results
From: Warren @ 2016-06-23  2:30 UTC (permalink / raw)


On Wednesday, 22 June 2016 09:01:48 UTC-4, G.B.  wrote:
> On 21.06.16 12:31, Warren wrote:
> > The suggestion for System.Address_To_Access_Conversions seems like a potential solution. The only other thing I can do is try to cheat with a C routine returning an address, but GNAT is just as likely to complain.
> 
> At the risk of being non-C-ish, could you require the
> outer objects' type to have an operation that delivers
> its own 'Access, so that when linking the object via
> its embedded list thing, the latter could call said
> operation?

The issue is that you're starting with a Node_Type of some sort, which is present in the record.  GNAT won't let me do anything to compute the start of the record (actually computing it is ok, but won't let me use the record based upon that address). This is so messed up, that I've decided to abandon any semblance of this idea. Lucky for me, I can use a lookup array to do what I need efficiently.

Warren

^ permalink raw reply	[relevance 0%]

* Re: Generic Embedded List Nodes
  2016-06-21 10:31  5%                             ` Warren
  2016-06-21 21:38  0%                               ` Niklas Holsti
@ 2016-06-22 13:01  0%                               ` G.B.
  2016-06-23  2:30  0%                                 ` Warren
  1 sibling, 1 reply; 200+ results
From: G.B. @ 2016-06-22 13:01 UTC (permalink / raw)


On 21.06.16 12:31, Warren wrote:
> The suggestion for System.Address_To_Access_Conversions seems like a potential solution. The only other thing I can do is try to cheat with a C routine returning an address, but GNAT is just as likely to complain.

At the risk of being non-C-ish, could you require the
outer objects' type to have an operation that delivers
its own 'Access, so that when linking the object via
its embedded list thing, the latter could call said
operation?


^ permalink raw reply	[relevance 0%]

* Re: Generic Embedded List Nodes
  2016-06-21 10:31  5%                             ` Warren
@ 2016-06-21 21:38  0%                               ` Niklas Holsti
  2016-06-22 13:01  0%                               ` G.B.
  1 sibling, 0 replies; 200+ results
From: Niklas Holsti @ 2016-06-21 21:38 UTC (permalink / raw)


On 16-06-21 13:31 , Warren wrote:
> On Tuesday, 21 June 2016 01:52:51 UTC-4, Niklas Holsti  wrote:
>> On 16-06-21 05:20 , Warren wrote:
>>> On Monday, 20 June 2016 15:33:16 UTC-4, Niklas Holsti  wrote:
>>>> On 16-06-20 15:26 , Warren wrote:
>>>>
>>>>> Anyway folks- thanks for your help but I now have a working solution. I'm signing off this thread.
>>>>
>>>> Before signing off, do please describe your solution.
>>>
>>> I thought I had the problem licked using the following generic
>>> Object_Of function, but when I whipped up an example, the compile
>>> problem returned (or there was pilot error):
>>>
>>>    function Object_Of(
>>>       Node: access Emb_Node;
>>>       Member: Natural
>>>    ) return Object_Type is
>>>       use System.Storage_Elements;
>>>
>>>       A:    constant System.Address := Node.all'Address;
>>>       B:    constant System.Address := A - Storage_Offset(Member);
>>>       R:    Object_Type;
>>>       for R'Address use B;
>>>       pragma Import(Convention => Ada, Entity => R);
>>>    begin
>>>       return R;
>>>    end Object_Of;
>>>
>>> The compiler is complaining with:
>>>
>>> warning: controlled object "R" must not be overlaid.
>>
>> The component My_Recd.Name, of the controlled type Unbounded_String, is
>> making Object_Type also controlled. I well understand that the compiler
>> does not want controlled objects to be overlaid with address clauses.
>>
>> Instead of a function returning Object_Type, you could try returning an
>> access to Object_Type, as produced by an instance of
>> System.Address_To_Access_Conversions. In fact, if I understand your
>> goals, you do not want Object_Of to return a _copy_ of the object
>> containing the Emb_Node, the need is to _find_ that very object.
>> Returning an access value is closer to what you want, I believe.
>
> That is correct (no copy). The suggestion for System.Address_To_Access_Conversions seems like a potential solution. The only other thing I can do is try to cheat with a C routine returning an address, but GNAT is just as likely to complain.

It now seems to me that the solutions suggested so far are too 
elaborate, and that a very simple solution exists: an embedded list node 
is just an ordinary component, derived from a tagged root type which 
holds the Prev and Next links, with an access discriminant referring to 
the containing object. The OP asked for a "generic" solution, but IMO a 
generic would not be simpler than this direct form.

Example code follows. Compiled but not tested.

package Emb_List
is

    -- The class of "embedded list nodes":

    type Emb_Node_T is tagged;

    type Emb_Node_Ref_T is access all Emb_Node_T'Class;

    type Emb_Node_T is tagged record
       Prev, Next : Emb_Node_Ref_T;
       -- Prev and Next are null if the node is not in any list.
       -- When the node is first in a list, Prev points to the list head.
       -- When the node is last in a list, Next is null.
    end record;

    subtype List_T is Emb_Node_T;
    -- A list head.
    -- Next points to the first node in the list.
    -- Prev is null.

    procedure Insert_At_Head (
       List : access List_T;
       Node : in     Emb_Node_Ref_T);
    -- Prepends Node at the head of the list.
    -- Assumes that Node is not in any list, to start with.

    procedure Delete (Node : in Emb_Node_Ref_T);
    -- Deletes the Node from the list it lies in, assuming that
    -- the Node does lie in a list.

    -- An example type with two embedded list nodes:

    type Integer_Object_T;

    type Integer_Emb_Node_T (Obj : access Integer_Object_T)
    is new Emb_Node_T with null record;

    type Integer_Object_T is limited record
       Value : Integer;
       Node1 : aliased Integer_Emb_Node_T (Integer_Object_T'Access);
       Node2 : aliased Integer_Emb_Node_T (Integer_Object_T'Access);
    end record;

    -- An example object:

    Int_Obj : Integer_Object_T;

    -- Two example lists, empty by default:

    List1, List2 : aliased List_T;

end Emb_List;



package body Emb_List
is

    procedure Insert_At_Head (
       List : access List_T;
       Node : in     Emb_Node_Ref_T)
    is
    begin
       List.Next.Prev := Node;
       Node.Next := List.Next;
       List.Next := Node;
       Node.Prev := Emb_Node_Ref_T (List);
    end Insert_At_Head;

    procedure Delete (Node : in Emb_Node_Ref_T)
    is
    begin
       Node.Prev.Next := Node.Next;
       Node.Next.Prev := Node.Prev;
       Node.Prev := null;
       Node.Next := null;
    end Delete;

begin

    -- Add the example object to the example lists:

    Insert_At_Head (List1'Access, Int_Obj.Node1'Access);
    Insert_At_Head (List2'Access, Int_Obj.Node2'Access);

    -- Delete from List2:

    Delete (Int_Obj.Node2'Access);

end Emb_List;


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

^ permalink raw reply	[relevance 0%]

* Re: Generic Embedded List Nodes
  2016-06-21  5:52  4%                           ` Niklas Holsti
@ 2016-06-21 10:31  5%                             ` Warren
  2016-06-21 21:38  0%                               ` Niklas Holsti
  2016-06-22 13:01  0%                               ` G.B.
  0 siblings, 2 replies; 200+ results
From: Warren @ 2016-06-21 10:31 UTC (permalink / raw)


On Tuesday, 21 June 2016 01:52:51 UTC-4, Niklas Holsti  wrote:
> On 16-06-21 05:20 , Warren wrote:
> > On Monday, 20 June 2016 15:33:16 UTC-4, Niklas Holsti  wrote:
> >> On 16-06-20 15:26 , Warren wrote:
> >>
> >>> Anyway folks- thanks for your help but I now have a working solution. I'm signing off this thread.
> >>
> >> Before signing off, do please describe your solution.
> >
> > I thought I had the problem licked using the following generic
> > Object_Of function, but when I whipped up an example, the compile
> > problem returned (or there was pilot error):
> >
> >    function Object_Of(
> >       Node: access Emb_Node;
> >       Member: Natural
> >    ) return Object_Type is
> >       use System.Storage_Elements;
> >
> >       A:    constant System.Address := Node.all'Address;
> >       B:    constant System.Address := A - Storage_Offset(Member);
> >       R:    Object_Type;
> >       for R'Address use B;
> >       pragma Import(Convention => Ada, Entity => R);
> >    begin
> >       return R;
> >    end Object_Of;
> >
> > The compiler is complaining with:
> >
> > warning: controlled object "R" must not be overlaid.
> 
> The component My_Recd.Name, of the controlled type Unbounded_String, is 
> making Object_Type also controlled. I well understand that the compiler 
> does not want controlled objects to be overlaid with address clauses.
> 
> Instead of a function returning Object_Type, you could try returning an 
> access to Object_Type, as produced by an instance of 
> System.Address_To_Access_Conversions. In fact, if I understand your 
> goals, you do not want Object_Of to return a _copy_ of the object 
> containing the Emb_Node, the need is to _find_ that very object. 
> Returning an access value is closer to what you want, I believe.

That is correct (no copy). The suggestion for System.Address_To_Access_Conversions seems like a potential solution. The only other thing I can do is try to cheat with a C routine returning an address, but GNAT is just as likely to complain.

Warren


^ permalink raw reply	[relevance 5%]

* Re: Generic Embedded List Nodes
  @ 2016-06-21  5:52  4%                           ` Niklas Holsti
  2016-06-21 10:31  5%                             ` Warren
  0 siblings, 1 reply; 200+ results
From: Niklas Holsti @ 2016-06-21  5:52 UTC (permalink / raw)


On 16-06-21 05:20 , Warren wrote:
> On Monday, 20 June 2016 15:33:16 UTC-4, Niklas Holsti  wrote:
>> On 16-06-20 15:26 , Warren wrote:
>>
>>> Anyway folks- thanks for your help but I now have a working solution. I'm signing off this thread.
>>
>> Before signing off, do please describe your solution.
>
> I thought I had the problem licked using the following generic
> Object_Of function, but when I whipped up an example, the compile
> problem returned (or there was pilot error):
>
>    function Object_Of(
>       Node: access Emb_Node;
>       Member: Natural
>    ) return Object_Type is
>       use System.Storage_Elements;
>
>       A:    constant System.Address := Node.all'Address;
>       B:    constant System.Address := A - Storage_Offset(Member);
>       R:    Object_Type;
>       for R'Address use B;
>       pragma Import(Convention => Ada, Entity => R);
>    begin
>       return R;
>    end Object_Of;
>
> The compiler is complaining with:
>
> warning: controlled object "R" must not be overlaid.

The component My_Recd.Name, of the controlled type Unbounded_String, is 
making Object_Type also controlled. I well understand that the compiler 
does not want controlled objects to be overlaid with address clauses.

Instead of a function returning Object_Type, you could try returning an 
access to Object_Type, as produced by an instance of 
System.Address_To_Access_Conversions. In fact, if I understand your 
goals, you do not want Object_Of to return a _copy_ of the object 
containing the Emb_Node, the need is to _find_ that very object. 
Returning an access value is closer to what you want, I believe.

> The test record looks like this:
>
>    type My_Recd is
>       record
>          ID:         Natural;
>          Node:       aliased Emb_Node;
>          Name:       Unbounded_String;
>       end record;

If you don't get the address arithmetic to work, I believe that a set of 
mixin-generics could be used to add as many embedded Emb_Nodes to a 
tagged limited record, with access discriminants pointing to the 
containing record. This would eliminate the address arithmetic, at the 
cost of increasing the size of the record by the sizes of the 
discriminants (not a great deal).

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

^ permalink raw reply	[relevance 4%]

* ANN: Cortex GNAT RTS 20160522
@ 2016-05-22 14:20  4% Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2016-05-22 14:20 UTC (permalink / raw)


Available at
https://sourceforge.net/projects/cortex-gnat-rts/files/20160522/

This release includes GNAT Ada Run Time Systems (RTSs) based
on FreeRTOS (http://www.freertos.org) and targeted at boards with
Cortex-M3, -M4, -M4F MCUs (Arduino Due from http://www.arduino.org,
the STM32F4-series evaluation boards from STMicroelectronics at
http://www.st.com).

In each case, the board support for the RTS (configuration for size
and location of Flash, RAM; clock initialization; interrupt naming) is
in $RTS/adainclude. Support for the on-chip peripherals is also
included, in Ada spec files generated by SVD2Ada
(https://github.com/AdaCore/svd2ada).

The Ada source is either original or based on FSF GCC (mainly 4.9.1,
some later releases too).

(1) arduino-due is a Ravenscar-style RTOS based on FreeRTOS from
    http://www.freertos.org for the Arduino Due.

    See arduino-due/COPYING* for licensing terms.

    On-chip peripheral support in atsam3x8e/.

    Tests in test-arduino-due/.

(2) stm32f4 is a Ravenscar-style RTOS based on FreeRTOS from
    http://www.freertos.org for the STM32F4-DISC* board.

    See stm32f4/COPYING* for licensing terms.

    On-chip peripheral support in stm32f40x/.

    Tests in test-stm32f4/.

(3) stm32f429i is a Ravenscar-style RTOS based on FreeRTOS from
    http://www.freertos.org for the STM32F429I-DISC* board.

    See stm32f429i/COPYING* for licensing terms.

    On-chip peripheral support in stm32f429x/.

    Tests in test-stm32f429i/.

In this release,

* There is no longer any dependence on the STMicroelectronics'
  STM32Cube package.

* The support for on-chip peripherals is limited to the
  SVD2Ada-generated spec files. The AdaCore 'bareboard' software
  (currently https://github.com/AdaCore/bareboard, but a name change
  is under consideration) supports the STM32 line.

* Tasking no longer requires an explicit start
  (https://sourceforge.net/p/cortex-gnat-rts/tickets/5/).

* Locking in interrupt-handling protected objects no longer inhibits
  all interrupts, only those of equal or lower priority
  (https://sourceforge.net/p/cortex-gnat-rts/tickets/18/).

The standard packages included (there are more, implementation-specific,
ones) are:

Ada
Ada.Containers
Ada.Containers.Bounded_Hashed_Maps
Ada.Containers.Bounded_Vectors
Ada.Exceptions
Ada.IO_Exceptions
Ada.Interrupts
Ada.Interrupts.Names
Ada.Iterator_Interfaces
Ada.Real_Time
Ada.Streams
Ada.Synchronous_Task_Control
Ada.Tags
Ada.Task_Identification
Interfaces
Interfaces.C
Interfaces.C.Strings
System
System.Assertions
System.Address_To_Access_Conversions
System.Storage_Elements
GNAT
GNAT.Source_Info


^ permalink raw reply	[relevance 4%]

* ANN: Cortex GNAT RTS 20160314
@ 2016-03-14 17:42  5% Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2016-03-14 17:42 UTC (permalink / raw)


At https://sourceforge.net/projects/cortex-gnat-rts/files/20160314/.

This release includes

* an RTS for the Arduino Due, arduino-due, and a minimal BSP,
  arduino-due-bsp.

* an RTS for the STM32F429I-DISCO, stm32f429i-disco-rtos, based on
  STMicroelectronics' STM32Cube package and FreeRTOS, and a
  corresponding partial BSP, stm32f429i-disco-bsp.

* an RTS for the STM32F429I-DISCO, stm32f429i, based on FreeRTOS, with
  a set of peripheral definition packages created by SVD2Ada.

In this release,

* the Containers support generalized iteration ("for all E of C
  loop"). Note, this is achieved by removing tampering checks. While
  tampering errors are rare, it would be as well to check algorithms
  using a fully-featured desktop compiler.

The standard packages included (there are more, implementation-specific,
ones) are:

Ada
Ada.Containers
Ada.Containers.Bounded_Hashed_Maps
Ada.Containers.Bounded_Vectors
Ada.Exceptions
Ada.IO_Exceptions
Ada.Interrupts
Ada.Interrupts.Names
Ada.Iterator_Interfaces
Ada.Real_Time
Ada.Streams
Ada.Synchronous_Task_Control
Ada.Tags
Ada.Task_Identification
Interfaces
Interfaces.C
Interfaces.C.Strings
System
System.Assertions
System.Address_To_Access_Conversions
System.Storage_Elements
GNAT
GNAT.Source_Info


^ permalink raw reply	[relevance 5%]

* ANN: Cortex GNAT RTS 20160207
@ 2016-02-07 22:45  5% Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2016-02-07 22:45 UTC (permalink / raw)


This release is at Sourceforge[1].

This release includes an RTS for the Arduino Due, arduino-due, and a
minimal BSP, arduino-due-bsp.

For the STM32F429I-DISCO, there is one RTS, stm32f429i-disco-rtos, and
one BSP, stm32f429i-disco-bsp.

In this release,

* the Containers support generalized iteration ("for all E of C
  loop"). Note, this is achieved by removing tampering checks. While
  tampering errors are rare, it would be as well to check algorithms
  using a fully-featured desktop compiler.

* FreeRTOS is configured to detect stack overflow (if it is detected,
  the RTS loops inside vApplicationStackOverflowHook()).

The standard packages included (there are more,
implementation-specific, ones) are:

   Ada
   Ada.Containers
   Ada.Containers.Bounded_Hashed_Maps
   Ada.Containers.Bounded_Vectors
   Ada.Exceptions
   Ada.IO_Exceptions
   Ada.Interrupts
   Ada.Interrupts.Names
   Ada.Iterator_Interfaces
   Ada.Real_Time
   Ada.Streams
   Ada.Synchronous_Task_Control
   Ada.Tags
   Ada.Task_Identification
   Interfaces
   Interfaces.C
   Interfaces.C.Strings
   System
   System.Assertions
   System.Address_To_Access_Conversions
   System.Storage_Elements
   GNAT
   GNAT.Source_Info

The software is supplied built with for debugging (-g) and with suitable
optimisation (-Og), using GNAT GPL 2015 on Mac OS X (it should work
out of the box with a Linux-hosted GNAT GPL 2015 cross-compiler, but
will need recompiling for another compiler version).

[1] https://sourceforge.net/projects/cortex-gnat-rts/files/20160207/


^ permalink raw reply	[relevance 5%]

* Re: Linux kernel module - memory allocation
  2015-05-18  8:56  3% ` Niklas Holsti
@ 2015-05-18  9:19  0%   ` q.kontinuum
  0 siblings, 0 replies; 200+ results
From: q.kontinuum @ 2015-05-18  9:19 UTC (permalink / raw)


Hi, thanks a lot for the fast reply.

In comp.lang.ada, you wrote:
> On 15-05-18 11:27 , q.kontinuum wrote:
> Do you mean a real "driver", either kernel-linked or a loadable module? 

Yes, I'm aiming for a loadable kernel module.

> Which Ada compiler are you using? Do you use some specific compiler 
> switches to adapt it to the driver environment?

I'm using gnat. Command line to compile a 
gnatmake -a -s -mcmodel=kernel ...

> But GNAT can also translate some C headers into Ada 
> declarations automatically.

I should look into that. Good to know.

> You could try with a constrained string subtype, say String(1 .. 10), 

I assume if I use that within a function, I'd run into the same problem
because the function might be called more often, thus still requiring
dynamic allocation. Since I know that only one instance of the driver 
will be used single threaded, and only one buffer is used, I could 
declare it in the modules declaration section rather than the function.

> what you should use. Perhaps you can wrap it up as a user-defined Ada 
> "storage pool" (see the Ada RM 13.11) which would let you use the "new" 
> statement

This sounds like just what I need - I will definitely have a closer look
at it, thanks a bunch!

> or you can write an Ada binding in the same way as for your C 
> wrappers. kmalloc seems to return a C "void *". Assuming that this is 
> implemented as an address, you should be able to use the predefined Ada 
> package System.Address_To_Access_Conversions to convert the kmalloc 
> result to a pointer of any type you want (but beware memory alignment 
> errors -- the documentation for kmalloc that I found did not promise to 
> return memory aligned in any particular way).

Thanks, sounds like a good starting point to gather some further 
information myself.


^ permalink raw reply	[relevance 0%]

* Re: Linux kernel module - memory allocation
  @ 2015-05-18  8:56  3% ` Niklas Holsti
  2015-05-18  9:19  0%   ` q.kontinuum
  0 siblings, 1 reply; 200+ results
From: Niklas Holsti @ 2015-05-18  8:56 UTC (permalink / raw)


On 15-05-18 11:27 , q.kontinuum wrote:
> I'm new to this group, new to Ada programming, and a bit out of touch with
> Linux driver development for some time. Since I want to learn Ada and want
> to get back in touch with Linux I'm trying to implement a driver for my
> raspberry-pi, to access a DS18B20 temperature sensor via onewire protocol.

I don't know much about the Linux driver environment, but perhaps I can 
help you a bit...

Do you mean a real "driver", either kernel-linked or a loadable module? 
Or do you mean user-land SW to operate the sensor through some existing 
I/O driver for the I/O channel? From the error messages you get, I guess 
you want to make a loadable driver module.

Which Ada compiler are you using? Do you use some specific compiler 
switches to adapt it to the driver environment?

> The steps I already took was to implement a small wrapper in C to link
> with a first Hello world module in Ada and to access the hr_timer of the
> Linux kernel (here I again used to wrapper and called it from Ada to avoid
> cloning the whole hrtimer struct from Linux kernel header files)

Yes, it is often simpler to have a C wrapper, if the header files are 
complex. But GNAT can also translate some C headers into Ada 
declarations automatically.

> Where I'm getting stuck now is a function returning a String. I simplified
> the function to this:
>
>     function UInt2String(I : Integer) return String is
>     begin
>        return "";
>     end;
>
> As soon as this function is used somewhere, I can't load the module.
> Here is the kernel log output when I try to load the module:
>
> May 18 10:19:39 localhost kernel: [87978.938801] wrapper:
>     Unknown symbol system__secondary_stack__ss_allocate (err 0)

A function that returns a value of run-time dynamic size, such as the 
unconstrained String in your example, needs support from the Ada 
run-time system (RTS). In the GNAT compiler, this support takes the form 
of a "secondary stack" that is used to hold such data of dynamic size, 
but with first-in-first-out life-times.

The error message you get shows that the kernel (of course) does not 
provide this Ada-specific support.

You could try with a constrained string subtype, say String(1 .. 10), 
but I suspect that you should be using some very specific GNAT switches 
to completely eliminate any dependency on the GNAT RTS (which will of 
course constrain the kind of Ada code you can run in this environment).

> I will need to store a binary tree later on to store the addresses of the
> devices found on the onewire bus. In C, I'd probably use kmalloc and
> casts to allocate memory for a node of the tree. How should I do that in
> Ada?

If kmalloc is what your environment (kernel) provides, I suppose that is 
what you should use. Perhaps you can wrap it up as a user-defined Ada 
"storage pool" (see the Ada RM 13.11) which would let you use the "new" 
statement, or you can write an Ada binding in the same way as for your C 
wrappers. kmalloc seems to return a C "void *". Assuming that this is 
implemented as an address, you should be able to use the predefined Ada 
package System.Address_To_Access_Conversions to convert the kmalloc 
result to a pointer of any type you want (but beware memory alignment 
errors -- the documentation for kmalloc that I found did not promise to 
return memory aligned in any particular way).

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

^ permalink raw reply	[relevance 3%]

* Re: passing messages between the tasks
  @ 2014-10-14 22:22  5%         ` Shark8
  0 siblings, 0 replies; 200+ results
From: Shark8 @ 2014-10-14 22:22 UTC (permalink / raw)


On 10/14/2014 3:08 PM, compguy45@gmail.com wrote:
> What i am trying to do is something like this....code from above...
>
> 3
>    4 procedure SomeProcedure is
>    5
>    6 task type lamp is
>    7    entry reset(id : Integer);
>    8 end lamp;
>    9
>   10 lamps : array (1..6) of lamp;
>   11
>   12    task body lamp is
>   13    begin
>   14       Put_Line("Body of task lamp");
>   15       accept reset(id : Integer) do
>   16         put("inside reset");
>   17         put(id);
>   18         New_Line;
>   19       end reset;
>   20       delay 4.0;
>   21    put("after accept");
>   22    end lamp;
>   23
>   24 begin
>   25    lamps(1).reset(id => 1);
>   26    lamps(2).reset(id => 2);
>   27 end SomeProcedure;
>
> I am trying to figure out how to do following....
> have say main tasks call reset on say lamps(3).reset....
> Then lamp(3) would call reset on lamps(2) and lamps(1) and wait
> then someone lamps(2) and lamps(1) when they done with reset
> would somehow let lamp(3) know about it....
>
>Is this possible to do...?

Hm, I think it is -- but it's a bit on the convoluted side; when I saw 
your first post asking the same question I wrote up some code as a bit 
of a proof of concept. It kind-of works, I could probably get it a lot 
better if (A) I had more time, and/or (B) I had more experience w/ 
tasks. {Tasks are a great feature; I just haven't had occasion to use 
them all that often.}

Anyway; here's what I got for making a network of tasks -- which is, 
essentially, what you're asking about:

-----------------
--  NODES.ADS  --
-----------------

Package Nodes is
    type Node_Interface is task interface;


    type Node_Access is access all Node_Interface'Class;
    type Node_List is array(Positive range <>) of Node_Access;

    Function "XOR" (Left : Node_List; Right : Positive) return Node_List is
      ( Left(Left'First..Natural'Pred(Right)) & 
Left(Natural'Succ(Right)..Left'Last) );
    Function "XOR" (Left : Node_List; Right : Positive) return not null 
access Node_List is
      ( New Node_List'(Left XOR Right) );


    Function Null_List return not null access Node_List is
       ( New Node_List'(2..1 => <>) );

    Function Make_Network(Size : Natural) return not null access Node_List;

    task type Node( Neighbors : not null access Node_List ) is
         new Node_Interface with
    end Node;

End Nodes;


-----------------
--  NODES.ADB  --
-----------------
with
Ada.Task_Identification,
Unchecked_Conversion,
      System.Address_To_Access_Conversions,
      System.Address_Image,
Ada.Text_IO;

Package body Nodes is
    Package Node_Pointers is new
      System.Address_To_Access_Conversions(Object => Node);

    Function Convert is new Unchecked_Conversion
      (Source => Node_Pointers.Object_Pointer,  Target => Node_Access);

    Function Convert( A : System.Address ) return Node_Access is
      ( Convert(Node_Pointers.To_Pointer( A )) );

    task body Node is
       use Ada.Task_Identification, System;

       New_Line : Constant String:= ASCII.CR & ASCII.LF;


       Function Line_1 return String is
         ("Task " & Image(Current_Task) & ": " & Neighbors'Length'Img
              & ASCII.HT & Address_Image(Node'Access.All'Address)
          & New_Line
         );

       Function Line_2( Input : Node_List ) return String is
         (if Input'Length = 0 then ""
          else
              ASCII.HT & Address_Image(Input(Input'First).All'Address) & 
New_Line
            & Line_2( Input(Input'First+1..Input'Last) )
         );

       Function Line_2 return String is
          ( Line_2(Node.Neighbors.All) );
       Function Line_3 return String is
         ("Done.");
    begin
       Ada.Text_IO.Put_Line( Line_1 & Line_2 & Line_3 );
       null;
    end Node;


    Function Make_Network(Size : Natural) return Node_List;
    Function Make_Network(Size : Natural) return not null access 
Node_List is
       ( New Node_List'(Make_Network(size)) );


    Function Make_Network(Size : Natural) return Node_List is
       subtype Full_Range       is Positive Range 1..Size;
       subtype Full_Node_List   is Node_List(Full_Range);

       subtype Constrained_List is Node_List(1..Size-1);
       subtype Constrained_Node is Node( Neighbors => new 
Constrained_List );
       Type Task_Array is array (Full_Range) of aliased Constrained_Node;

       Package TAP is new System.Address_To_Access_Conversions(Task_Array);

       Generic
       Package Incrementation is
          Procedure Increment;
          Function  Increment return Full_Range;
       End Incrementation;

       Package body Incrementation is
          Index : Full_Range:= Full_Range'First;
          Function  Increment return Full_Range is
          begin
             Return  Result : constant Full_Range:= Index do
                Increment;
             end return;
          end Increment;

          Procedure Increment is
          begin
             Index:= (if Index = Full_Range'Last then Full_Range'First
                      else Full_Range'Succ( Index ));
          end Increment;
       end Incrementation;


       Function Make_Nodes(Task_List : out Task_Array) return Node_List is

          Package Inc is new Incrementation;
          Use Inc;

          List : constant Full_Node_List:=
            ( others => Convert(Task_List(Increment)'Address) );

             Function Get_List return Constrained_List is
             begin
                Return Result : Constrained_List:= List xor Increment;
             end;

             List_List : constant Array(Full_Range) of Constrained_List:=
                            (others => Get_List);

          Function Make_Tasks( List : Full_Node_List ) return Task_Array is
             Subtype Actual_Node is
               Node(Neighbors => New Node_List'(List_List(Increment)));
             Type Task_Cluster is Array(Full_Range) of Actual_Node;

             Function Tasks return Task_Cluster is
             begin
                Return result: Task_Cluster;
             end;

             Function Convert is new Unchecked_Conversion
               (Source => Task_Cluster, Target => Task_Array);
          begin
             Return Convert( Tasks );
          end Make_Tasks;



       Begin
          return Result : Full_Node_List := List do

             declare
                pragma Warnings( Off );
                K : Task_Array:= Make_Tasks(result)
                  with Address => Task_List'Address;
                pragma Warnings( On );
             begin
                null;
             end;
--              for Index in Full_Range loop
--                 declare
--                    N : Node renames Task_List(Index);
--                    A : constant System.Address := N'Address;
--                    pragma Warnings( Off );
--                    T : Node(Neighbors => New 
Node_List'(List_List(Index)))
--                      with Address => A;
--                    pragma Warnings( On );
--                 begin
--                    null;
--                 end;
--              end loop;

          end return;
       End Make_Nodes;



       Tasks : aliased Task_Array with Import;

    begin
       Return Make_Nodes(Tasks);
    end Make_Network;

End Nodes;


----------------
--  TEST.ADB  --
----------------
With
Nodes;

procedure Test is
    use all type Nodes.Node_List;

    Children_1 : not null access Nodes.Node_List:= Nodes.Make_Network(3);
    Master   : Nodes.Node( Neighbors =>
                           Children_1
                           --Nodes.Null_List
                          );

begin
    null;
end Test;



^ permalink raw reply	[relevance 5%]

* Re: Best representation for spares
  @ 2014-02-16 16:33  6%               ` Niklas Holsti
  0 siblings, 0 replies; 200+ results
From: Niklas Holsti @ 2014-02-16 16:33 UTC (permalink / raw)


On 14-02-16 15:40 , Rego, P. wrote:
> On Sunday, February 16, 2014 7:02:41 AM UTC-3, Niklas Holsti wrote:
>> Here you are "overlaying" a record object on a specific storage
>> location, presumably a memory-mapped I/O control register. This is OK,
>> but it has consequences...
> But is there a diffferent way to memory-map the registers?

You can use System.Address_To_Access_Conversions to create a reference
(pointer, access) to the memory address, and then use that pointer:

    package Conversions is new System.Address_To_Access_Conversions (
       Object => Mem_Mapped_Reg_T);

    Ptr : Conversions.Object_Pointer :=
       Conversions.To_Pointer (System'To_Address (16#.....#));

    Reg : Mem_Mapped_Reg_T;

    Reg := Ptr.all;
    ...
    Ptr.all := Reg;

>> If the Spare bits are documented as "reserved", there should
>> not be any need to initialize just them...
> 
> There are some points in datasheet which are a little confusing,
> it says the spare is "reserved", but also says "write zero" in
> some cases (not all).

The bits are typically "reserved" because some later version of the HW
may define some meaning for them, for example to activate some advanced
HW functions that are not available now.

Usually, in order to write anything to a MMIO register, the program has
to write the *entire* register at once, using a word-sized memory-store
instruction. Writing only one bit, or only some other part of the
register, is not usually supported by the HW (except on some small
microcontrollers with bit-addressed memory). This means that you cannot
avoid writing the reserved bits too. The datasheet is saying that you
should write zeroes to the reserved bits, and then nothing bad will
happen even in the future -- no new surprising effects will happen even
if the program is executed in some new version of the HW where the
reserved bits have been given some new functions.

It does not mean (usually) that you *must* initialize these bits to
zero; it means that writing zero is safe, while writing something else
may not be.

> I did not get. Is is better to use
> Auxiliary_Peripherals_Register_Map: 
>    Auxiliary_Peripherals_Register_Map_Type 
>       := (others => <>);
> or just initialize in system initialization?

I would initialize only in the system init, using an assignment
statement. Using either an overlay, or a pointer from
Address_To_Access_Conversions. The pointer method has the advantage that
you can then default-initialize Spares, and it will work:

   Reg_Init : Memory_Mapped_Reg_T;
   ...
   Reg_Init.X := ...;
   Reg_Init.Y := ...;

   Ptr.all := Reg_Init;

Reg_Init.Spares can be default initialized (e.g. to zero), and those
zeroes will be written to Ptr.all. But I would probably write use an
aggregate expression, and not a variable:

   Ptr.all := (X => ..., Y => ..., Spares => ...);

and not bother with default initializations.

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

^ permalink raw reply	[relevance 6%]

* Re: Gnat's Handling of Record with Address Clause
  2013-09-26 15:05  0%   ` Eryndlia Mavourneen
@ 2013-09-26 15:21  4%     ` Adam Beneschan
  0 siblings, 0 replies; 200+ results
From: Adam Beneschan @ 2013-09-26 15:21 UTC (permalink / raw)


On Thursday, September 26, 2013 8:05:17 AM UTC-7, Eryndlia Mavourneen wrote:

> Since the "Message" parameter is an address, I assume that you mean declaring an access type for My_Buffer_T, then doing the address -> access conversion for an access variable on that type.  

Yes.

> A lot of work to get around this Gnat issue.  

I think using System.Access_To_Address_Conversions is the right way to do it, regardless of whose compiler you're using.  Using an Address aspect on a discriminant record type like this is going to be problematic, without a specific language feature to support it.  As you found out, the language doesn't let you declare objects of indefinite types without specifying the constraints, even if you have an Address aspect; but if you do specify the discriminant constraint, what do you put for the constraint, given that the correct value will be something that has to be read from memory?  So there are language design issues involved with using Address on a discriminant record; it's not really a GNAT issue.  Even on a non-discriminant record, there are potential problems with the Address aspect because record fields that have implicit initializers are still going to be initialized, unless there's also an Import aspect.  (See AARM 13.3(12.d/3).)  

So on balance, it's probably right in general to use System.Address_To_Access_Conversions instead of Address aspects.

                              -- Adam

^ permalink raw reply	[relevance 4%]

* Re: Gnat's Handling of Record with Address Clause
  2013-09-26 14:48  5% ` Adam Beneschan
@ 2013-09-26 15:05  0%   ` Eryndlia Mavourneen
  2013-09-26 15:21  4%     ` Adam Beneschan
  0 siblings, 1 reply; 200+ results
From: Eryndlia Mavourneen @ 2013-09-26 15:05 UTC (permalink / raw)


On Thursday, September 26, 2013 9:48:23 AM UTC-5, Adam Beneschan wrote:
> On Thursday, September 26, 2013 7:23:36 AM UTC-7, Eryndlia Mavourneen wrote:
> 
> I haven't looked over the whole post yet, but just looking at this part:
> 
> > RM 13.1(22) says: "An implementation need not support the specification for a representation aspect that contains nonstatic expressions, unless each nonstatic expression is a name that statically denotes a constant declared before the entity."
> 
> > The overall effect of all this appears to be that Gnat is allowed to disallow a dynamically-determined address for an object.  If this is what is happening here (not a bug in Gnat), then it would seem that any kind of OS work, looping through a kernel linked list, for instance, would not be possible.
> 
> it seems that you could still use System.Address_To_Access_Conversions to achieve what you need.  (RM 13.7.2)
> 
>                               -- Adam

Thank you for the idea, Adam.  This sounds like an approach; I will try it.

Since the "Message" parameter is an address, I assume that you mean declaring an access type for My_Buffer_T, then doing the address -> access conversion for an access variable on that type.  

A lot of work to get around this Gnat issue.  I wonder why Adacore doesn't just allow you to do this in the first place.  The use of the Address clause should be enough of a flag of a potential problem.  -or-  Is this handling of a dynamic address really that difficult to implement?

-- Eryndlia (KK1T)


^ permalink raw reply	[relevance 0%]

* Re: Gnat's Handling of Record with Address Clause
  @ 2013-09-26 14:48  5% ` Adam Beneschan
  2013-09-26 15:05  0%   ` Eryndlia Mavourneen
  0 siblings, 1 reply; 200+ results
From: Adam Beneschan @ 2013-09-26 14:48 UTC (permalink / raw)


On Thursday, September 26, 2013 7:23:36 AM UTC-7, Eryndlia Mavourneen wrote:

I haven't looked over the whole post yet, but just looking at this part:

> RM 13.1(22) says: "An implementation need not support the specification for a representation aspect that contains nonstatic expressions, unless each nonstatic expression is a name that statically denotes a constant declared before the entity."
> 
> The overall effect of all this appears to be that Gnat is allowed to disallow a dynamically-determined address for an object.  If this is what is happening here (not a bug in Gnat), then it would seem that any kind of OS work, looping through a kernel linked list, for instance, would not be possible.

it seems that you could still use System.Address_To_Access_Conversions to achieve what you need.  (RM 13.7.2)

                              -- Adam


^ permalink raw reply	[relevance 5%]

* Re: System.Address to Access to function/procedure conversion
  @ 2013-07-28 20:04  4%     ` Jeffrey Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey Carter @ 2013-07-28 20:04 UTC (permalink / raw)


On 07/28/2013 12:05 PM, Tarek Ghaleb wrote:
>
> Interesting, I thought System.Address was equivalent to a C pointer,
> and I've seen it used that way in many snippets of code, etc. For
> things like void*, if not represented as System.Address, how would it
> be represented then?

Such code is compiler-dependent. GNAT usually (always?) maintains a 
correspondence between hardware address, System.Address, access types, and C 
pointers, but I've certainly used compilers where that wasn't true. I recall one 
system written originally with GNAT that was ported to Rational (same platform). 
The code used Unchecked_Conversion between access types and System.Address, 
which failed miserably on Rational, where the 2 were not the same. It had to be 
revised to use System.Address_To_Access_Conversions, which was not a trivial 
undertaking. Moral: it's usually cheaper to write portable code in the 1st place.

A void* passed between C and Ada is usually C's equivalent of a private type, 
with all values coming from C and never dereferenced by Ada. For such cases, all 
that we need to model in Ada is that what we have is a C pointer. The 
implementation usually looks like

type Void is null record;
type Void_Ptr is access all Void;
pragma Convention (C, Void_Ptr);

Of course, there's no real need for type Void; Void_Ptr could be "access all 
Integer" and it would work just as well. The advantage of using Void is that 
anyone who dereferences a Void_Ptr gets something useless.

If Void_Ptr is declared publicly, it should obviously be [limited] private. And 
usually there's a better name for it than Void_Ptr.

-- 
Jeff Carter
"Oh Lord, bless this thy hand grenade, that with it thou
mayst blow thine enemies to tiny bits, in thy mercy."
Monty Python and the Holy Grail
24

^ permalink raw reply	[relevance 4%]

* System.Address to Access to function/procedure conversion
@ 2013-07-28 15:27  4% Tarek Ghaleb
    0 siblings, 1 reply; 200+ results
From: Tarek Ghaleb @ 2013-07-28 15:27 UTC (permalink / raw)


Hi Everyone,

This is my first post to comp.lang.ada and it is so embarrassingly
trivial. Given an Address of a function/procedure, how can you call it
or convert the address to an access?

I first thought of System.Address_To_Access_Conversions, but then it
doesn't seem to work for a function/procedure.

The way I finally did it was to wrap an access to the function in a
record and then pass the Address of the record, but there must be a
simpler way.

As for why not just pass an Access to the function directly, the
Address is actually passed to a C function which later passes it back
to Ada.

Tarek.

-- 
For fools rush in where angels fear to tread. -- Alexander Pope

--- news://freenews.netfront.net/ - complaints: news@netfront.net ---


^ permalink raw reply	[relevance 4%]

* Re: Tasking troubles, unexpected termination.
  @ 2012-10-31  2:17  2%     ` Shark8
  0 siblings, 0 replies; 200+ results
From: Shark8 @ 2012-10-31  2:17 UTC (permalink / raw)


Here's the updated code:

---- Scheduling.adb ------------------------------------------
with
Ada.Text_IO,
Ada.Calendar,
Ada.Containers.Indefinite_Vectors,
Ada.Task_Termination,
Ada.Task_Identification,
Task_Debugging;

Procedure Scheduling is

    -- Introduce shorthand so convert Strings to access strings.
    Function "+" (Item : String) Return Not Null Access String is
      ( New String'(Item) );
    
    -- Forward declare the Notification type; indicate it has discriminants.
    Type Notification(<>);
    
    -- Declare Handle for Notifications.
    Type Notification_Handle is Not Null Access Notification;
    
    Type Notification(	Message	: Not Null Access String;
			Expiry	: Not Null Access Ada.Calendar.Time
		     ) is null record;
    
    -- Declare the Timing-task.
    Task Type Timing ( Resolution : Not Null Access Duration ) is
	Entry Add( Event : Notification_Handle );
    end Timing;

    
    -- Implementation for the timing-task.
    Task body Timing is

	-- Package for showing Duration.
	Package Decimal_Display is new Ada.Text_IO.Fixed_IO( Duration );
	
	-- Internal package, defining Vectors holding notification handles.
	Package Notification_Vector is New Ada.Containers.Indefinite_Vectors
	  ( Index_Type => Positive, Element_Type => Notification_Handle );
	Use Notification_Vector;
	
	-- Handle expired messages.
	Procedure Handle_Expiration( List : in out Vector ) is
	    Use Ada.Calendar, Ada.Text_IO;
	    Length : Positive:= Positive(List.Length);
	    Now    : Time:= Clock;

	    -- We flag everything to be deleted, as tampering with the cursor is
	    -- not good.
	    Type Deletion_Flags is Array(1..Length) of Boolean;
	    Deletion_Marks : Deletion_Flags:= (Others => False);
	    
	    
	    procedure Execute(Position : Cursor) is
		Item	: Constant Notification_Handle:= Element(position);
		Index	: Constant Positive:= Positive( To_Index(position) );
	    begin
		Deletion_Marks(Index):= Now >= Item.Expiry.All;
		--
		Ada.Text_IO.Put( ASCII.HT & "Exipration: " );
		Decimal_Display.Put( Item.Expiry.All - Now, Fore => 2, Aft => 3 );
		Ada.Text_IO.New_Line;
	    end Execute;

	begin
	    -- Iterate through the vector's elements; old-style iterator.
	    List.Reverse_Iterate( Process => Execute'Access );

	    -- Delete flagged elements; iteration bckwards to preserve indicies.
	    For Index in reverse Deletion_Marks'Range loop
		if Deletion_Marks(Index) then
		    
		    Put_Line( "Message: " & List(Index).Message.All);
		    List.Delete( Index );
		end if;
	    end loop;
	    
	    -- Render a report on the new length, if it was altered.
	    declare
		Post_op_length : Natural:= Natural(List.Length);
	    begin
		if Length /= post_op_length then
		    Put_Line( "Deleted items; New Length:" &  post_op_length'Img);
		end if;
	    end;
	end Handle_Expiration;

	-- Declare a Vector to hold all the nofifications.
	Notification_List : Vector:= Empty_Vector;
	
	Use Ada.Task_Termination, Task_Debugging, Ada.Containers, Ada.Calendar;
	
	-- Mark the start-time.
	Start : Time:= Clock;
	
--	Function Elapsed Return String is
--	  ( Duration'Image(Clock - Start)(1..7) );
	Function Elapsed Return Duration is
	  ( Clock - Start );

    begin
	-- Set our debugging-handler for this task.
	Ada.Task_Termination.Set_Specific_Handler(
		T       => Ada.Task_Identification.Current_Task,
		Handler => Debug.Termination'Access );

	-- When there are no items in our internal vector, then we need can only
	-- accept Add or terminate the task.
	-- When we add an item, then we can either add another item or when the
	-- time expires iterate the vector and handling Notifications as needed.
	loop
	    select 
		accept Add( Event : Notification_Handle ) do
		    Notification_List.Append( Event );
		end add;
		while not Notification_List.Is_Empty loop
		    Ada.Text_IO.Put( "Elapsed:" );
		    Decimal_Display.Put( Elapsed, Fore => 2, Aft => 3 );
		    Ada.Text_IO.New_Line;
		    Handle_Expiration( List => Notification_List );
		    select
			accept Add( Event : Notification_Handle ) do
			    Notification_List.Append( Event );
			    Ada.Text_IO.Put_Line( "New Length: " & Notification_List.Length'Img );
			    Ada.Text_IO.Put( ASCII.HT & "Exipration: " );
			    Decimal_Display.Put( Event.Expiry.All - Clock, Fore => 2, Aft => 3 );
			    Ada.Text_IO.New_Line;
			end add;
		    or
			delay Timing.Resolution.All;
		    end select;
		end loop;
		Ada.Text_IO.Put_Line( "EMPTY." );
	    or
		terminate;
	    end select;
	end loop;
    end Timing;
    
    
      
    K : Timing( Resolution => New Duration'(2.0) ); -- 2 second resolution.
    Now : Ada.Calendar.Time:= Ada.Calendar.Clock;
begin
    For Index in 1..10 loop
	declare
	    Use Ada.Calendar;
	    Item : Notification(
			 Message => + ("DD"&Positive'Image(Index)),
			 -- Expire at Now and 3*Index seconds.
			 Expiry  => New Time'( Now + Duration(Index) )
			);
	begin
	    K.Add( Event => New Notification'(Item) );
	end;
    end loop;
    
    -- Add an element in the past... it should immediately be operated on.
    K.Add( Event => New Notification'(
	Message => + ("Last."),
	Expiry  => New Ada.Calendar.Time'( Now )
	)
    );

end Scheduling;

---- Task_Debugging.ads ----------------------------------------------
-- The following are not strictly nessacary, but used in this example for 
-- debugging purposes.
With
System.Address_To_Access_Conversions,
Ada.Unchecked_Conversion,
Ada.Exceptions.Traceback,
Ada.Task_Identification,
Ada.Task_Termination;

Package Task_Debugging is
    Pragma Elaborate_Body;
    
    Protected Type Debugging is
	-- Termination debugging function.
	procedure Termination(
				 Cause : Ada.Task_Termination.Cause_Of_Termination;
				 T     : Ada.Task_Identification.Task_Id;
				 X     : Ada.Exceptions.Exception_Occurrence);

    End Debugging;
    
    -- Debug, an instance of our debugging object.
    Debug : Debugging;
    
End Task_Debugging;

---- Task_Debugging.adb ----------------------------------------------
With Ada.Text_IO;

Package Body Task_Debugging is

    Protected body Debugging is
	-- Termination debugging function.
	procedure Termination(
		       Cause : Ada.Task_Termination.Cause_Of_Termination;
		       T     : Ada.Task_Identification.Task_Id;
		       X     : Ada.Exceptions.Exception_Occurrence) is
	    Use Ada.Text_IO, Ada.Task_Termination, Ada.Exceptions;
	begin
	    Put_Line("Termination: "& Cause'Img);
	    case Cause is
	    When Normal | Abnormal => Null;
	    When Unhandled_Exception =>
		Put_Line( Exception_Name(X)&": "&Exception_Message(X) );
	    end case;
	end Termination;	
    end Debugging;

End Task_Debugging;
---------------------------------------------------------------------------

I've fixed the original problems (first the "tampering", and second a constraint_error) but there's still something strange going on. The discriminants for notifications seem to be being ignored (or rather the latest one being used).

Here's the output:
C:\Programming\Projects\Scheduler>scheduling.exe
Elapsed: 0.000
        Exipration:  0.984
New Length:  2
        Exipration:  1.983
Elapsed: 0.002
        Exipration:  1.982
        Exipration:  1.982
New Length:  3
        Exipration:  2.981
Elapsed: 0.004
        Exipration:  2.980
        Exipration:  2.980
        Exipration:  2.980
[...]
Message: Last.
Deleted items; New Length: 10
Elapsed: 2.047
        Exipration:  7.938
        Exipration:  7.938
        Exipration:  7.938
        Exipration:  7.938
        Exipration:  7.938
        Exipration:  7.938
        Exipration:  7.938
        Exipration:  7.938
        Exipration:  7.938
        Exipration:  7.938
Elapsed: 4.051
        Exipration:  5.933
        Exipration:  5.933
        Exipration:  5.933
        Exipration:  5.933
        Exipration:  5.933
        Exipration:  5.933
        Exipration:  5.933
        Exipration:  5.933
        Exipration:  5.933
        Exipration:  5.933
Elapsed: 6.061
        Exipration:  3.923
        Exipration:  3.923
        Exipration:  3.923
        Exipration:  3.923
        Exipration:  3.923
        Exipration:  3.923
        Exipration:  3.923
        Exipration:  3.923
        Exipration:  3.923
        Exipration:  3.923
Elapsed: 8.086
        Exipration:  1.898
        Exipration:  1.898
        Exipration:  1.898
        Exipration:  1.898
        Exipration:  1.898
        Exipration:  1.898
        Exipration:  1.898
        Exipration:  1.898
        Exipration:  1.898
        Exipration:  1.898
Elapsed:10.106
        Exipration: -0.122
        Exipration: -0.122
        Exipration: -0.122
        Exipration: -0.122
        Exipration: -0.122
        Exipration: -0.122
        Exipration: -0.122
        Exipration: -0.122
        Exipration: -0.122
        Exipration: -0.122
Message: DD 10
Message: DD 9
Message: DD 8
Message: DD 7
Message: DD 6
Message: DD 5
Message: DD 4
Message: DD 3
Message: DD 2
Message: DD 1
Deleted items; New Length: 0
EMPTY.
Termination: NORMAL

As you can see, instead of each element being different they're all tagged as having the same expiration.



^ permalink raw reply	[relevance 2%]

* Re: GNAT (GCC) Profile Guided Compilation
  2012-07-18 10:01  6%                                   ` Georg Bauhaus
@ 2012-07-18 17:36  0%                                     ` Keean Schupke
  0 siblings, 0 replies; 200+ results
From: Keean Schupke @ 2012-07-18 17:36 UTC (permalink / raw)


On Wednesday, 18 July 2012 11:01:11 UTC+1, Georg Bauhaus  wrote:
> On 15.07.12 10:27, Keean Schupke wrote:
> &gt; function F(N : Node, V : Value) return Boolean is begin (
> &gt;     return (N.Enum = Const) or else ((N.Enum = V) = (N.Number = 0));
> &gt; )
> &gt; 
> &gt; B : constant Boolean = F(N1, V) 
> &gt;     and then F(N2, V)
> &gt;     and then F(N3, V)
> &gt;     and then F(N4, V);
> &gt; 
> 
> FWIW, I have two observations after playing with the above function:
> 
> Using different ways of supplying the variables to F and to functions
> like it, two things seemed to have noticeable influence:
> 
> 1) making the Node record limited (good)
> 2) supplying the values, not the record, to F (possibly good)
> 
> The results have varied a lot with everything (CPU, compiler, switches, ...),
> and I haven&#39;t checked the indirections for correctness; in any case,
> plain F (record components) did well.
> 
> with System;
> package News_23.Choice is
> 
>    function F  (N : Node; V : Value) return Boolean;
>    function FA (N : Node; V : Value) return Boolean;
>    function FP1 (p : System.Address; V : Value) return Boolean;
>    function FP2 (p : System.Address; V : Value) return Boolean;
>    function FP3 (p : System.Address; V : Value) return Boolean;
>    function F_3_Args (Enum   : Value;
> 		      Number : Numeric;
> 		      V	     : Value) return Boolean;
> private
>    Const : constant Value := Two;
> end News_23.choice;
> 
> with System.Address_To_Access_Conversions, System.Storage_Elements;
> with Ada.Unchecked_Conversion;
> package body News_23.Choice is
> 
>    use System.Storage_Elements;
>    Enum_Offset : constant := 4 * Storage_Element&#39;Size;
>    Number_Offset : constant := 8 * Storage_Element&#39;Size;
> 
>    function F(N : Node; V : Value) return Boolean is begin
>      return (N.Enum = Const) or else ((N.Enum = V) = (N.Number = 0));
>    end;
> 
>    package Value_P is new System.Address_To_Access_Conversions
>      (Object =&gt; Value);
>    package Numeric_P is new System.Address_To_Access_Conversions
>      (Object =&gt; Numeric);
> 
>    function FA(N : Node; V : Value) return Boolean is
>    begin
>       declare
> --	 Enm : Value_P.Object_Pointer renames Value_P.To_Pointer (N&#39;Address +
> N.Enum&#39;Position);
> --	 Num : Numeric_P.Object_Pointer renames Numeric_P.To_Pointer (N&#39;Address +
> N.Number&#39;Position);
> 	 Enm : Value_P.Object_Pointer renames Value_P.To_Pointer (N&#39;Address +
> Enum_Offset);
> 	 Num : Numeric_P.Object_Pointer renames Numeric_P.To_Pointer (N&#39;Address +
> Number_Offset);
>       begin
> 	 return (Enm.all = Const) or else ((Enm.all = V) = (Num.all = 0));
>       end;
>    end FA;
> 
>    function FP1 (P : System.Address; V : Value) return Boolean is
>       Enm : Value;
>       pragma Import (Ada, Enm);
>       for Enm&#39;Address use P + Enum_Offset;
>       Num : Numeric;
>       pragma Import (Ada, Num);
>       for Num&#39;Address use P + Number_Offset;
>    begin
>       pragma Inspection_Point (P);
>       return (Enm = Const) or else ((Enm = V) = (Num = 0));
>    end FP1;
> 
>    function FP2 (P : System.Address; V : Value) return Boolean is
>       Enm : Value;
>       pragma Import (Ada, Enm);
>       for Enm&#39;Address use To_Address (To_Integer (P) + Enum_Offset);
>       Num : Numeric;
>       pragma Import (Ada, Num);
>       for Num&#39;Address use To_Address (To_Integer (P) + Number_Offset);
>    begin
>       pragma Inspection_Point (P);
>       return (Enm = Const) or else ((Enm = V) = (Num = 0));
>    end FP2;
> 
>    type Adr is mod 2**Standard&#39;Address_Size;
>    function To_N is new Ada.Unchecked_Conversion (System.Address, Adr);
>    function To_Adr is new Ada.Unchecked_Conversion (Adr, System.Address);
> 
>    function FP3 (P : System.Address; V : Value) return Boolean is
>       Enm : Value;
>       pragma Import (Ada, Enm);
>       for Enm&#39;Address use To_Adr (To_N (P) + Enum_Offset);
>       Num : Numeric;
>       pragma Import (Ada, Num);
>       for Num&#39;Address use To_Adr (To_N (P) + Number_Offset);
>    begin
>       pragma Inspection_Point (P);
>       return (Enm = Const) or else ((Enm = V) = (Num = 0));
>    end FP3;
> 
>    function F_3_Args(Enum : Value; Number : Numeric ; V : Value) return
> Boolean is begin
>      return (Enum = Const) or else ((Enum = V) = (Number = 0));
>    end F_3_Args;
> 
> end News_23.Choice;

I think if you use -O3 -gnatn (and pragma Inline(X)) the function will be inlined. Does it still make a difference then?

Cheers,
Keean.



^ permalink raw reply	[relevance 0%]

* Re: GNAT (GCC) Profile Guided Compilation
  @ 2012-07-18 10:01  6%                                   ` Georg Bauhaus
  2012-07-18 17:36  0%                                     ` Keean Schupke
  0 siblings, 1 reply; 200+ results
From: Georg Bauhaus @ 2012-07-18 10:01 UTC (permalink / raw)


On 15.07.12 10:27, Keean Schupke wrote:
> function F(N : Node, V : Value) return Boolean is begin (
>     return (N.Enum = Const) or else ((N.Enum = V) = (N.Number = 0));
> )
> 
> B : constant Boolean = F(N1, V) 
>     and then F(N2, V)
>     and then F(N3, V)
>     and then F(N4, V);
> 

FWIW, I have two observations after playing with the above function:

Using different ways of supplying the variables to F and to functions
like it, two things seemed to have noticeable influence:

1) making the Node record limited (good)
2) supplying the values, not the record, to F (possibly good)

The results have varied a lot with everything (CPU, compiler, switches, ...),
and I haven't checked the indirections for correctness; in any case,
plain F (record components) did well.

with System;
package News_23.Choice is

   function F  (N : Node; V : Value) return Boolean;
   function FA (N : Node; V : Value) return Boolean;
   function FP1 (p : System.Address; V : Value) return Boolean;
   function FP2 (p : System.Address; V : Value) return Boolean;
   function FP3 (p : System.Address; V : Value) return Boolean;
   function F_3_Args (Enum   : Value;
		      Number : Numeric;
		      V	     : Value) return Boolean;
private
   Const : constant Value := Two;
end News_23.choice;

with System.Address_To_Access_Conversions, System.Storage_Elements;
with Ada.Unchecked_Conversion;
package body News_23.Choice is

   use System.Storage_Elements;
   Enum_Offset : constant := 4 * Storage_Element'Size;
   Number_Offset : constant := 8 * Storage_Element'Size;

   function F(N : Node; V : Value) return Boolean is begin
     return (N.Enum = Const) or else ((N.Enum = V) = (N.Number = 0));
   end;

   package Value_P is new System.Address_To_Access_Conversions
     (Object => Value);
   package Numeric_P is new System.Address_To_Access_Conversions
     (Object => Numeric);

   function FA(N : Node; V : Value) return Boolean is
   begin
      declare
--	 Enm : Value_P.Object_Pointer renames Value_P.To_Pointer (N'Address +
N.Enum'Position);
--	 Num : Numeric_P.Object_Pointer renames Numeric_P.To_Pointer (N'Address +
N.Number'Position);
	 Enm : Value_P.Object_Pointer renames Value_P.To_Pointer (N'Address +
Enum_Offset);
	 Num : Numeric_P.Object_Pointer renames Numeric_P.To_Pointer (N'Address +
Number_Offset);
      begin
	 return (Enm.all = Const) or else ((Enm.all = V) = (Num.all = 0));
      end;
   end FA;

   function FP1 (P : System.Address; V : Value) return Boolean is
      Enm : Value;
      pragma Import (Ada, Enm);
      for Enm'Address use P + Enum_Offset;
      Num : Numeric;
      pragma Import (Ada, Num);
      for Num'Address use P + Number_Offset;
   begin
      pragma Inspection_Point (P);
      return (Enm = Const) or else ((Enm = V) = (Num = 0));
   end FP1;

   function FP2 (P : System.Address; V : Value) return Boolean is
      Enm : Value;
      pragma Import (Ada, Enm);
      for Enm'Address use To_Address (To_Integer (P) + Enum_Offset);
      Num : Numeric;
      pragma Import (Ada, Num);
      for Num'Address use To_Address (To_Integer (P) + Number_Offset);
   begin
      pragma Inspection_Point (P);
      return (Enm = Const) or else ((Enm = V) = (Num = 0));
   end FP2;

   type Adr is mod 2**Standard'Address_Size;
   function To_N is new Ada.Unchecked_Conversion (System.Address, Adr);
   function To_Adr is new Ada.Unchecked_Conversion (Adr, System.Address);

   function FP3 (P : System.Address; V : Value) return Boolean is
      Enm : Value;
      pragma Import (Ada, Enm);
      for Enm'Address use To_Adr (To_N (P) + Enum_Offset);
      Num : Numeric;
      pragma Import (Ada, Num);
      for Num'Address use To_Adr (To_N (P) + Number_Offset);
   begin
      pragma Inspection_Point (P);
      return (Enm = Const) or else ((Enm = V) = (Num = 0));
   end FP3;

   function F_3_Args(Enum : Value; Number : Numeric ; V : Value) return
Boolean is begin
     return (Enum = Const) or else ((Enum = V) = (Number = 0));
   end F_3_Args;

end News_23.Choice;





^ permalink raw reply	[relevance 6%]

* Re: Efficient Sequential Access to Arrays
  @ 2012-07-15 21:44  5%     ` Georg Bauhaus
  0 siblings, 0 replies; 200+ results
From: Georg Bauhaus @ 2012-07-15 21:44 UTC (permalink / raw)


On 15.07.12 22:03, Keean Schupke wrote:
> On Sunday, 15 July 2012 20:48:35 UTC+1, Dmitry A. Kazakov  wrote:
>> On Sun, 15 Jul 2012 11:40:08 -0700 (PDT), Keean Schupke wrote:
>>
>> &gt; However in order to achieve this performance I needed to rework the arrays
>> &gt; as the use of Indexes was too slow.
>>
>> You have to measure it in order to know. Write two variants and compare
>> their performance.
>
> Have done, the difference is about 10k simulations per second.
>
>>
>> &gt; An example of this is lets say we are
>> &gt; accessing element 5 from array A &quot;A(5)&quot; this requires a multiplication to
>> &gt; access (base_address + index * record_size).
>>
>> It does not, because 5 is constant.
>
> Obviously the index is not actually a constant but the result of selecting a random element in the list. The multiplication is necessary for finding this first element, but the operations on relative elements (+/-1, +/-2 etc) can use addition with a pointer, not so with an index.

There is address arithmetic in System.*. For the simple case of
constant distances, something like the following might have some
hints. Or it might if redone after thinking. procedure Grab has
the multiplication for offsets of components of a record type
object in an array.

The point is that one may express offsets by referring
to type attributes that follow from representation clauses
and then convert between addresses and pointers.

with Ada.Numerics.Float_Random;    use  Ada.Numerics.Float_Random;
with System.Address_To_Access_Conversions, System.Storage_Elements;
procedure Iter_Arrays (Size : Natural) is

    Storage_Elements : constant := 1;

    type Index is mod 2**32;
    type Data is digits 6;
    for Data'Size use 32;

    G : Generator;

    type Things is record
       One: Data := Data (Random (G));
       Two: Data := Data (Random (G));
    end record;

    for Things use record
       One at 0 * Storage_Elements range 0 .. Data'Size - 1;
       Two at 4 * Storage_Elements range 0 .. Data'Size - 1;
    end record;
    pragma Assert (Things'Size = 64);

    type List is array (Index range <>) of Things;
    for List'Alignment use 4 * Storage_Elements;
    for List'Component_Size use 64;


--  using array indexing

    procedure Bumble (A : in out List; Step : Index) is
    begin
       for K in A'First + Step .. A'Last - Step loop
          declare
             Diff_Backward : constant Data := A (K).One - A (K - Step).Two;
             Diff_Forward : constant Data := A (K).Two - A (K + Step).One;
          begin
             if (abs Diff_Backward) < (abs Diff_Forward) then
                A (K).One := A (K - Step).One;
             else
                A (K).Two := A (K + Step).Two;
             end if;
          end;
       end loop;
    end Bumble;


--  using relative addresses

    package Indirection is new System.Address_To_Access_Conversions
      (Object => Data);
    subtype Data_Pointer is Indirection.Object_Pointer;


    procedure Grab  (A : in out List; Step : Index) is
       -- [A] = [one][two][one][two]...[one][two]
       use System.Storage_Elements, Indirection;
       Offset_Backward : constant Storage_Offset :=
         Storage_Offset (0 + Step * 8 + 4);
       Offset_Forward : constant Storage_Offset :=
         Storage_Offset (0 - Step * 8 + 0);
    begin
       for K in A'First + Step .. A'Last - Step loop
          declare
             Back : constant Data_Pointer :=
               To_Pointer (A (K).One'Address + Offset_Backward);
             Ahead : constant Data_Pointer :=
               To_Pointer (A (K).Two'Address + Offset_Backward);
             Diff_Backward : constant Data := A (K).One - Back.all;
             Diff_Forward : constant Data := A (K).One - Ahead.all;
          begin
             if (abs Diff_Backward) < (abs Diff_Forward) then
                A (K).One := A (K - Step).One;
             else
                A (K).Two := A (K + Step).Two;
             end if;
          end;
       end loop;
    end Grab;

    Test_Data : List (0 .. Index(Size));

begin
    Bumble (Test_Data, 2);
    Grab (Test_Data, 3);
end Iter_Arrays;



^ permalink raw reply	[relevance 5%]

* Re: GNAT (GCC) Profile Guided Compilation
  2012-06-29 12:26  0%       ` stefan-lucks
@ 2012-06-29 12:51  0%         ` Keean Schupke
  0 siblings, 0 replies; 200+ results
From: Keean Schupke @ 2012-06-29 12:51 UTC (permalink / raw)
  Cc: stefan-lucks

On Friday, 29 June 2012 13:26:23 UTC+1, (unknown)  wrote:
> On Fri, 29 Jun 2012, Keean Schupke wrote:
> 
> > On Friday, 29 June 2012 11:01:30 UTC+1, Keean Schupke  wrote:
> 
> > > Maintaining the address of the current cell is faster than using 
> > > indexed addressing (mainly because of the extra parameter that needs 
> > > to be passed around increasing the pressure on register allocation).
> 
> I guess you did some benchmarking, regarding that issue?
> 
> > > I would be interested to understand how an algorithm can be 
> > > implemented in a more Ada way?
> 
> Faster or slower, you are extensively using access types (Element_Access 
> and Set_Access). This is something Ada programmers usually try to avoid, 
> except when there is an urgent need for some dynamic memory management 
> (e.g., implementing one's own Container library). 
> 
> >     generic
> >         type Element_Type is limited private;
> >         type Element_Access is not null access all Element_Type;
> >         type Set_Index is range <>;
> >     package Eager_Disjointsets is
> >         type Set_Type is limited private;
> >         type Set_Access is not null access all Set_Type;
> 
> What, exactly, do you use Element_Access for? And why, exactly, do you 
> bother to define Set_Access?

I use Element_Access because the element is going to be a record that needs to be updated in place. To copy the record is too slow. If you look at the get method we want to do:

Get(Set, Index).Something := xxx

The record stored in each Node of the set datatype will be limited, so you cannot return it from a function, you can only return an access to it.

Why Set_Access, because in order to avoid an access-level problem you cannot define the element-access at a different block level from the set-access, so in order to safely return an element-access we must pass a set-access in.

> 
> >         function Find(
> >             Set : in Set_Access;
> >             Index : in Set_Index
> >         ) return Set_Index;
> >         pragma Inline_Always(Find);
>  
> Why don't you just write the following? (Same for your other operations.)
> 
> 	function find
> 	  (Set   : in Set_Type;
> 	   Index : in Set_Index) return Set_Index;

Because of the above requirements of the Get function, it is better to make all the methods take a Set_Access for consistency. The we only need to pass a Set_Access around, never a set, forcing pass-by-reference and not copying.

> 
> [...]
> 
> >     private
> >         type Node_Type is limited record
> >             Canonical : Set_Index;
> >             Successor : Set_Index;
> >             Size : Natural;
> >             Value : aliased Element_Type;
> >         end record;
> >         type Set_Type is array (Set_Index) of Node_Type;
> >     end Eager_Disjointsets;
> 
> Why, exactly, do you make Value aliased? Is this related to your "faster 
> than indexed addressing" point above?

This is because we need to return an access to the value from 'Get' so that it can be updated in place. Remember 'Element_Type' will be limited.

> 
> This may be hard for the compiler to properly optimize: An aliased 
> component Element_Type in a record ... and then there is an array of such 
> records, and all is inside a generic package. 

Actually the compiler does pretty well. 40k per second it matches the C++ version. It is only when trying to use profile-guided optimisation that Ada is not improving.

> 
> If you really need Value to be aliased (do you?), then you can try out 
> rewriting Set_Type:
> 
>   type Set_Index_Array is array(Set_Index) of Set_Index;
>   type Size_Array      is array(Set_Index) of Natural;
>   type Value_Array     is array(Set_Index) of aliased Element_Type;
> 
>   type Set_Type is record
>     Canonical, Successor: Set_Index_Array;
>     Size:                 Size_Array;
>     Value:                Value_Array;
>   end record;

I dont think this will be faster as we now have to compute the array index offset for accessing each property. Happy to benchmark for you...

> 
> I have no idea if the above modification helps to speed up the 
> computation, or not. It may backfire, I don't know. 
> 
> >     package body Eager_Disjointsets is
> >         function Find(
> >             Set : in Set_Access;
> >             Index : in Set_Index
> >         ) return Set_Index is begin
> >             return Set(Index).Canonical;
> >         end Find;
> 
> Now, here you would have to write "return Set.Canonical(Index);"
> 
> >     -- (C)2011 Keean Schupke, all rights reserved.
> >     generic
> >         Size : Int;
> >         type Element_Type is limited private;
> >         type Element_Access is not null access all Element_Type;
> >     package Eager_Disjointsets is
> >         type Set_Type is limited private;
> >         type Set_Access is not null access all Set_Type;
> >         type Node_Type is limited private;
> >         type Cursor is access all Node_Type;
> 
> Is Int another name for Integer?

Sorry, its a type name for the local best performing integer type, which is Integer_64 in my case. 

> 
> I understand that for performance reason you introduced Cursor as access 
> all Node_Type and later Set_Array as aliased array of Node_Type.
> 
> But again, what do you need Element_Access and Set_Access for?

See above.

> 
> >         package Node_Address is new 
> >         System.Address_To_Access_Conversions(Node_Type);
> 
> Probably, the compiler finds that out by itself -- but you may want to 
> make it explicit that Node_Size doesn't change:
> 
> >         Node_Size : constant Storage_Offset := Node_Type'Object_Size
> >             / System.Storage_Elements.Storage_Element'Size;

Yes, thats a good spot - I missed that.

> 
> Also, if Node_Size isn't a power of 2, it may be difficult for the 
> compiler to decide on the alignment of objects of type Node_Type -- with 
> possible effects on caching. On one hand, it may be good to pack the 
> objects closely together, to make as many fit into a single cache line as 
> possible. On the other hand, it is bad if a part of a certain node is in 
> one cache line, another part in another cache line.

Packing is slower, the whole data set is small enough to fit in the cache (<5k) so alignment wins over packing.

> 
> >         function Find(
> >             Node : in Cursor
> >         ) return Cursor is begin
> >             return Cursor(Node.Canonical);
> >         end Find;
> 
> Not related to performance, but why don't you just write 
> "return Node.Canonical;" as Node.Canonical is of type Cursor, anyway?

Again, good spot, Canonical was not always a Cursor, so I missed it.

> 
> 
> -- 
> ---- Stefan.Lucks (at) uni-weimar.de, University of Weimar, Germany  ----
>     <http://www.uni-weimar.de/cms/medien/mediensicherheit/home.html>
> ------  I  love  the  taste  of  Cryptanalysis  in  the  morning!  ------


Cheers,
Keean.



^ permalink raw reply	[relevance 0%]

* Re: GNAT (GCC) Profile Guided Compilation
  2012-06-29 10:24  3%     ` Keean Schupke
@ 2012-06-29 12:26  0%       ` stefan-lucks
  2012-06-29 12:51  0%         ` Keean Schupke
  0 siblings, 1 reply; 200+ results
From: stefan-lucks @ 2012-06-29 12:26 UTC (permalink / raw)


On Fri, 29 Jun 2012, Keean Schupke wrote:

> On Friday, 29 June 2012 11:01:30 UTC+1, Keean Schupke  wrote:

> > Maintaining the address of the current cell is faster than using 
> > indexed addressing (mainly because of the extra parameter that needs 
> > to be passed around increasing the pressure on register allocation).

I guess you did some benchmarking, regarding that issue?

> > I would be interested to understand how an algorithm can be 
> > implemented in a more Ada way?

Faster or slower, you are extensively using access types (Element_Access 
and Set_Access). This is something Ada programmers usually try to avoid, 
except when there is an urgent need for some dynamic memory management 
(e.g., implementing one's own Container library). 

>     generic
>         type Element_Type is limited private;
>         type Element_Access is not null access all Element_Type;
>         type Set_Index is range <>;
>     package Eager_Disjointsets is
>         type Set_Type is limited private;
>         type Set_Access is not null access all Set_Type;

What, exactly, do you use Element_Access for? And why, exactly, do you 
bother to define Set_Access?

>         function Find(
>             Set : in Set_Access;
>             Index : in Set_Index
>         ) return Set_Index;
>         pragma Inline_Always(Find);
 
Why don't you just write the following? (Same for your other operations.)

	function find
	  (Set   : in Set_Type;
	   Index : in Set_Index) return Set_Index;

[...]

>     private
>         type Node_Type is limited record
>             Canonical : Set_Index;
>             Successor : Set_Index;
>             Size : Natural;
>             Value : aliased Element_Type;
>         end record;
>         type Set_Type is array (Set_Index) of Node_Type;
>     end Eager_Disjointsets;

Why, exactly, do you make Value aliased? Is this related to your "faster 
than indexed addressing" point above?

This may be hard for the compiler to properly optimize: An aliased 
component Element_Type in a record ... and then there is an array of such 
records, and all is inside a generic package. 

If you really need Value to be aliased (do you?), then you can try out 
rewriting Set_Type:

  type Set_Index_Array is array(Set_Index) of Set_Index;
  type Size_Array      is array(Set_Index) of Natural;
  type Value_Array     is array(Set_Index) of aliased Element_Type;

  type Set_Type is record
    Canonical, Successor: Set_Index_Array;
    Size:                 Size_Array;
    Value:                Value_Array;
  end record;

I have no idea if the above modification helps to speed up the 
computation, or not. It may backfire, I don't know. 

>     package body Eager_Disjointsets is
>         function Find(
>             Set : in Set_Access;
>             Index : in Set_Index
>         ) return Set_Index is begin
>             return Set(Index).Canonical;
>         end Find;

Now, here you would have to write "return Set.Canonical(Index);"

>     -- (C)2011 Keean Schupke, all rights reserved.
>     generic
>         Size : Int;
>         type Element_Type is limited private;
>         type Element_Access is not null access all Element_Type;
>     package Eager_Disjointsets is
>         type Set_Type is limited private;
>         type Set_Access is not null access all Set_Type;
>         type Node_Type is limited private;
>         type Cursor is access all Node_Type;

Is Int another name for Integer?

I understand that for performance reason you introduced Cursor as access 
all Node_Type and later Set_Array as aliased array of Node_Type.

But again, what do you need Element_Access and Set_Access for?

>         package Node_Address is new 
>         System.Address_To_Access_Conversions(Node_Type);

Probably, the compiler finds that out by itself -- but you may want to 
make it explicit that Node_Size doesn't change:

>         Node_Size : constant Storage_Offset := Node_Type'Object_Size
>             / System.Storage_Elements.Storage_Element'Size;

Also, if Node_Size isn't a power of 2, it may be difficult for the 
compiler to decide on the alignment of objects of type Node_Type -- with 
possible effects on caching. On one hand, it may be good to pack the 
objects closely together, to make as many fit into a single cache line as 
possible. On the other hand, it is bad if a part of a certain node is in 
one cache line, another part in another cache line.

>         function Find(
>             Node : in Cursor
>         ) return Cursor is begin
>             return Cursor(Node.Canonical);
>         end Find;

Not related to performance, but why don't you just write 
"return Node.Canonical;" as Node.Canonical is of type Cursor, anyway?


-- 
---- Stefan.Lucks (at) uni-weimar.de, University of Weimar, Germany  ----
    <http://www.uni-weimar.de/cms/medien/mediensicherheit/home.html>
------  I  love  the  taste  of  Cryptanalysis  in  the  morning!  ------




^ permalink raw reply	[relevance 0%]

* Re: GNAT (GCC) Profile Guided Compilation
  @ 2012-06-29 10:24  3%     ` Keean Schupke
  2012-06-29 12:26  0%       ` stefan-lucks
  0 siblings, 1 reply; 200+ results
From: Keean Schupke @ 2012-06-29 10:24 UTC (permalink / raw)
  Cc: mailbox

On Friday, 29 June 2012 11:01:30 UTC+1, Keean Schupke  wrote:
> On Friday, 29 June 2012 10:34:19 UTC+1, Dmitry A. Kazakov  wrote:
> > On Fri, 29 Jun 2012 02:17:19 -0700 (PDT), Keean Schupke wrote:
> > 
> > > Anyone have any ideas why profile guided compilation performs so poorly
> > > with Ada compared to C++?
> > 
> > Probably because you programmed it using low level C-ish stuff like
> > addresses instead of accessing data directly. In general, if you write a C
> > program in Ada (or any other language), you cannot expect it do better than
> > in C. To beat C, the precondition is to design it in Ada way.
> > 
> > -- 
> > Regards,
> > Dmitry A. Kazakov
> > http://www.dmitry-kazakov.de
> 
> I don't think you are right here, but I would be happy to be proved wrong. 
> 
> In general I find the choice of algorithm dominates performance. In this case most of the performance is dominated by a disjoint-set (union-find) algorithm operating on an array of data. The data nominally represents a 2D space (although I am using a 1D array to avoid the cost of multiplication on every access).
> 
> Most operations access the neighbouring cells, hence require a +/- one cell, or +/- one row operations.
> 
> Maintaining the address of the current cell is faster than using indexed addressing (mainly because of the extra parameter that needs to be passed around increasing the pressure on register allocation).
> 
> I would be interested to understand how an algorithm can be implemented in a more Ada way?
> 
> 
> Cheers,
> Keean.

To facilitate the discussion I will post the core packages from the implementation. First the slower version using array indexing (this is the 32k simulations per second version). As my application is lookup dominated, this algorithm (the eager disjoint set algorithm) is faster than the WQUPC (Weighted Quick Union with Path Compression) algorithm for my application.



    -- (C)2011 Keean Schupke, all rights reserved.
    generic
        type Element_Type is limited private;
        type Element_Access is not null access all Element_Type;
        type Set_Index is range <>;
    package Eager_Disjointsets is
        type Set_Type is limited private;
        type Set_Access is not null access all Set_Type;
        function Find(
            Set : in Set_Access;
            Index : in Set_Index
        ) return Set_Index;
        pragma Inline_Always(Find);

        procedure Makeset(
            Set : in Set_Access;
            Index : in Set_Index
        );
        pragma Inline_Always(Makeset);

        procedure Link(
            Set : in Set_Access;
            Left, Right : in out Set_Index
        );
        pragma Inline_Always(Link);

        function Get(
            Set : in Set_Access;
            Index : in Set_Index
        ) return Element_Access;
        pragma Inline_Always(Get);

        function Next(
            Set : in Set_Access;
            Index : in Set_Index
        ) return Set_Index;
        pragma Inline_Always(Next);

        procedure Set_Next(
            Set : in Set_Access;
            Index : in Set_Index;
            Next : in Set_Index
        );
        pragma Inline_Always(Set_Next);

    private
        type Node_Type is limited record
            Canonical : Set_Index;
            Successor : Set_Index;
            Size : Natural;
            Value : aliased Element_Type;
        end record;
        type Set_Type is array (Set_Index) of Node_Type;
    end Eager_Disjointsets;

    package body Eager_Disjointsets is
        procedure Makeset(
            Set : in Set_Access;
            Index : in Set_Index
        ) is begin
            Set(Index).Canonical := Index;
            Set(Index).Size := 1;
        end Makeset;

        function Find(
            Set : in Set_Access;
            Index : in Set_Index
        ) return Set_Index is begin
            return Set(Index).Canonical;
        end Find;

        procedure Swap_Indexes is new Swap(Set_Index);

        procedure Link(
            Set : in Set_Access;
            Left, Right : in out Set_Index) is
        begin
            if Set(Left).Size <= Set(Right).Size then
                Swap_Indexes(Left, Right);
            end if;

            declare
                Index : Set_Index := Right;
            begin
                Link_Loop : loop
                    Set(Index).Canonical := Left;
                    Index := Set(Index).Successor;
                    exit Link_Loop when Index = Right;
                end loop Link_Loop;
            end;

            Add(Set(Left).Size, Set(Right).Size);

            Swap_Indexes(Set(Left).Successor, Set(Right).Successor);
        end Link;

        function Get(
            Set : in Set_Access;
            Index : in Set_Index
        ) return Element_Access is begin
            return Set(Index).Value'Access;
        end Get;

        function Next(
            Set : in Set_Access;
            Index : in Set_Index
        ) return Set_Index is begin
            return Set(Index).Successor;
        end Next;

        procedure Set_Next(
            Set : in Set_Access;
            Index : in Set_Index;
            Next : in Set_Index
        ) is begin
            Set(Index).Successor := Next;
        end Set_Next;
    end Eager_Disjointsets;



And this is the faster 40k simulations per second version:



    -- (C)2011 Keean Schupke, all rights reserved.
    generic
        Size : Int;
        type Element_Type is limited private;
        type Element_Access is not null access all Element_Type;
    package Eager_Disjointsets is
        type Set_Type is limited private;
        type Set_Access is not null access all Set_Type;
        type Node_Type is limited private;
        type Cursor is access all Node_Type;

        function Find(Node : in Cursor) return Cursor;
        pragma Inline_Always(Find);
        procedure Makeset(Node : in Cursor);
        pragma Inline_Always(Makeset);
        procedure Link(Left, Right : in out Cursor);
        pragma Inline_Always(Link);

        function Succ(Node : in Cursor) return Cursor;
        pragma Inline_Always(Succ);
        procedure Set_Succ(Node, Succ : in Cursor);
        pragma Inline_Always(Set_Succ);

        function First(Set : in Set_Access) return Cursor;
        pragma Inline_Always(First);
        function Element(Node : in Cursor) return Element_Access;
        pragma Inline_Always(Element);
        function Index(Set : in Set_Access; Node : in Cursor) return Int;
        pragma Inline_Always(Index);
        procedure Next(Node : in out Cursor);
        pragma Inline_Always(Next);

        function Step return Int;
        pragma Inline_Always(Step);
        function "+" (Left : in Cursor; Right : in Int) return Cursor;
        pragma Inline_Always("+");
        function "-" (Left : in Cursor; Right : in Int) return Cursor;
        pragma Inline_Always("-");
    private
        type Node_Type is limited record
            Canonical : Cursor;
            Successor : Cursor;
            Size : Int;
            Value : aliased Element_Type;
        end record;
        type Set_Type is array (0 .. Size - 1) of aliased Node_Type;

        package Node_Address is new System.Address_To_Access_Conversions(Node_Type);

        Node_Size : Storage_Offset := Node_Type'Object_Size
            / System.Storage_Elements.Storage_Element'Size;
    end Eager_Disjointsets;

    package body Eager_Disjointsets is
        function To_Cursor(A : System.Address) return Cursor is
        begin
            return Cursor(Node_Address.To_Pointer(A));
        end To_Cursor;
        pragma Inline_Always(To_Cursor);

        function To_Address(C : Cursor) return System.Address is
        begin
            return Node_Address.To_Address(Node_Address.Object_Pointer(C));
        end To_Address;
        pragma Inline_Always(To_Address);

        procedure Makeset(
            Node : in Cursor
        ) is begin
            Node.Canonical := Node;
            Node.Size := 1;
        end Makeset;

        function Find(
            Node : in Cursor
        ) return Cursor is begin
            return Cursor(Node.Canonical);
        end Find;

        procedure Swap_Cursors is new Swap(Cursor);

        procedure Link(
            Left, Right : in out Cursor) is
        begin
            if Left.Size <= Right.Size then
                Swap_Cursors(Cursor(Left), Cursor(Right));
            end if;

            declare
                Node : Cursor := Right;
            begin
                Link_Loop : loop
                    Node.Canonical := Left;
                    Node := Cursor(Node.Successor);
                    exit Link_Loop when Node = Right;
                end loop Link_Loop;
            end;

            Add(Left.Size, Right.Size);
            Swap_Cursors(Cursor(Left.Successor), Cursor(Right.Successor));
        end Link;

        function Succ(
            Node : in Cursor
        ) return Cursor is begin
            return Cursor(Node.Successor);
        end Succ;
        procedure Set_Succ(
            Node, Succ : in Cursor
        ) is begin
            Node.Successor := Succ;
        end Set_Succ;

        function First(
            Set : in Set_Access
        ) return Cursor is begin
            return Set(Set_Type'First)'Access;
        end First;

        function Element(
            Node : in Cursor
        ) return Element_Access is begin
            return Node.Value'Access;
        end Element;

        function Index(
            Set : in Set_Access;
            Node : in Cursor
        ) return Int is begin
            return Int((To_Address(Node) - To_Address(First(Set))) / Node_Size);
        end Index;

        procedure Next(
            Node : in out Cursor
        ) is begin
            Node := To_Cursor(To_Address(Node) + Node_Size);
        end Next;

        function Step return Int is
        begin
            return Int(Node_Size);
        end Step;

        function "+" (Left : in Cursor; Right : in Int) return Cursor is
        begin
            return To_Cursor(To_Address(Left) + Storage_Offset(Right));
        end "+";

        function "-" (Left : in Cursor; Right : in Int) return Cursor is
        begin
            return To_Cursor(To_Address(Left) - Storage_Offset(Right));
        end "-";
    end Eager_Disjointsets;



Would appreciate any advice on how this could be implemented in a more Ada friendly way, or any general performance tips.



Cheers,
Keean.



^ permalink raw reply	[relevance 3%]

* Re: Dispatching callback handed over to C
  @ 2012-04-04  7:26  5%         ` Georg Bauhaus
  0 siblings, 0 replies; 200+ results
From: Georg Bauhaus @ 2012-04-04  7:26 UTC (permalink / raw)


On 03.04.12 22:20, Randy Brukardt wrote:

> The whole idea of the void pointer is so anti-Ada that it is best to get rid
> of it as early as you can. (There is no such thing as "untyped data" in Ada,
> and, as Dmitry likes to point out, not in real life, either. There is only
> data for which the type is not known at compile-time, and that sort of data
> is a problem - best to avoid it.)

Just to mention that there is more to (void*) than "untyped data"!
The C standard guarantees certain properties of objects when
the programmer applies C's type conversion rules in many
directions. (void*) is not a demolition operation.

There is also a ptrdiff_t both in C and in Ada, the ptrdiff_t rules
again implying anything but untyped data. And the definitions of
either language's type system seem to join here and there.

Unchecked_Union works for discriminated records, but it does not
extend to the union of tag-discriminated records of some R'Class.

I see that Maciej's solution has two hooks in it that I would hope are
hooks for addressing the concerns. They both have body visibility only.
One declares subtype Void_Ptr is System.Address, so
System.Address can be replaced with something that better matches O-O
arguments of type (void*). And the solution has a pointer translation
mechanism involving an instance of System.Address_To_Access_Conversions.

What else can we do to enable O-O mechanics in existing C libraries?

(If there isn't anything Ada can do, then I-can-emulate-all-your-language
in my not-that-many-CVE-generating C programs, so why don't you just make
your great Ada language work with today's libraries after only 30 years...
;-)






^ permalink raw reply	[relevance 5%]

* Re: Memory Access
  2011-11-08 17:46  5%           ` awdorrin
@ 2011-11-08 20:11  4%             ` Adam Beneschan
  0 siblings, 0 replies; 200+ results
From: Adam Beneschan @ 2011-11-08 20:11 UTC (permalink / raw)


On Nov 8, 9:46 am, awdorrin <awdor...@gmail.com> wrote:
>
> Now I just have to try to understand what is actually going on with
> those commands.
>
> I'm assuming that the subtype is setting the bounds on the array. so
> that the Dev_Table_Ptr_Type is now able to see the elements.

Something like that.  The subtype declaration says that every object
of that subtype has those bounds.  This also means that for any object
X of type Dev_Table_Ptr_Type, X.all has those bounds too.  The reason
that's important is because the bounds don't have to be stored
somewhere else.  If you have an access-to-an-unconstrained array, then
for any object X with that access type, the bounds have to be stored
somewhere along with X.  The problem is that it's left up to the
implementation just how to store those bounds.  It looks like AdaMulti
makes X a three-word object containing a data address, the lower
bound, and the upper bound; while GNAT stores them differently.


> The Dev_Table_Pointer.To_Pointer is mapping the address to an access
> type.
> I'm not quite sure I understand why the package definition for
> Dev_Table_Pointer is needed - and why
> System.Address_To_Access_Conversions cannot be used directly... i'm
> guessing its due to Ada type checking?

System.Address_To_Access_Conversions is a generic package.  You can't
use a generic package directly; you have to instantiate it.  In this
case, you have to instantiate it with a type.  And yes, I think that
this needs to be a generic because of type checking; Ada doesn't have
the equivalent of a (void *) that you can typecast willy-nilly between
other pointer types and screw yourself up royally.

                        -- Adam



^ permalink raw reply	[relevance 4%]

* Re: Memory Access
  2011-11-08 16:00  5%         ` Adam Beneschan
@ 2011-11-08 17:46  5%           ` awdorrin
  2011-11-08 20:11  4%             ` Adam Beneschan
  0 siblings, 1 reply; 200+ results
From: awdorrin @ 2011-11-08 17:46 UTC (permalink / raw)


On Nov 8, 11:00 am, Adam Beneschan <a...@irvine.com> wrote:
>
> You're saying that Dev_Table is a global access to an unconstrained
> array, and it sounds to me like you're trying to get Dev_Table to
> point to some arbitrary address that isn't known until runtime.
> Unfortunately, I don't think there's a portable way to do that in Ada
> (because the implementation of unconstrained arrays differs between
> implementations).  In fact, there may not be a good way to do it at
> all in GNAT, even non-portably.
>
> A possibility is to make Dev_Table an access to a *constrained*
> array.  If Num_Devs_Cnst is a constant that is known at compile time,
> you could declare
>
>   subtype Constrained_Dev_Table is Dev_Table_Type (1 ..
> Num_Devs_Cnst);
>   type Dev_Table_Ptr_Type is access all Constrained_Dev_Table;
>
> and now there are a couple ways to make Dev_Table_Ptr_Type point to
> what you want.  Here's one, based on an example I gave earlier:
>
>    with System.Address_To_Access_Conversions;
>
> then declare the following **globally** (not inside a subprogram):
>
>    package Dev_Table_Pointer is new
>          System.Address_To_Access_Conversions
> (Constrained_Dev_Table);
>
> and now, to make Dev_Table point to the data at address Dev_Data_Obj:
>
>    Dev_Table := Dev_Table_Ptr_Type (Dev_Table_Pointer.To_Pointer
> (Dev_Data_Obj));
>
> If Num_Devs_Cnst isn't known at compile time, you could still declare
> a constrained array type:
>
>   subtype Constrained_Dev_Table is Dev_Table_Type (1 .. Integer'Last);
>
> and do the same as above.  But then you have to do extra work to make
> sure that you don't later access a Dev_Table element outside the range
> 1 .. Num_Devs_Cnst.  One way is that whenever you want to work with
> Dev_Table:
>
>   declare
>      Actual_Dev_Table : Dev_Table_Type renames Dev_Table (1 ..
> Num_Devs_Cnst);
>         -- or Dev_Table.all (1 .. Num_Devs_Cnst), which means the same
> thing
>   begin
>      --
>      Something := Actual_Dev_Table (NNN).Something;
>         -- will raise Constraint_Error if NNN is out of range 1 ..
> Num_Devs_Cnst
>   end;
>
> Hope this helps.
>
>                         -- Adam


Adam, Thanks - I tried your suggestion and it looks like it may be
working. At least the code is no longer SegFaulting ;)

Now I just have to try to understand what is actually going on with
those commands.

I'm assuming that the subtype is setting the bounds on the array. so
that the Dev_Table_Ptr_Type is now able to see the elements.
The Dev_Table_Pointer.To_Pointer is mapping the address to an access
type.
I'm not quite sure I understand why the package definition for
Dev_Table_Pointer is needed - and why
System.Address_To_Access_Conversions cannot be used directly... i'm
guessing its due to Ada type checking?

Thanks!



^ permalink raw reply	[relevance 5%]

* Re: Memory Access
  @ 2011-11-08 16:00  5%         ` Adam Beneschan
  2011-11-08 17:46  5%           ` awdorrin
  0 siblings, 1 reply; 200+ results
From: Adam Beneschan @ 2011-11-08 16:00 UTC (permalink / raw)


On Nov 8, 4:22 am, awdorrin <awdor...@gmail.com> wrote:
> Something like:
>
> declare
>   tempDevTable : Dev_Table_Ptr_Type := new Dev_Table_Type( 1 ..
> Num_Devs_Cnst );
>   for tempDevTable'Address use Dev_Data_Obj;
> begin
>   Dev_Table := tempDevTable;
> end
>
> I'm thinking this would not work - too used to C pointers I suppose
> where it doesn't matter. ;)

You're right: this would *not* work.

Here's what the above code would do.  tempDevTable is a pointer
object, which may be one word or three words (or something else)
depending on the implementation.  This pointer *object* would be
located at Dev_Data_Obj---not the pointed-to data.  The "new"
operation causes the program to allocate memory from a storage pool.
The memory it allocates will be enough to hold Num_Devs_Cnst objects
of type Config_Type.  The point here is that the "new" always means to
allocate memory from a storage pool; you can't use an 'Address clause
to change the meaning of "new" to something else, which is what I
think you were trying to do.

You're saying that Dev_Table is a global access to an unconstrained
array, and it sounds to me like you're trying to get Dev_Table to
point to some arbitrary address that isn't known until runtime.
Unfortunately, I don't think there's a portable way to do that in Ada
(because the implementation of unconstrained arrays differs between
implementations).  In fact, there may not be a good way to do it at
all in GNAT, even non-portably.

A possibility is to make Dev_Table an access to a *constrained*
array.  If Num_Devs_Cnst is a constant that is known at compile time,
you could declare

  subtype Constrained_Dev_Table is Dev_Table_Type (1 ..
Num_Devs_Cnst);
  type Dev_Table_Ptr_Type is access all Constrained_Dev_Table;

and now there are a couple ways to make Dev_Table_Ptr_Type point to
what you want.  Here's one, based on an example I gave earlier:

   with System.Address_To_Access_Conversions;

then declare the following **globally** (not inside a subprogram):

   package Dev_Table_Pointer is new
         System.Address_To_Access_Conversions
(Constrained_Dev_Table);

and now, to make Dev_Table point to the data at address Dev_Data_Obj:

   Dev_Table := Dev_Table_Ptr_Type (Dev_Table_Pointer.To_Pointer
(Dev_Data_Obj));

If Num_Devs_Cnst isn't known at compile time, you could still declare
a constrained array type:

  subtype Constrained_Dev_Table is Dev_Table_Type (1 .. Integer'Last);

and do the same as above.  But then you have to do extra work to make
sure that you don't later access a Dev_Table element outside the range
1 .. Num_Devs_Cnst.  One way is that whenever you want to work with
Dev_Table:

  declare
     Actual_Dev_Table : Dev_Table_Type renames Dev_Table (1 ..
Num_Devs_Cnst);
        -- or Dev_Table.all (1 .. Num_Devs_Cnst), which means the same
thing
  begin
     --
     Something := Actual_Dev_Table (NNN).Something;
        -- will raise Constraint_Error if NNN is out of range 1 ..
Num_Devs_Cnst
  end;

Hope this helps.

                        -- Adam




^ permalink raw reply	[relevance 5%]

* Re: Memory Access
  @ 2011-11-07 22:42  6%   ` Adam Beneschan
    1 sibling, 0 replies; 200+ results
From: Adam Beneschan @ 2011-11-07 22:42 UTC (permalink / raw)


On Nov 7, 2:21 pm, Adam Beneschan <a...@irvine.com> wrote:
>
> If you known the address of the array data, then something like this
> will work even if you don't know the address until runtime:
>
>     Data_Address : System.Address;
>     ...
> begin
>     -- do some stuff that sets Data_Address to the address.  Or you
>     -- could make
>     -- Data_Address be a parameter to a subroutine, or something
>     -- Then:
>
>     declare
>        Dev_Table : Dev_Table_Type (1 .. Num_Devs_Cnst);
>        for Dev_Table'Address use Data_Address;
>     begin
>        -- and you can use Dev_Table in here
>     end;
>
> This will work whether Num_Devs_Cnst is known at compile time or not.
> (The _Cnst makes it look like it's a constant that's known at compile
> time.  But it doesn't need to be.)

An alternative, if you don't want to use an Address clause:

with System.Address_To_Access_Conversions;

...
   Data_Address : System.Address;
begin
   -- set Data_Address to something as above
   declare
      subtype Constrained_Dev_Table is Dev_Table_Type (1 ..
Num_Devs_Cnst);
      package Dev_Table_Pointer is new
         System.Address_To_Access_Conversions (Constrained_Dev_Table);
      Dev_Table : Dev_Table_Pointer.Object_Pointer :=
         Dev_Table_Pointer.To_Pointer (Data_Address);
   begin
      ...
   end;

Dev_Table is now declared as an access (pointer) to a constrained
array subtype, rather than an array, but you should still be able to
use it in the same way.  This method still won't let you create a
Dev_Table_Ptr_Type that points to the array, though.

                       -- Adam



^ permalink raw reply	[relevance 6%]

* Re: Memory Access
    @ 2011-11-07 22:26  4% ` Niklas Holsti
  1 sibling, 0 replies; 200+ results
From: Niklas Holsti @ 2011-11-07 22:26 UTC (permalink / raw)


On 11-11-07 21:09 , awdorrin wrote:
> I am trying to migrate source code from an older AdaMulti compiler
> than ran on Solaris to GNAT on Linux.
>
> The original program makes use of shared memory and has structures
> populated in C code that are accessed within Ada code.

By "shared memory", do you mean the "System V" inter-process 
communication mechanism that involves kernel calls to map shared memory 
areas into the address space of a process? Or do you mean just some 
variables within one and the same process and address space that are 
shared (accessed) by different threads, in different languages, but 
within the same process and same address space?

Are the structures (variables) defined (that is, allocated) in C code 
and imported into the Ada code, or vice versa?

Are they statically allocated or dynamically allocated?

How are the variables passed between the C code and the Ada code? As 
parameters in subprogram calls, or through some kind of global pointers 
or addresses?

> The original developers used some AdaMulti 'features' that do not
> appear to exist within GNAT to play some tricks on setting up a
> pointer as an array of records.
>
> For instance:
>
> Config_Type is an Ada Record which matches a C struct.
> A Dev_Table is used as an array of these Config_Type records.
>
> The original code has the following statements:
>
> type Dev_Table_Type is array (Device_Num_Type range<>) of
> Config_Type;
> type Dev_Table_Ptr_Type is access Dev_Table_Type;
> Dev_Table := Dev_Table_Ptr_Type;
> Bounds_Ptr : Global_Types.Int_Ptr_Type;
>
> Then, in the Ada Procedure we have:
>
> Dev_Data_Obj := Get_Object_Pointer( Dev_Data_Obj_Name );

What is Dev_Data_Obj_Name?
What is Get_Object_Pointer?
What is Dev_Data_Obj?

>
> Dev_Table := To_Dev_Table_Ptr( Get_UDP( Dev_Data_Obj) );

What is Get_UDP?

>
> Bounds_Ptr := Dev_Table_Ptr_To_Int_Ptr( Dev_Table );
> Bounds_Ptr.all := 1;
>
> Bounds_Ptr := Int_To_Int_Ptr( Dev_Table_Ptr_To_Int( Dev_Table ) + 4);
> Bounds_Ptr.all := Int32( Num_Devs_Cnst );

What is Num_Devs_Cnst? Is it a static (compile-time) constant, or a 
dynamically computed variable?

>
> The To_Dev_Table_Ptr, Dev_Table_Ptr_To_Int_Ptr, Int_To_Int_Ptr are all
> unchecked conversion methods.

Such conversions beween access types and other types should be avoided 
(as unportable). Current Ada has better facilities (see 
System.Address_To_Access_Conversions, if my memory serves; can't look it 
up, sorry, my mobile net connection is too puny).

>
> I understand that the Bounds_Ptr is being used to assign array
> constraints to the dope vector.

That looks likely, from the code above.

> But I'm guessing that GNAT doesn't
> define these dope vectors using this sort of definition.

Whatever kind of dope vectors GNAT has, one should not access them 
through such low-level and unportable tricks.

>
> I'm
> making the assumption that the way this code was implemented
> (somewhere between 1992 and 98) was not really the right way to
> approach this problem.

I fully agree with that.

> But I'm not sure what method should be used,
> and haven't had much luck the past few days searching the web and
> newsgroups.
>
> I would have thought I could have defined the Dev_Table differently,
> perhaps:
>
> Dev_Table : Dev_Table_Ptr_Type := new Dev_Table_Type( 1 ..
> Num_Devs_Cnst );
>
> If I knew the address of pointer at the time of declaration I figured
> I could do:
>
> for Dev_Table'Address use {address_of_memory_array} - but I won't know
> that until run time, so I'm not sure how I can assign that properly.
>
> I hope I'm making sense here - because I'm pretty confused about all
> of this at the moment... :-)

I think you are on the right track, or tracks, but the solution depends 
on the answers to my questions above.

While waiting for the answers: I hope you are already using pragma 
Convention to tell the Ada compiler to lay out the Ada record types and 
array types following the C conventions.

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



^ permalink raw reply	[relevance 4%]

* Re: acceess problem
  2011-07-26 17:43  5%         ` Adam Beneschan
@ 2011-07-27 12:06  0%           ` Gautier write-only
  0 siblings, 0 replies; 200+ results
From: Gautier write-only @ 2011-07-27 12:06 UTC (permalink / raw)


On 26 juil, 19:43, Adam Beneschan <a...@irvine.com> wrote:
> Although I don't like this approach, if you're going to convert an
> Address to an access object, surely it's better to use
> System.Address_To_Access_Conversions, which is designed for this sort
> of conversion, than to use Unchecked_Conversion, which assumes that a
> System.Address and the access object you're converting to have the
> same format, which isn't always the case.  There's no point in using
> "pure Ada" if it results in code that compiles on another system but
> doesn't work properly.

Could not agree more!
http://globe3d.svn.sourceforge.net/viewvc/globe3d/bindings/gl.adb?r1=153&r2=152&pathrev=153



^ permalink raw reply	[relevance 0%]

* Re: acceess problem
  @ 2011-07-26 17:43  5%         ` Adam Beneschan
  2011-07-27 12:06  0%           ` Gautier write-only
  0 siblings, 1 reply; 200+ results
From: Adam Beneschan @ 2011-07-26 17:43 UTC (permalink / raw)


On Jul 26, 8:57 am, Gautier write-only <gautier_niou...@hotmail.com>
wrote:
> On 25 juil, 10:27, Simon Wright <si...@pushface.org> wrote:
>
> > Replace 'Access with 'Unchecked_Access or, if that doesn't work, with
> > the (GNAT-special) 'Unrestricted_Access.
>
> Unless 'Unrestricted_Access has been inbetween added to the language,
> there is a way to have it in a pure Ada form:
>
>   function Cvt is new
> Ada.Unchecked_Conversion(System.Address,DoublePtr);
>   -- This method is functionally identical as GNAT's
> Unrestricted_Access
>   -- but has no type safety (cf GNAT Docs)
>   pragma No_Strict_Aliasing(DoublePtr); -- recommended by GNAT 2005
>
>   procedure Vertex (v: Double_vector_3D) is
>   begin
>     Vertex3dv(Cvt(v(0)'Address));
>   end Vertex;
>
> ^this is an excerpt from an existing GL binding (why reinvent it?)...http://globe3d.svn.sourceforge.net/viewvc/globe3d/bindings/gl.adb?rev...

Although I don't like this approach, if you're going to convert an
Address to an access object, surely it's better to use
System.Address_To_Access_Conversions, which is designed for this sort
of conversion, than to use Unchecked_Conversion, which assumes that a
System.Address and the access object you're converting to have the
same format, which isn't always the case.  There's no point in using
"pure Ada" if it results in code that compiles on another system but
doesn't work properly.

                              -- Adam



^ permalink raw reply	[relevance 5%]

* Re: How do I write directly to a memory address?
  @ 2011-02-03 18:07  5% ` Jeffrey Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey Carter @ 2011-02-03 18:07 UTC (permalink / raw)


On 02/03/2011 01:08 AM, mockturtle wrote:
>
> I do not have any experience about this part of Ada, but maybe I can give you
> a "pointer" to some bootstrapping information.  Maybe you could want to use
> an attribute representation  clause for Vidmem'Address (see Section 13.3 of
> the RM) . With some improvisation, I would write something like
>
> type Vidmem_Array is array (natural range<>) of Character; Vidmem :
> Vidmem_Array (0 .. Max_Size);
>
> for Vidmem'Address use 16#000B_8000#;

An address clause is the usual approach. If one is going to write to such 
memory, one probably doesn't care what the Ada runtime might do to initialize 
it, but if one is planning to read predefined information stored there, one 
probably wants to prevent any initialization through a pragma Import:

pragma Import (Ada, Vidmem);

System.Address is an implementation-defined type, and an address clause takes a 
value of that type. A universal integer may or may not be acceptable. Any such 
code is not portable.

Other possibilities include Ada.Storage_IO (ARM A.9) and 
System.Address_To_Access_Conversions (ARM 13.7.2). Masochists (such as those who 
use C-family languages by choice) might want to use address arithmetic, found in 
System.Storage_Elements (ARM 13.7.1).

Note that the quoted C code will happily read from memory not part of message 
and write to memory not part of vidmem; Ada will not.

-- 
Jeff Carter
"How'd you like to hide the egg and gurgitate
a few saucers of mocha java?"
Never Give a Sucker an Even Break
101



^ permalink raw reply	[relevance 5%]

* Re: User Defined Storage Pool : Example
  @ 2011-01-22  9:47  4% ` anon
  0 siblings, 0 replies; 200+ results
From: anon @ 2011-01-22  9:47 UTC (permalink / raw)


-- referance delete for spacing


-- Found on www.adapower.com
--
-- http://www.adapower.com/index.php?Command=Class&ClassID=Advanced&CID=222
--
-- Files:
--        memory_management-test.adb
--        memory_management-support.ads
--        memory_management-support.adb
--        memory_management.ads
--        memory_management.adb
--
-- To compile and run:
-- 
--   >gnat make memory_management-test.adb
--   >memory_management-test

--
--  Memory Management with Storage Pools (Anh Vo)
--
--  Memory management can cause real headache due to memory leakage over 
--  time. That is, memory allocation is not properly deallocated after the 
--  call. When the memory runs out, the result could be catastrophic for 
--  some applications. This problem can be recued by garbage collector 
--  built-in the compiler such as Java. However, the cost of run-time 
--  overhead is high.
     
--  Here comes Ada 95 to the recue. How is it possible you may ask? Ah! 
--  Ada 95 provides a feature called Storage Pool. It allows the users 
--  have total control over the memory management. Best of all, it does 
--  not involve run-time overhead as garbage collector. When it is 
--  combined with controlled type, the memory leakage problem is history.
    
--  As shown in the test case, 100 storage elements were allocated 
--  initially. Then, these storage elements are reused again and again. It 
--  is pretty cool isn't it? Enjoy.
     

--------------------------------------------
-- File => memory_management-test.adb
--
with Ada.Finalization ;
with Ada.Text_Io ;
with Memory_Management.Support ;
     
procedure Memory_Management.Test is
    use Ada ;
    use Text_Io ;
     
begin
     
  Put_Line ("********* Memory Control Testing Starts **********") ;
   
  for Index in 1 .. 10 loop
    declare
      David_Botton : Support.General_Data ;
      Nick_Roberts : Support.General_Data ;
      Anh_Vo       : Support.General_Data ;
     
    begin
      David_Botton := ( Finalization.Controlled with
                         Id   => new Integer' ( 111 ), 
                         Name => new String' ( "David Botton" ) ) ;

      Nick_Roberts := ( Finalization.Controlled with
                          Id   => new Integer' ( 222 ), 
                          Name => new String' ( "Nick Roberts" ) ) ;

      Anh_Vo := ( Finalization.Controlled with
                    Id   => new Integer' ( 333 ),
                    Name => new String' ( "Anh Vo" ) ) ;
    end ;
  end loop ;
     
  Put_Line ( "Memory Management Test Passes" ) ;
     
exception
  when others =>
    Put_Line ( "Memory Management Test Fails" ) ;
     
end Memory_Management.Test ;


--------------------------------------------
-- File => memory_management-support.ads
--
with Ada.Finalization ;
     
package Memory_Management.Support is
     
  use Ada ;
     
  -- Adjust the storage size according to the application
  Big_Pool : User_Pool ( Size => 100 )  ;
     
  type Int_Acc is access Integer ;
    for Int_Acc'Storage_Pool use Big_Pool ;
     
  type Str_Acc is access all String ;
    for Str_Acc'Storage_Pool use Int_Acc'Storage_Pool ;
     
  type General_Data is new Finalization.Controlled 
         with record
                Id : Int_Acc ;
                Name : Str_Acc ;
              end record ;
     
  procedure Initialize ( Object : in out General_Data )  ;
     
  procedure Finalize ( Object : in out General_Data )  ;
     
end Memory_Management.Support ;
     

--------------------------------------------
-- File => memory_management-support.adb
--
with Ada.Unchecked_Deallocation ;
     
package body Memory_Management.Support is
     
  procedure Free is new Ada.Unchecked_Deallocation 
                                                 ( Integer, Int_Acc ) ;
  procedure Free is new Ada.Unchecked_Deallocation
                                                  ( String, Str_Acc ) ;
     
   procedure Initialize ( Object : in out General_Data ) is
     begin
       null ;
     end Initialize ;
     
  procedure Finalize ( Object : in out General_Data ) is
    begin
      Free ( Object.Id ) ;
      Free ( Object.Name ) ;
    end Finalize ;
     
end Memory_Management.Support ;
     
--------------------------------------------     
-- File => memory_management.ads
--
with System.Storage_Pools ;
with System.Storage_Elements ;
     
package Memory_Management is
     
    use System ;
    use Storage_Elements ;
    use Storage_Pools ;
     
  type User_Pool ( Size : Storage_Count ) is new
                                       Root_Storage_Pool with private ;
     
  procedure Allocate ( Pool                     : in out User_Pool ;
                       Storage_Address          :    out Address   ;
                       Size_In_Storage_Elements : in Storage_Count ;
                       Alignment                : in Storage_Count ) ;
     
  procedure Deallocate 
                      ( Pool                     : in out User_Pool ;
                        Storage_Address          : in     Address   ;
                        Size_In_Storage_Elements : in Storage_Count ;
                        Alignment                : in Storage_Count ) ;
     
  function Storage_Size ( Pool : in User_Pool ) 
               return Storage_Count ;
     
  -- Exeption declaration

  Memory_Exhausted : exception ;
     
  Item_Too_Big : exception ;
     
private
  type User_Pool ( Size : Storage_Count ) is new Root_Storage_Pool
           with record
                  Data       : Storage_Array ( 1 .. Size ) ;
                  Addr_Index : Storage_Count := 1 ;
                end record ;
     
end Memory_Management ;
     

--------------------------------------------     
-- File => memory_management.adb
--
with Ada.Exceptions ;
with Ada.Text_Io ;
with System ;
with System.Storage_Elements ;
with System.Address_To_Access_Conversions ;
     
package body Memory_Management is
     
    use Ada ;
    use Text_Io ;
    use System ;
    use Storage_Elements ;
    use type Storage_Count ;
     
  Package_Name : constant String := "Memory_Management." ;
     
    -- Used to turn on/off the debug information
  Debug_On : Boolean := True ; -- False ;
     
  type Holder is record
         Next_Address : Address := System.Null_Address ;
  end record ;
     
  package Addr_To_Acc is new Address_To_Access_Conversions ( Holder ) ;
     
  -- Keep track of the size of memory block for reuse
  Free_Storage_Keeper : array ( Storage_Count range 1 .. 100 )
          of Address := ( others => Null_Address ) ;
     
  procedure Display_Info ( Message       : string ; 
                           With_New_Line : Boolean := True ) is
    begin
      if Debug_On then
        if With_New_Line then
          Put_Line ( Message ) ;
        else
          Put ( Message ) ;
        end if ;
      end if ;
    end Display_Info ;
     

  procedure Allocate ( Pool                     : in out User_Pool ;
                       Storage_Address          :    out Address   ;
                       Size_In_Storage_Elements : in Storage_Count ;
                       Alignment                : in Storage_Count ) is
          
      Procedure_Name : constant String := "Allocate" ;
      Temp_Address   : Address  := Null_Address ;
      Marker         : Storage_Count ;
    begin
     
      Marker := ( Size_In_Storage_Elements + Alignment - 1 )
              / Alignment ;
     
      if Free_Storage_Keeper ( Marker ) /= Null_Address then
        Storage_Address := Free_Storage_Keeper ( Marker ) ;
        Free_Storage_Keeper (Marker) :=
        Addr_To_Acc.To_Pointer 
                ( Free_Storage_Keeper ( Marker ) ).Next_Address ;
      else
        Temp_Address := Pool.Data (Pool.Addr_Index)'Address ;
              
        Pool.Addr_Index := Pool.Addr_Index 
                         + Alignment 
                         * ( ( Size_In_Storage_Elements 
                               + Alignment - 1 ) 
                         / Alignment ) ;
     
        -- make sure memory is available as requested
        if Pool.Addr_Index > Pool.Size then
          Exceptions.Raise_Exception ( Storage_Error'Identity,
                                       "Storage exhausted in " 
                                       & Package_Name 
                                       & Procedure_Name ) ;
        else
          Storage_Address := Temp_Address ;
        end if ;
      end if ;
     
      Display_Info  ( "Address allocated from pool: "
                      & Integer_Address'Image 
                          ( To_Integer ( Storage_Address ) ) ) ;
   
      Display_Info ( "storage elements allocated from pool: "
                     & Storage_Count'Image 
                          ( Size_In_Storage_Elements ) ) ;
     
      Display_Info ( "Alignment in allocation operation: "
                     & Storage_Count'Image ( Alignment ) ) ;
   
    exception
      when Error : others => -- Object too big or memory exhausted
        Display_Info ( Exceptions.Exception_Information ( Error ) ) ;
        raise ;
     
    end Allocate ;


  procedure Deallocate 
                     ( Pool                     : in out User_Pool ;
                       Storage_Address          : in     Address   ;
                       Size_In_Storage_Elements : in Storage_Count ;
                       Alignment                : in Storage_Count ) is
          
      Marker : Storage_Count ;
     
    begin
     
      Marker := ( Size_In_Storage_Elements + Alignment - 1) 
              / Alignment ;
      Addr_To_Acc.To_Pointer ( Storage_Address ).Next_Address :=
                                     Free_Storage_Keeper ( Marker ) ;
      Free_Storage_Keeper ( Marker ) := Storage_Address ;
     
      Display_Info  ( "Address returned to pool: " 
                      & Integer_Address'Image 
                          ( To_Integer ( Storage_Address ) ) ) ;
     
      Display_Info ( "storage elements returned to pool: "
                     & Storage_Count'Image 
                         ( Size_In_Storage_Elements ) ) ;
     
      Display_Info ( "Alignment used in deallocation: "
                     & Storage_Count'Image ( Alignment ) ) ;
     
  end Deallocate ;
     
  function Storage_Size ( Pool : in User_Pool ) 
             return Storage_Count is
    begin
      return Pool.Size ;
    end Storage_Size ;
     
end Memory_Management ;




^ permalink raw reply	[relevance 4%]

* Re: Does mmap gives a right result?!
  @ 2010-10-04  8:05  5% ` Ludovic Brenta
  0 siblings, 0 replies; 200+ results
From: Ludovic Brenta @ 2010-10-04  8:05 UTC (permalink / raw)


Francesco PIRANEO GIULIANO wrote on comp.lang.ada:
>[...] I've imported mmap as follows:
>
>    function mmap(addr : in u32; length : in u32; prot : in mmap_prot;
> flags : in mmap_flag; fd : in file_id; offset : in u32) return
> Void_Ptr;
>    pragma import( C, mmap, "mmap" );
>    pragma import_function(mmap);
>
> Void_Ptr is defined as follows:
>
>    type void is mod System.Memory_Size;
>    for void'Size use System.Word_Size;
>
>    type Void_Ptr is access all Void;
>    pragma Convention (C, Void_Ptr);
>
> The lines above has been derived by:http://en.wikibooks.org/wiki/Ada_Programming/Types/access#Where_is_vo...
>
> Finally, the mmap has been called as follows:
>
>       fbindex := mmap(0, fbhandler.fixinfo.smem_len,
> fbhandler.PROT_READ + fbhandler.PROT_WRITE, fbhandler.MAP_FILE +
> fbhandler.MAP_SHARED, fbid, 0);
>
> NOTE: I defined PROT_READ and so on as constants in my code;
>
> First question: I have to analyze if fbindex is /= -1 otherwise I have
> to raise an exception:
>
>       if integer(fbindex) = -1 then
>              raise BADMMAPRESULT;
>       end if;
>
> ...seems to be the most logical comparision BUT the following error in
> compile phase appears: "illegal operand for numeric conversion" -- Any
> help is really apreciated here! :-)
>
> When commenting out the above instructions and starting the compiled
> application, everything goes right except, when I try to draw inside
> the first location the program hungs with the following:
>
> raised STORAGE_ERROR : stack overflow (or erroneous memory access)
>
> I'm quite sure my mmap doesn't run properly. I'm about to makes all
> framebuffer's interfacing functions in C then implement the remaining
> in Ada but it will be a nice things if everything can be made with the
> same language.
>
> Any clues or opinion is welcome about.

Since mmap returns (void*) -1 or a "valid" void pointer, I would
import it into Ada as a function returning
System.Storage_Elements.Integer_Address, which you can compare against
-1 and convert to a System.Address using
System.Storage_Elements.To_Address. For example:

function mmap (Hint : in System.Address; Length : in
System.Storage_Elements.Storage_Count;
  Prot : in mmap_prot; Flags : in mmap_flag; fd : in file_id; offset :
in u32)
  return System.Storage_Elements.Integer_Address;
pragma Import (C, mmap, "mmap");

But all this work (the definition of constants for the flags, the
import, the comparison with -1, the raising of an exception and the
conversion to System.Address) has already been done in Florist, see
the function POSIX.Memory_Mapping.Map_Memory. I suggest you simply
"aptitude install libflorist2009-dev", add "with "florist";" to your
project file and compile...

Once you have the address, you can either:

(1) declare the object contained in the file with an address
representation clause, or
(2) convert the address to an access value using an instance of
System.Address_To_Access_Conversions.

HTH

PS. Jacob has nice stories to tell about this function...

--
Ludovic Brenta.



^ permalink raw reply	[relevance 5%]

* Access to C_float wipes out float value
@ 2010-08-20  1:40  6% deadlyhead
  0 siblings, 0 replies; 200+ results
From: deadlyhead @ 2010-08-20  1:40 UTC (permalink / raw)


I'm in the unfortunate position of needing to interface to code which
deals heavily with void* c types and functions.  In order to get to
grips with this, I've written two small files whereby I created a
function which returns a void* in C, and in Ada this value is
converted to an Access type (depending on the input to the C
function), and it's .all value is then displayed.

The code:

/*************************** Begin C code ***************************/

#include "stdio.h"

void*
do_something (int get_float)
{

  int*   i;
  float* f;

  int in = 12345;
  float fl = 9876.54321;

  f = &fl;
  i = &in;

  if (!get_float) {
    printf ("Value of \"*i\" is %d\n", *i);
    return i;
  } else {
    printf ("Value of \"*f\" is %f\n", *f);
    return f;
  }
}

/**************************** End C code ****************************/

--------------------------- Begin Ada code ---------------------------

with Ada.Text_IO;         use Ada.Text_IO;

with System;
with System.Address_To_Access_Conversions;
with Interfaces.C;

procedure Void_Stuff is

   package C renames Interfaces.C;

   subtype Void_Ptr is System.Address;

   package Int_ATAC is new System.Address_To_Access_Conversions
     (Object => C.int);

   package Flt_ATAC is new System.Address_To_Access_Conversions
     (Object => C.C_float);


   package Int_IO is new Integer_IO (C.int);
   use Int_IO;

   package C_Float_IO is new Float_IO (C.C_float);
   use C_Float_IO;

   use Int_ATAC;
   use FLT_ATAC;

   type C_Bool is  (False, True);
   for  C_Bool use (False => 0, True => 1);
   pragma Convention (C, C_Bool);

   function Do_Something (Get_Float : C_Bool) return Void_Ptr;
   pragma Import (C, Do_Something, "do_something");

   My_Int : Int_ATAC.Object_Pointer;
   My_Flt : Flt_ATAC.Object_Pointer;

begin

   --  Let's do this
   My_Int := To_Pointer (Do_Something (False));

   Put ("The value of ""My_Int"" is ");
   Put (My_Int.all, Width => 0);
   New_Line;

   My_Flt := To_Pointer (Do_Something (True));
   Put ("The value of ""My_Flt"" is ");
   Put (My_Flt.all);
   New_Line;

end Void_Stuff;

---------------------------- End Ada Code ----------------------------

The output:

Value of "*i" is 12345
The value of "My_Int" is 12345
Value of "*f" is 9876.542969
The value of "My_Flt" is  6.06708E-39      <----- wtf???

I can't think of any way that I messed this up.  There must me
something about float* in C that truly screws them up when treated as
a System.Address in Ada.  I suppose that the safest way would be to
wrap such a function up in a nice, type-safe Ada function where only
one output type is possible and use an ... access Float; type instead,
but _dang_.  I really want to know what's going on here.

Maybe my problem is my dislike of C in general, and a subsequent lack
of understanding?  I plan on implementing a nice thick binding as this
project progresses, so I'll be getting around this anyway.  Thank you
if you can provide any insight, though.

-- deadlyhead



^ permalink raw reply	[relevance 6%]

* Re: Gem 39 - compiler specific?
  2009-09-04 12:07  4%                 ` Maciej Sobczak
@ 2009-09-04 22:41  0%                   ` sjw
  0 siblings, 0 replies; 200+ results
From: sjw @ 2009-09-04 22:41 UTC (permalink / raw)


On Sep 4, 1:07 pm, Maciej Sobczak <see.my.homep...@gmail.com> wrote:

> I have done it very recently and I used
> System.Address_To_Access_Conversions. The access values to genuine Ada
> objects (even of class-wide types) are converted to addresses and
> handed to the C++ component, which at some later point in time calls
> back into Ada providing the previously stored address that Ada
> converts to the original access value.
>
> A very important part of this business is that the C++ component
> *never* uses the given address in any other way than to remember it.
> It is just a "cookie".

Then I don't quite see why you needed to convert at all?

   procedure P (Q : Fancy_Access);
   pragma Import (C, Q);

Or is it that the size of a Fancy_Access makes it hard to represent on
the C side?



^ permalink raw reply	[relevance 0%]

* Re: Gem 39 - compiler specific?
  @ 2009-09-04 12:07  4%                 ` Maciej Sobczak
  2009-09-04 22:41  0%                   ` sjw
  0 siblings, 1 reply; 200+ results
From: Maciej Sobczak @ 2009-09-04 12:07 UTC (permalink / raw)


On 4 Wrz, 09:29, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> Do we need that semantics (reinterpret bit pattern as another type)? It is
> difficult to invent a case where an access value would be obtained from a
> bit patterns. It is never needed, IMO.

Hint: interfacing with other languages (notably C and C++) with
libraries that have some callback or object map functionality.

I have done it very recently and I used
System.Address_To_Access_Conversions. The access values to genuine Ada
objects (even of class-wide types) are converted to addresses and
handed to the C++ component, which at some later point in time calls
back into Ada providing the previously stored address that Ada
converts to the original access value.

A very important part of this business is that the C++ component
*never* uses the given address in any other way than to remember it.
It is just a "cookie".

This is an example of scenario where access values are obtained from
what is essentially a bit pattern. The conversions are from access to
address and then from address to access and both are performed by the
Ada code within a single compilation unit. As far as I understand it
is safe, AARM-wise.

--
Maciej Sobczak * www.msobczak.com * www.inspirel.com

Database Access Library for Ada: www.inspirel.com/soci-ada



^ permalink raw reply	[relevance 4%]

* Re: Gem 39 - compiler specific?
  2009-09-03 17:27  0%         ` Adam Beneschan
@ 2009-09-03 20:26  0%           ` Dmitry A. Kazakov
    0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2009-09-03 20:26 UTC (permalink / raw)


On Thu, 3 Sep 2009 10:27:57 -0700 (PDT), Adam Beneschan wrote:

> On Sep 3, 9:38�am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
>> On Thu, 3 Sep 2009 08:26:50 -0700 (PDT), Adam Beneschan wrote:
>>> On Sep 3, 12:26�am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
>>> wrote:
>>>> Skewed address is not a problem here. The problem is that
>>>> System.Address_To_Access_Conversions should take an access type as a
>>>> parameter rather than declare it new. This makes its use quite limited.
>>
>>> I don't see any limitation, at least where To_Pointer is concerned
>>> (which is what the above code needed to use). �If you declare an
>>> instance of this package for any object type T:
>>
>>> � type Convert_T_Access is new System.Address_To_Access_Conversions
>>> (T);
>>
>>> then an object of type Convert_T_Access.Object_Pointer can be
>>> converted to any access type whose designated type is T. �I checked
>>> through the legality rules in 4.6, and I couldn't find a way to
>>> declare an access-to-T type that you couldn't convert an
>>> Object_Pointer to. �Thus, if you have any access type
>>
>>> � type Acc_T is access T; �[or access all T, or access constant T]
>>
>>> you can convert an address Addr to an Acc_T by saying:
>>
>>> � Acc_T (Convert_T_Access.To_Pointer (Addr))
>>
>> But Acc_T is a pool-specific access, while Address_To_Access_Conversions
>> creates a general access type.
> 
> Sigh... I missed that---you can't convert a general access type to a
> pool-specific one.  4.6 can be hard to follow, the way it's organized,
> but that's not a good excuse.  I've read it enough times that I should
> know better.
> 
> However, one could make that case that if you declare a pool-specific
> access type, then by definition it should point to something that's in
> a pool; and that if you want an access that could point to an
> arbitrary address (as Access_To_Address_Conversions would let you do),
> you should use a general access type.

Address may have some specific representation when points into a pool. The
idea of Access_To_Address_Conversions is to provide programmer a bit more
safety than Unchecked_Conversion would.

Why do we have Access_To_Address_Conversions? Why not to require
Unchecked_Conversion to do all the checks Access_To_Address_Conversions
does in the corresponding cases? I mean, there is no obvious reason why the
implementation of Access_To_Address_Conversions should be safer than one of
Unchecked_Conversion. The information the compiler has at the instantiation
point is just same.

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



^ permalink raw reply	[relevance 0%]

* Re: Gem 39 - compiler specific?
  2009-09-03 16:38  0%       ` Dmitry A. Kazakov
@ 2009-09-03 17:27  0%         ` Adam Beneschan
  2009-09-03 20:26  0%           ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Adam Beneschan @ 2009-09-03 17:27 UTC (permalink / raw)


On Sep 3, 9:38 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> On Thu, 3 Sep 2009 08:26:50 -0700 (PDT), Adam Beneschan wrote:
> > On Sep 3, 12:26 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> > wrote:
> >> Skewed address is not a problem here. The problem is that
> >> System.Address_To_Access_Conversions should take an access type as a
> >> parameter rather than declare it new. This makes its use quite limited.
>
> > I don't see any limitation, at least where To_Pointer is concerned
> > (which is what the above code needed to use).  If you declare an
> > instance of this package for any object type T:
>
> >   type Convert_T_Access is new System.Address_To_Access_Conversions
> > (T);
>
> > then an object of type Convert_T_Access.Object_Pointer can be
> > converted to any access type whose designated type is T.  I checked
> > through the legality rules in 4.6, and I couldn't find a way to
> > declare an access-to-T type that you couldn't convert an
> > Object_Pointer to.  Thus, if you have any access type
>
> >   type Acc_T is access T;  [or access all T, or access constant T]
>
> > you can convert an address Addr to an Acc_T by saying:
>
> >   Acc_T (Convert_T_Access.To_Pointer (Addr))
>
> But Acc_T is a pool-specific access, while Address_To_Access_Conversions
> creates a general access type.

Sigh... I missed that---you can't convert a general access type to a
pool-specific one.  4.6 can be hard to follow, the way it's organized,
but that's not a good excuse.  I've read it enough times that I should
know better.

However, one could make that case that if you declare a pool-specific
access type, then by definition it should point to something that's in
a pool; and that if you want an access that could point to an
arbitrary address (as Access_To_Address_Conversions would let you do),
you should use a general access type.

                                    -- Adam



^ permalink raw reply	[relevance 0%]

* Re: Gem 39 - compiler specific?
  2009-09-03 15:26  4%     ` Adam Beneschan
@ 2009-09-03 16:38  0%       ` Dmitry A. Kazakov
  2009-09-03 17:27  0%         ` Adam Beneschan
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2009-09-03 16:38 UTC (permalink / raw)


On Thu, 3 Sep 2009 08:26:50 -0700 (PDT), Adam Beneschan wrote:

> On Sep 3, 12:26�am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:

>> Skewed address is not a problem here. The problem is that
>> System.Address_To_Access_Conversions should take an access type as a
>> parameter rather than declare it new. This makes its use quite limited.
> 
> I don't see any limitation, at least where To_Pointer is concerned
> (which is what the above code needed to use).  If you declare an
> instance of this package for any object type T:
> 
>   type Convert_T_Access is new System.Address_To_Access_Conversions
> (T);
> 
> then an object of type Convert_T_Access.Object_Pointer can be
> converted to any access type whose designated type is T.  I checked
> through the legality rules in 4.6, and I couldn't find a way to
> declare an access-to-T type that you couldn't convert an
> Object_Pointer to.  Thus, if you have any access type
> 
>   type Acc_T is access T;  [or access all T, or access constant T]
> 
> you can convert an address Addr to an Acc_T by saying:
> 
>   Acc_T (Convert_T_Access.To_Pointer (Addr))

But Acc_T is a pool-specific access, while Address_To_Access_Conversions
creates a general access type. Here Unchecked_Conversion between access
types is required, which AFIAK is not guaranteed to work anyway. In some
cases I use:

declare
   X : T;
   for X'Address use Addr;
   pragma Import (X);
begin
   ...

> There do seem to be some limitations on using To_Address, though; you
> can't convert an "access constant T" to an Object_Pointer, and you
> can't convert an access-to-T type that is nested inside a subprogram.

Yes, accessibility rules is another major nuisance.

> So you couldn't use To_Address on those types. Offhand, though, I'd
> guess that there is much less need for this than for To_Pointer, so
> this may not be a severe enough limitation to require fixing.

That happens quite often in generic bodies. An access type comes from a
formal parameter, Address_To_Access_Conversions is instantiated within the
generics. In many (most?) cases I used considered it, I must resort to the
old and ugly Ada programmer's friend .all'Unchecked_Access...

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



^ permalink raw reply	[relevance 0%]

* Re: Gem 39 - compiler specific?
  2009-09-03  7:26  5%   ` Dmitry A. Kazakov
@ 2009-09-03 15:26  4%     ` Adam Beneschan
  2009-09-03 16:38  0%       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Adam Beneschan @ 2009-09-03 15:26 UTC (permalink / raw)


On Sep 3, 12:26 am, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> On Wed, 2 Sep 2009 18:20:36 -0500, Randy Brukardt wrote:
> > "Maciej Sobczak" <see.my.homep...@gmail.com> wrote in message
> >news:9e0bbbcd-260f-48ed-8043-d6280c633e85@h3g2000yqa.googlegroups.com...
> >> Consider:
>
> >>http://www.adacore.com/2008/06/09/gem-39/
>
> >> The example code performs Unchecked_Conversion between addresses of
> >> two different array types.
> >> As far as I understand, there is no standard provision for arrays to
> >> occupy contiguous memory space (and not even for the alignment of
> >> their components) and such a conversion relies heavily on the
> >> assumption that arrays can be "overlaid" by plain address
> >> reinterpretation.
>
> >> Still, this technique is quite attractive. What is the chance (in
> >> practice) to hit the compiler that does not get it "right"?
>
> > This is horrible code; it should never be written in Ada 95 or newer! The
> > problem is that System.Address is not necessarily the same as a general
> > access type, so this Unchecked_Conversion may not work (or may not even
> > compile) on another implementation. (It won't on at least some versions of
> > Janus/Ada, for instance.)
>
> > Ada 95 provides System.Address_to_Access_Conversions for this purpose, so at
> > the very least the writer of the Rock (it surely isn't a "Gem"!!!) should
> > have used it:
>
> > procedure Write_Buffer
> >       (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
> >        Item   : in Buffer)  is
> >       Item_Size : constant Stream_Element_Offset :=
> >                      Buffer'Object_Size / Stream_Element'Size;
>
> >      subtype SEA is Stream_Element_Array (1..Item_Size);
>
> >      package A2A is new System.Address_to_Access_Conversions (SEA);
>
> > begin
> >       Ada.Streams.Write (Stream.all, A2A.To_Pointer (Item'Address).all);
> > end Write_Buffer;
>
> > (As an aside, this technique could not work in Janus/Ada if Buffer was an
> > unconstrained array: 'Address of an unconstrained array points at the array
> > descriptor, not the data.
>
> It must point to the first array element 13.3(14). BTW, it is interesting
> where it should point when the array is empty.
>
> > (That's in fact true for all objects in Janus/Ada:
> > there is a static part and an optional dynamic part, and all operations like
> > 'Address and 'Size point at the static part. That was decided long before
> > Ada 95 came around and tried to change these definitions; it's not practical
> > to change in Janus/Ada as address clauses could not be made to work - among
> > other things - if the static part is ignored.)
>
> Skewed address is not a problem here. The problem is that
> System.Address_To_Access_Conversions should take an access type as a
> parameter rather than declare it new. This makes its use quite limited.

I don't see any limitation, at least where To_Pointer is concerned
(which is what the above code needed to use).  If you declare an
instance of this package for any object type T:

  type Convert_T_Access is new System.Address_To_Access_Conversions
(T);

then an object of type Convert_T_Access.Object_Pointer can be
converted to any access type whose designated type is T.  I checked
through the legality rules in 4.6, and I couldn't find a way to
declare an access-to-T type that you couldn't convert an
Object_Pointer to.  Thus, if you have any access type

  type Acc_T is access T;  [or access all T, or access constant T]

you can convert an address Addr to an Acc_T by saying:

  Acc_T (Convert_T_Access.To_Pointer (Addr))

There do seem to be some limitations on using To_Address, though; you
can't convert an "access constant T" to an Object_Pointer, and you
can't convert an access-to-T type that is nested inside a subprogram.
So you couldn't use To_Address on those types.  Offhand, though, I'd
guess that there is much less need for this than for To_Pointer, so
this may not be a severe enough limitation to require fixing.

                              -- Adam




^ permalink raw reply	[relevance 4%]

* Re: Gem 39 - compiler specific?
  2009-09-02 23:20  5% ` Randy Brukardt
@ 2009-09-03  7:26  5%   ` Dmitry A. Kazakov
  2009-09-03 15:26  4%     ` Adam Beneschan
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2009-09-03  7:26 UTC (permalink / raw)


On Wed, 2 Sep 2009 18:20:36 -0500, Randy Brukardt wrote:

> "Maciej Sobczak" <see.my.homepage@gmail.com> wrote in message 
> news:9e0bbbcd-260f-48ed-8043-d6280c633e85@h3g2000yqa.googlegroups.com...
>> Consider:
>>
>> http://www.adacore.com/2008/06/09/gem-39/
>>
>> The example code performs Unchecked_Conversion between addresses of
>> two different array types.
>> As far as I understand, there is no standard provision for arrays to
>> occupy contiguous memory space (and not even for the alignment of
>> their components) and such a conversion relies heavily on the
>> assumption that arrays can be "overlaid" by plain address
>> reinterpretation.
>>
>> Still, this technique is quite attractive. What is the chance (in
>> practice) to hit the compiler that does not get it "right"?
> 
> This is horrible code; it should never be written in Ada 95 or newer! The 
> problem is that System.Address is not necessarily the same as a general 
> access type, so this Unchecked_Conversion may not work (or may not even 
> compile) on another implementation. (It won't on at least some versions of 
> Janus/Ada, for instance.)
> 
> Ada 95 provides System.Address_to_Access_Conversions for this purpose, so at 
> the very least the writer of the Rock (it surely isn't a "Gem"!!!) should 
> have used it:
> 
> procedure Write_Buffer
>       (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
>        Item   : in Buffer)  is
>       Item_Size : constant Stream_Element_Offset :=
>                      Buffer'Object_Size / Stream_Element'Size;
> 
>      subtype SEA is Stream_Element_Array (1..Item_Size);
> 
>      package A2A is new System.Address_to_Access_Conversions (SEA);
> 
> begin
>       Ada.Streams.Write (Stream.all, A2A.To_Pointer (Item'Address).all);
> end Write_Buffer;
> 
> (As an aside, this technique could not work in Janus/Ada if Buffer was an 
> unconstrained array: 'Address of an unconstrained array points at the array 
> descriptor, not the data.

It must point to the first array element 13.3(14). BTW, it is interesting
where it should point when the array is empty.

> (That's in fact true for all objects in Janus/Ada: 
> there is a static part and an optional dynamic part, and all operations like 
> 'Address and 'Size point at the static part. That was decided long before 
> Ada 95 came around and tried to change these definitions; it's not practical 
> to change in Janus/Ada as address clauses could not be made to work - among 
> other things - if the static part is ignored.)

Skewed address is not a problem here. The problem is that
System.Address_To_Access_Conversions should take an access type as a
parameter rather than declare it new. This makes its use quite limited.

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



^ permalink raw reply	[relevance 5%]

* Re: Gem 39 - compiler specific?
  @ 2009-09-02 23:20  5% ` Randy Brukardt
  2009-09-03  7:26  5%   ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Randy Brukardt @ 2009-09-02 23:20 UTC (permalink / raw)


"Maciej Sobczak" <see.my.homepage@gmail.com> wrote in message 
news:9e0bbbcd-260f-48ed-8043-d6280c633e85@h3g2000yqa.googlegroups.com...
> Consider:
>
> http://www.adacore.com/2008/06/09/gem-39/
>
> The example code performs Unchecked_Conversion between addresses of
> two different array types.
> As far as I understand, there is no standard provision for arrays to
> occupy contiguous memory space (and not even for the alignment of
> their components) and such a conversion relies heavily on the
> assumption that arrays can be "overlaid" by plain address
> reinterpretation.
>
> Still, this technique is quite attractive. What is the chance (in
> practice) to hit the compiler that does not get it "right"?

This is horrible code; it should never be written in Ada 95 or newer! The 
problem is that System.Address is not necessarily the same as a general 
access type, so this Unchecked_Conversion may not work (or may not even 
compile) on another implementation. (It won't on at least some versions of 
Janus/Ada, for instance.)

Ada 95 provides System.Address_to_Access_Conversions for this purpose, so at 
the very least the writer of the Rock (it surely isn't a "Gem"!!!) should 
have used it:

procedure Write_Buffer
      (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
       Item   : in Buffer)  is
      Item_Size : constant Stream_Element_Offset :=
                     Buffer'Object_Size / Stream_Element'Size;

     subtype SEA is Stream_Element_Array (1..Item_Size);

     package A2A is new System.Address_to_Access_Conversions (SEA);

begin
      Ada.Streams.Write (Stream.all, A2A.To_Pointer (Item'Address).all);
end Write_Buffer;

(As an aside, this technique could not work in Janus/Ada if Buffer was an 
unconstrained array: 'Address of an unconstrained array points at the array 
descriptor, not the data. (That's in fact true for all objects in Janus/Ada: 
there is a static part and an optional dynamic part, and all operations like 
'Address and 'Size point at the static part. That was decided long before 
Ada 95 came around and tried to change these definitions; it's not practical 
to change in Janus/Ada as address clauses could not be made to work - among 
other things - if the static part is ignored.)

IMHO, using System.Address is for anything other than address clauses is 
*always* wrong in Ada 95: there are always ways to use general access types 
in order to deal with any "pointer" type issue. But we don't even need to do 
*that* here - you can directly used Unchecked_Conversion to directly convert 
between the array types:

procedure Write_Buffer
      (Stream : not null access Ada.Streams.Root_Stream_Type'Class;
       Item   : in Buffer)  is
      Item_Size : constant Stream_Element_Offset :=
                     Buffer'Object_Size / Stream_Element'Size;

     subtype SEA is Stream_Element_Array (1..Item_Size);

     function To_SEA is new Ada.Unchecked_Conversion (Source => Buffer, 
Target => SEA);

begin
      Ada.Streams.Write (Stream.all, To_SEA (Item));
end Write_Buffer;

And now there is no use of Address or access types at all (other than for 
the stream, of course). Any decent compiler will compile this conversion 
into nothing: No code is needed or should be generated for it. (Janus/Ada 
can do this, and it is pretty dumb. Indeed, it can does this precisely 
because this example needs to work cheaply, as it is the way the majority of 
user-defined stream attributes ought to be written.)

                                                 Randy.







^ permalink raw reply	[relevance 5%]

* Enumeration of network shared under Windows (was: Interpretation of extensions different from Unix/Linux?)
  @ 2009-08-21 10:11  6%                                         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2009-08-21 10:11 UTC (permalink / raw)


On Thu, 20 Aug 2009 19:08:31 -0500, Randy Brukardt wrote:

> I disagree with everything you wrote on this topic. And there will be a way 
> to enumerate roots over my dead body, because it is not reliably 
> implementable on Windows (no matter how you define the roots).

Here is complete Ada program that enumerates Windows shares:

with Ada.Text_IO;           use Ada.Text_IO;
with Interfaces.C.Strings;  use Interfaces.C.Strings;
with Win32;                 use Win32;
with Win32.Windef;          use Win32.Windef;
with Win32.Winnetwk;        use Win32.Winnetwk;
with Win32.Winnt;           use Win32.Winnt;
with Win32.Winerror;        use Win32.Winerror;
with System;                use System;

with System.Address_To_Access_Conversions;

procedure Net_Share is
   Result      : DWORD;
   Count       : aliased DWORD;
   Size        : aliased DWORD;
   Enumeration : aliased HANDLE;
   Buffer      : String (1..10_000);
   use type DWORD;

   function WNetOpenEnumA             -- The standard version is
            (  dwScope       : DWORD; -- unusable for our purpose
               dwType        : DWORD;
               dwUsage       : DWORD;
               lpNetResource : Address;
               lphEnum       : access HANDLE
            )  return DWORD;
   pragma Import (Stdcall, WNETOPENENUMA, "WNetOpenEnumA");

   package Conversions is
      new System.Address_To_Access_Conversions (NETRESOURCEA);

begin
   Result :=
      WNetOpenEnumA
      (  RESOURCE_CONNECTED,
         RESOURCETYPE_DISK,
         0,
         Null_Address,
         Enumeration'Access
      );
   if Result /= NO_ERROR then
      Put_Line ("Error in WNetOpenEnumA" & DWORD'Image (Result));
   end if;
   loop
      Count  := 1;
      Size   := Buffer'Size / 8;
      Result :=
         WNetEnumResource
         (  Enumeration,
            Count'Unchecked_Access,
            Buffer'Address,
            Size'Unchecked_Access
         );
      exit when Result = ERROR_NO_MORE_ITEMS;
      if Result /= NO_ERROR then
         Put_Line ("Error in WNetEnumResource" & DWORD'Image (Result));
      end if;
      declare
         Resource : LPNETRESOURCEA :=
            Conversions.To_Pointer
            (  Buffer'Address
            ) .all'Unchecked_Access;
      begin
         Put_Line
         (  Value (To_Chars_Ptr (Resource.lpLocalName))
         &  " "
         &  Value (To_Chars_Ptr (Resource.lpRemoteName))
         );
      end;
   end loop;
   Result := WNetCloseEnum (Enumeration);
   if Result /= NO_ERROR then
      Put_Line ("Error in WNetCloseEnum" & DWORD'Image (Result));
   end if;
end Net_Share;

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



^ permalink raw reply	[relevance 6%]

* Re: put of access type
  2009-08-18 23:17  5% ` Jeffrey R. Carter
@ 2009-08-19  3:36  0%   ` Rob Solomon
  0 siblings, 0 replies; 200+ results
From: Rob Solomon @ 2009-08-19  3:36 UTC (permalink / raw)


>Rob Solomon wrote:
>> I would like to output a pointer to the screen.
>
>Why? An access value is not usually meaningful.
>
>In general, you can't do this. However, using an instantiation of 
>System.Address_To_Access_Conversions, you can convert values of the access type 
>Object_Pointer declared there to type System.Address. Then, using 
>System.Storage_Elements.To_Integer, you can convert that address to an integer 
>type that you can output using 'Image with Ada.Text_IO or an instantiation of 
>the appropriate generic from Ada.Text_IO.

I thought someone would question why I want this.  As I said in my 1st
message, I'm trying to learn the language and I would like to see what
happens when I define pointers.  I mean access types.

The only way I know to see the results of my playing is to output
them.

Thanks for the help,
Rob




^ permalink raw reply	[relevance 0%]

* Re: put of access type
  @ 2009-08-18 23:17  5% ` Jeffrey R. Carter
  2009-08-19  3:36  0%   ` Rob Solomon
  0 siblings, 1 reply; 200+ results
From: Jeffrey R. Carter @ 2009-08-18 23:17 UTC (permalink / raw)


Rob Solomon wrote:
> I would like to output a pointer to the screen.

Why? An access value is not usually meaningful.

In general, you can't do this. However, using an instantiation of 
System.Address_To_Access_Conversions, you can convert values of the access type 
Object_Pointer declared there to type System.Address. Then, using 
System.Storage_Elements.To_Integer, you can convert that address to an integer 
type that you can output using 'Image with Ada.Text_IO or an instantiation of 
the appropriate generic from Ada.Text_IO.

-- 
Jeff Carter
"My mind is aglow with whirling, transient nodes of
thought, careening through a cosmic vapor of invention."
Blazing Saddles
85



^ permalink raw reply	[relevance 5%]

* Re: GNAT on WinXP: System.OS_Lib.Spawn raises Program_Error
  2009-05-02 20:39  5%   ` anon
@ 2009-05-03  9:42  0%     ` Martin
  0 siblings, 0 replies; 200+ results
From: Martin @ 2009-05-03  9:42 UTC (permalink / raw)


On May 2, 9:39 pm, a...@anon.org (anon) wrote:
> Martin
>
> GNAT.OS_LIB existed in GNAT 3.15p  but since GNAT 2005 it have been
> moved to System.OS_LIB.  And the GNAT.OS_LIB just renames System.OS_LIB
> which makes this package a legacy for older projects and can be avoided for
> future use. It just causes more work for the compiler which increase the
> compile time.

Still there in the Win32 GPL 2008 edition.


> Plus, there are only 6 System files in the RM Ada standards:
>
>   0. System
>   1.   System.Address_To_Access_Conversions
>   2.   System.Machine_Code
>   3.   System.RPC
>   4.   System.Storage_Elements
>   5.   System.Storage_Pools
>
> All others System packages like all GNAT packages are non RM Ada
> standard package list. And any GNAT Ada programmer should know that.

You're assuming a level of knowledge that I don't find in the real
world.


> Adacore's annual or GNU quarterly update of GNAT is the Ada standard, for
> most people and schools, and very few programmers will use anything else.

I have no proof that 'very few programmers will use anything else' and
I suspect you don't either. I've used (professionally) 7 Ada compilers
that I can think of off the top of my head. And at least 1 more that
I've just on a personal level. That's not counting all the different
versions of each compiler separately.


> And any improvement that Adacore makes that is passed to GNU version will
> become to most programmers, additions to the Ada standards.  Just like a
> lot of programmers were using the Ada 2005 specs before they were approved
> in January, 2008.

GNAT extensions are not likely to become standard. Ada2005 specs were
_very_ likely to become standard.

Besides, I assume were all here in c.l.a. because we want to see
_more_ Ada in the world, so hopefully that means more people using all
Ada compilers and not just GNAT. We should be pointing out the 'right
thing to do' to all and let them make their minds up.


> Plus, "GNATLINK" uses "System.OS_LIB.spawn" to call the "gcc" compiler
> to compile the binder generated file.  If this was not OK, then why would
> Adacore or GNU use it?

Because AdaCore / GNU and certainly not going to port they're code to
a different compiler.


> And finally the RM allows the usages of additional System packages to be
> included in a standard.  System.OS_LIB is an "implementation-defined
> children of System" see, RM 13.7 (36),

The RM also allows the use of 'goto', are you advocating wide-spread
use of this facility too? Just because something is allowed does not
make it a 'good idea'.


> So you need to stop with the idea using non standard packages is a "bad
> idea". Plus, all that is needed is a few comments for future version of
> GNAT. And that because most programs written with GNAT will almost
> never be move from GNAT, so only updating comments are needed.

Sorry, that's just pants.

I just went though a porting exercise at work where a project was
looking to migrate from XD-Ada/68k to <some_other_Ada_product>/
PowerPC. One issue with XD-Ada based systems was that XD-Ada included
various non-standard extensions to package System - types of a known
size. This is the 2nd project I've seen that made _large_scale_ use of
these types throughout their code.

Perfectly avoidable (by defining types they know to match the size
required, perhaps even calling it 'Interfaces') or limiting the effect
by defining their own 'Project_System' package. The 1st option would
have involved 0 hours work the 2nd option a 2 minute job with minimal
source code files touched. In the end _dozens_ of files needed to be
modified and that incurs a lot more time (i.e. money) to check / re-
test.

Like I said - this is not the first time this has happened (and not
just with Ada - VC++ no hasn't come with <iostream.h>, only
<iostream>, since 2005 and I've seen projects which started post-98
when <iostream> was the standard header defined get bitten by this).

Cheers
-- Martin




^ permalink raw reply	[relevance 0%]

* Re: GNAT on WinXP: System.OS_Lib.Spawn raises Program_Error
  @ 2009-05-02 20:39  5%   ` anon
  2009-05-03  9:42  0%     ` Martin
  0 siblings, 1 reply; 200+ results
From: anon @ 2009-05-02 20:39 UTC (permalink / raw)


Martin

GNAT.OS_LIB existed in GNAT 3.15p  but since GNAT 2005 it have been 
moved to System.OS_LIB.  And the GNAT.OS_LIB just renames System.OS_LIB 
which makes this package a legacy for older projects and can be avoided for 
future use. It just causes more work for the compiler which increase the 
compile time.

Plus, there are only 6 System files in the RM Ada standards: 

  0. System
  1.   System.Address_To_Access_Conversions
  2.   System.Machine_Code
  3.   System.RPC
  4.   System.Storage_Elements
  5.   System.Storage_Pools

All others System packages like all GNAT packages are non RM Ada 
standard package list. And any GNAT Ada programmer should know that. 

Adacore's annual or GNU quarterly update of GNAT is the Ada standard, for 
most people and schools, and very few programmers will use anything else. 
And any improvement that Adacore makes that is passed to GNU version will 
become to most programmers, additions to the Ada standards.  Just like a 
lot of programmers were using the Ada 2005 specs before they were approved 
in January, 2008.

Plus, "GNATLINK" uses "System.OS_LIB.spawn" to call the "gcc" compiler 
to compile the binder generated file.  If this was not OK, then why would 
Adacore or GNU use it? 

And finally the RM allows the usages of additional System packages to be 
included in a standard.  System.OS_LIB is an "implementation-defined 
children of System" see, RM 13.7 (36),

So you need to stop with the idea using non standard packages is a "bad 
idea". Plus, all that is needed is a few comments for future version of 
GNAT. And that because most programs written with GNAT will almost 
never be move from GNAT, so only updating comments are needed.



In <923b28dd-46ee-40cb-b13e-5f8860405f22@r36g2000vbr.googlegroups.com>, Martin <martin.dowie@btopenworld.com> writes:
>On May 2, 5:16=A0am, a...@anon.org (anon) wrote:
>> First, in GNAT GPL 2008, GNAT.OS_LIB renames System.OS_LIB, so using
>> GNAT.OS_LIB would be a waste of time.
>
>Not entirely a waste, as using "GNAT.*" makes it explicit to anyone
>reading the code that this is a non-standard package being used. Using
>'System.OS_Lib' would give the erroneous impression to the casual
>reader that only standard language defined packages are being used and
>that there perhaps would be =A30.00 cost to compile it up using a
>different compiler.
>
>Using non-standard extensions to standard units is generally a
>_bad_idea_ but if it is unavoidable then it should be hidden in an
>abstration layer that you have control over.
>
>Cheers
>-- Martin
>




^ permalink raw reply	[relevance 5%]

* Representing image data
@ 2009-03-10 21:26  2% Kenneth Almquist
  0 siblings, 0 replies; 200+ results
From: Kenneth Almquist @ 2009-03-10 21:26 UTC (permalink / raw)


I've been working on the design of an image decoding library.  The
basic idea is that the library will examine the first few bytes of
an image, determine the format, and call the appropriate decoder,
so that an application using the library can read images without
writing code for each image format it wants to handle.

I'm looking for suggestions on what the Ada interface to the
library should look like--and in particular how the image contents
should be provided to the application using the library.  The current
design has a C interface with no type checking on the image data.

What follows is the C language interface presented in Ada syntax.
The data for each pixel consists of one or more samples.  There are
a fair number of possibilities, because both the meaning of the
samples and the number of bits per sample can vary.  The possibilities
for the meanings of the samples are:

    Imd.W - white (greyscale) sample
    Imd.WA - white + alpha (transparency) samples
    Imd.RGB - red + green + blue samples (color image)
    Imd.RGBA - RGB + alpha samples
    Imd.CMYK - C + M + Y + K samples (color printer separation)
    Imd.Unknown - one or more samples whose meaning is not known
                  by the library.

Any of the previous possibilities may be combined with Imd.Mapped.
If Imd.Mapped is set, there is one sample per pixel representing
an index into a color map.  Each entry in the color map will contain
one or more sample values, in one of the formats listed above.

The size of the samples can be one of:

    Imd.Size_1BE
    Imd.Size_8
    Imd.Size_16

Imd.Size_8 means that samples are 8 bits.  The corresponding Ada type
is Interfaces.Unsigned_8 or equivalent.  Imd.Size_16 means 16 bit
samples, stored in Interfaces.Unsigned_16 or equivalent.  Imd.Size_1BE
means one bit samples, packed into Unsigned_8 quantities in big endian
order (high order bit first).  Imd.Size_1BE is only used when there is
one sample per pixel; it is intended to allow bit maps to be represented
compactly.

If a color map is used, then the size of the samples in the color map
also needs to be specified.  The possiblities are:

    Imd.Map_Size_8
    Imd.Map_Size_16

In the C language interface, all of the above constants have the type
Interfaces.Unsigned_16, and can be combined using the "+" or "or"
operators.  For example, mapped RGB color with 8 bit sample sizes can
be specified as

    Imd.RGB or Imd.Mapped or Imd.Size_8 or Imd.Map_Size_8

Most applications would use only a few of the possible output formats.
The library contains conversions to:
    - convert mapped data to unmapped data
    - convert greyscale to RGB.
    - convert CMYK to RGB (but not very accurately).
    - add or discard the alpha channel.
    - convert sample sizes to 8 or 16 bits.
So the library can convert any image to (Imd.RGB or Imd.Size_8) except
for images where the meanings of the samples are unknown.

One additional variation is that the image can be decoded one row at a
time, or in one piece.  A row is represented as a sequence of pixel
values, in left to right order.  An image is represented as a sequence
of rows, in top to bottom order.  If the sample format is Imd.Size_1BE,
then each row will be padded if necessary to make the size a multiple
of 8, so that each row will start on a byte boundary.

After processing the image header, the steps for decoding an image are:

    -- Set the output type.
    -- The variable Decoder is a pointer to the decoder structure.
    if Imd.Set_Output_Format(Decoder, Imd.RGB or Imd.Mapped or
                              Imd.Size_8 or Imd.Map_Size_8) = False then
	Ada.Text_IO.Put_Line("Cannot convert to mapped RGB format");
        raise ...;
    end if;

    -- Read the map (only do this for mapped output).
    declare
        type Map_Type is ...;
        type Map_Ptr is access all Map_Type;
    begin
        -- Allocate space for map.  The Sizeof_Map routine calculates
        -- the correct size.
        Map_Ptr := malloc(Imd.Sizeof_Map(Decoder));
        if Map_Ptr = null then raise Storage_Error; end if;

	-- Get the map.
        Imd.Get_Map(Decoder, Map_Ptr.all'Address);
        if Decoder.Error /= 0 then raise ...; end if;
        ...
    end;

    -- Read the entire image at once.
    declare
        type Image_Array is ...;
        type Image_Ptr is access all Image_Array;
    begin
	-- Allocate space for the image.  Imd.Sizeof_Image calculates
	-- the correct size.
        Image_Ptr := malloc(Imd.Sizeof_Image(Decoder));
        if Map_Ptr = null then raise Storage_Error; end if;

        -- Read the image.
        Imd.Get_Image(Decoder, Image_Ptr.all'Address);
        if Decoder.Error /= 0 then raise ...; end if;
        ...
    end;

If the application wants to read one row at a time, it uses something like:

    -- Read the image, one row at a time.
    if Imd.Start_Output(Decoder) = False then
	Ada.Text_IO.Put_Line("Cannot decode image");
        raise ...;
    end if;

    for Row_Number in 1 .. Decoder.Height loop
        declare
            type Row is ...;
            package Row_Acc is new System.Address_To_Access_Conversions(Row);
            Row_Ptr : Row_Acc.Object_Ptr;
        begin
            -- Read one row.  Read_Row returns a pointer to the
            -- row, which is stored in a block of memory allocated
            -- by the library.
            Row_Ptr := Row_Acc.To_Pointer(Imd.Read_Row(Decoder));
            ...
        end;
    end loop;
    -- Check for error.  We could have done this inside the loop.
    if Decoder.Error /= 0 then raise ...; end if;

For Imd.RGB + Imd.Size_8 output, the Row type could be declared as

    type Primary is (Red, Green, Blue);
    type Pixel is array (Primary) of Interfaces.Unsigned_8;
    type Row is array(1 .. Decoder.Width) of Pixel;

But in C you would probably do the equivalent of

    type Row is array (Natural) of Interfaces.Unsigned_8;

Thanks for any ideas.
		                Kenneth Almquist



^ permalink raw reply	[relevance 2%]

* Re: Access procedure to pointer
  2008-05-27 11:19  5% Access procedure to pointer Sébastien
@ 2008-05-27 16:51  0% ` Jeffrey R. Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey R. Carter @ 2008-05-27 16:51 UTC (permalink / raw)


S�bastien wrote:
> 
> I need to convert an access to a procedure to a pointer 
> (System.Address). I can't use the System.Address_To_Access_Conversions 
> package since I can't define a type on a procedure (only on a procedure 
> access).

Why do you need to do this?

Note that System.Address is not necessarily the same as a pointer, whether you 
mean an Ada access value or a C pointer. Assuming so can cause portability 
problems, and I can't recall a situation where it was necessary.

-- 
Jeff Carter
"What's the amount of the insult?"
Never Give a Sucker an Even Break
104



^ permalink raw reply	[relevance 0%]

* Access procedure to pointer
@ 2008-05-27 11:19  5% Sébastien
  2008-05-27 16:51  0% ` Jeffrey R. Carter
  0 siblings, 1 reply; 200+ results
From: Sébastien @ 2008-05-27 11:19 UTC (permalink / raw)


Hi,

I need to convert an access to a procedure to a pointer 
(System.Address). I can't use the System.Address_To_Access_Conversions 
package since I can't define a type on a procedure (only on a procedure 
access).

Is there any way to do it?

Thanks,
Sebastien



^ permalink raw reply	[relevance 5%]

* Re: Pointer
  @ 2008-05-19 10:32  5%     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2008-05-19 10:32 UTC (permalink / raw)


On Mon, 19 May 2008 10:13:48 +0000, S�bastien wrote:

>> Suggesting, n is returned from the C program:
>> 
>> with Interfaces.C;  use Interfaces.C;
>> with Interfaces.C.Strings;  use Interfaces.C.Strings;
>> 
>> function Get_It return String is
>>    procedure Internal (N : out size_t; Data : out chars_ptr);
>>    pragma Import (C, Internal, "<C-name>");
>>    Data : chars_ptr;
>>    N : size_t;
>> begin
>>    Internal (Data);
>>    return Value (N, Data);
>> end Get_It;
> 
> Yes it's exaclty what I did ... and it's exaclty what I would like to 
> avoid :-) Actually, I was looking for a pure Ada solution.

In what sense pure? Do you want to re-implement Interfaces.C.String?

> I think there is a way using an unchecked type conversion, but how to be 
> sure of the size of the System.Address?

(And how to sure about the size of Character vs. char?)

You could convert System.Address to a pointer of an Ada object using an
instance of System.Address_To_Access_Conversions.

(It seems that I don't fully understand your problem)

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



^ permalink raw reply	[relevance 5%]

* Access to fixed memory location
@ 2007-11-30 19:32  5% Tomas Cernaj
  0 siblings, 0 replies; 200+ results
From: Tomas Cernaj @ 2007-11-30 19:32 UTC (permalink / raw)


Hello everyone,

is there any way to tell the Ada compiler that an Address attribute 
should be constant? I want to use it for accessing fixed memory 
locations, and without the Address attribute being constant the compiler 
won't optimize away an indirect access.

I couldn't find anything in the RM or GNAT documentation... The point is 
that I want to use the 'Address construct on the AVR target, which is an 
8-bit processor, so the indirect access is quite expensive.

I suppose that was a bit unclear, so here's an example: :)
I have the following declarations in a package spec file:

    type T_Type is array (0 .. 7) of Boolean;
    pragma Pack (T_Type);
    for T_Type'Size use 8;
    
    package TA is new System.Address_To_Access_Conversions (T_Type);
    X : constant access T_Type
        := TA.To_Pointer (System.Storage_Elements.To_Address (50));
    
    Y : T_Type;
    for Y'Address use System.Storage_Elements.To_Address (51);
    pragma Import (Ada, Y);

Note that X is something like a "T_Type * const X" in C.
Compiling the following code

        X (4) := True;
        Y (5) := True;

with GNAT (gcc-4.2 -O -S) yields this assembler output (x86-64):

        orb     $16, 50			; X (4) := True
        movq    testpkg__y(%rip), %rdx	; Y (5) := True
        movzbl  (%rdx), %eax
        orl     $32, %eax
        movb    %al, (%rdx)

That's because the compiler can not assume that Y'Address will not be 
changed.

Thank you for your help,
Tomas



^ permalink raw reply	[relevance 5%]

* Re: urgent question - generics
  @ 2007-09-04  0:38  4%   ` anon
  0 siblings, 0 replies; 200+ results
From: anon @ 2007-09-04  0:38 UTC (permalink / raw)


-- A more complete answer since your through with your test. And yes 
-- you can copy and paste this code into a a file and use the gnat 
-- system to compile/bind/link and then excute the program.
--
-- In most cases there are a number of ways to create code.  Some are 
-- more direct or aids the compiler to help you while others are more 
-- indirect or toward the system performance and code usage. I did have 
-- seven ways of answering the question but the other 3 were too 
-- complex for a beginner. Even one use the generic package 
-- caled "System.Address_To_Access_Conversions" 
--
-- But in true Generic the function should be able to handle all
-- types of calls both Ada and non-Ada procedure.
--
-- In GNAT both Access and Address are the same but with other 
-- system where memory is protected or even using seperate 
-- memories this may not be the case.
--

with Ada.text_IO ;
with System ;

--
-- see function_3, might be too complex.
--
with Ada.Unchecked_Conversion ;

procedure zzero is

  --
  -- This allows all types of procedures both Ada and external
  -- with or without parameters.  Creates a static procedure 
  -- design effect.
  --
  function function_0 ( func : System.Address ; Data : Float ) 
             return float is

      procedure tst ;
      pragma Import ( Ada, tst ) ;
      for tst'address use func ;

    begin -- function_0
      tst ;
      return Data * 2.0 ;
    end function_0 ;

------------------------------------------------------------------------------
-- The Probability the answer that she ask for:                             --
--                                                                          --
--   type proc_access is access procedure ; -- is the generic statement     --
--                                          -- that she needed.             --
--                                                                          --
--   tst.all ;                              -- statement to call set        --
--                                          -- procedure                    --
--                                                                          --
------------------------------------------------------------------------------
  --
  -- This version allows only procedures that are Ada without 
  -- parameters.
  --

  type proc_access is access procedure ;

  function function_1 ( tst : proc_access ; Data : Float ) 
             return float is

    begin -- function_1
      tst.all ;
      return Data * 2.0 ;
    end function_1 ;



  --
  -- This version allows only procedures that are Ada without 
  -- parameters. Creates a static procedure design effect for 
  -- calling procedure.
  --

  type func_access is access procedure ;

  function function_2 ( func : func_access ; Data : Float ) 
             return float is

      procedure tst ;
      pragma Import ( Ada, tst ) ;
      for tst'address use func.all'address ;

    begin -- function_2
      tst ;
      return Data * 2.0 ;
    end function_2 ;


  --
  -- This version allows only procedures that are Ada without 
  -- parameters. And also use another Generic package to 
  -- convert the addressing schemes that creates a static 
  -- procedure design effect. But shows that both can be used 
  -- in the same package.
  --
  type procedure_access is access procedure ;

  function function_3 ( func : procedure_access ; Data : Float ) 
               return float is


      -- --------------------------------------- --
      -- use for calling method version two only --
      -- --------------------------------------- --

      --
      -- limit this conversion function to function_3 usage only
      --
      function PA_To_A is new Ada.Unchecked_Conversion 
                     ( Source => procedure_access, 
                       Target => System.Address ) ;

      procedure tst ;
      pragma Import ( Ada, tst ) ;
      for tst'address use PA_To_A ( func ) ;

    begin -- function_3
      --
      -- simple dynamic call version method 1
      --
      func.all ;
      --
      -- simple static call version method 2
      --
      tst ;
      return Data * 2.0 ;
    end function_3 ;


  -- ---------- --
  -- Test: Proc --
  -- ---------- --

  procedure test is
    begin -- test
      Ada.Text_IO.Put_Line ( "Testing" ) ;
    end test ;


  Result : Float ; 

begin
  Result := function_0 ( test'address, 0.5 ) ;
  --
  Result := function_1 ( test'access, 0.7 ) ;
  Result := function_2 ( test'access, 0.9 ) ;
  --
  Result := function_3 ( test'access, 0.1 ) ;

end zzero ;


In <1188837355.753212.161150@r34g2000hsd.googlegroups.com>,  shoshanister@gmail.com writes:
>On Sep 3, 4:01 pm, a...@anon.org (anon) wrote:
>> In <1188819393.588005.23...@r34g2000hsd.googlegroups.com>,  shoshanis...@gmail.com writes:
>>
>> >Hi, First, I'm a female.
>>
>>   Sorry about calling you a guy, it is an easy mistake to make on the net.
>>
>> >Please don't post any more answers or such.
>>
>>   If you look here I will always answer a question with code if
>>   possible! Its just the way I am.  I even jump of people here for not
>>   posting code.  Because in a test my code or anyone else code is
>>   not going to help, unless you understand it! And the only way is to
>>   see the code.
>>
>> >I understand according to what you wrote that I probably did not fully
>> >understand the generics mechanism. In this case, even if you will
>> >answer my question, it will not help me because my exam starts in an
>> >hour.
>> >I posted the question here, after trying to figure things out by my
>> >self, and I had no intention to insult any one of you or to take
>> >advantage of you.
>>
>>  No insult or advantage of taken!
>>
>> >In a way, I'm not worried of not passing the exam. The worse thing
>> >that can happen is that I will take the course again, and gain my
>> >knowledge from the teacher as well as from the books, because studying
>> >ADA by your self is not simple.
>>
>>   Actually, installing a free GNAT Ada version and starting to program
>>   is the BEST way to learn.  Teachers only have time to give you an
>>   brief understand of any language. In the US that less than 45 hours
>>   spanning 15 weeks. Outside programming is the only way to gain a
>>   deeper understanding. And asking question with an expectation of an
>>   answer is the second best way to gain a direction for that deeper
>>   understand.
>>
>>   Plus, in my many years experience if a person just say read a section
>>   or chapter than they also do not understand the problem or the
>>   language. Even my professor would not do that, they would give an
>>   example (like I did) and then assign someone an extra assignment that
>>   would include the example as a small part of the whole project.
>>
>>   The only thing was their projects, either homework or extra
>>   assignments were too simple for me, (bored me to death).  I actually
>>   had to expand them to make the worth my time.  My Ada professor
>>   use most of my work in Ada to teach his other classes at two
>>   universities and wrote a number of text books using my classwork
>>   that were used in both Europe and US universities.
>>
>>   What I did for my first Ada assignment after modifying it, was
>>   rated at doctoral level programming. I even had to have permission
>>   from 3 universities and their computer systems to fully execute the
>>   assignment.
>>
>> >Thanks a lot for your help.
>> >I hope that some day I will be able to join this group as an equal
>> >member and not just a student.
>>
>>   I kind of believe that 50+ % of this group is students.
>
>Hi, Thanks for your kind response.
>I just came back from the exam. It was not very difficult but I can't
>say it was easy. I don't believe I passed, but it's ok. I don't mind
>attending the course again, Ada is a nice and very powerful language,
>and I wouldn't mind getting to know it better.
>I'm going to get some rest now. Thanks :)
>




^ permalink raw reply	[relevance 4%]

* Re: copying data between memory locations
  @ 2007-09-03 11:09  4% ` Niklas Holsti
  0 siblings, 0 replies; 200+ results
From: Niklas Holsti @ 2007-09-03 11:09 UTC (permalink / raw)


jef.mangelschots@gmail.com wrote:
> In our current design, we have a package that maintains a list of
> descriptors of various buffers in the application. We don't want to
> know their datatypes or how to write data into them. We only want to
> maintain a physical address of them and use that address to directly
> write data into these buffers (this data comes out incoming packets
> over the network).
> 
> In C, this is very straightforward and use the address as a pointer
> and simply copy the packet into the memory location.

Easy to code, hard to debug, ... as you probably know :-)

> I can't figure out a way to do this in Ada (at least not Ada83).
> 
> suppose the following:
> 
> type BUFFER_DETAILS_RECORD is
> record
>     num_bytes : integer;
>     start_address : system.address;
> end record;
> type BUFFER_DETAILS_ARRAY_TYPE is array(1..2) of
> BUFFER_DETAILS_RECORD;
> BUFFER_DETAILS : constant BUFFER_DETAILS_ARRAY_TYPE :=
> BUFFER_DETAILS_ARRAY_TYPE'(1 => (num_bytes => 100, start_address =>
> 16#123# ),  1 => (num_bytes => 200, start_address => 16#456# ));
> 
> procedure insert_block(idx : in integer; num_bytes : in integer;
> offset : in integer; data : BYTE_ARRAY_TYPE) is
> begin
>    ??? how do I copy the content of data into the memory pointed to by
> BUFFER_DETAILS(idx).start_address + offset
> end;

You have two problems, in fact: (1) adding an address and an 
(integer) offset to give a new address, and (2) accessing the data 
at that address.

For the addition problem (1) Ada 95/2007 provide the standard 
package System.Storage_Elements. For Ada 83 I don't know of any 
standard method; I would look for a compiler-specific method, 
perhaps compiler-specific functions in package System or in some 
other compiler-supplied package. You could also try to use 
Unchecked_Conversion to convert System.Address to some integer 
type, add the integers, and convert back, but that works only if 
the System.Address is really implemented as an integral type (and 
not, for example, as a segment + offset). But you can also delegate 
the offset to the second problem (2), see below.

For the accessing problem (2) Ada 95/2007 provide the standard 
package System.Address_To_Access_Conversions that can be used to 
convert the physical address into an access to the buffer, of any 
type desired, for example a Byte_Array_Type.

In Ada 83 there are two methods for accessing data at a given 
System.Address:

- Declare an "overlay" for the buffer using an address clause:

      Vec : Byte_Array_Type;
      for Vec use at the_known_address;

   The LRM says that this feature "should not" be used to achieve
   overlays of objects. In practice it is (or was) used in this
   way, at least when the compiler supported it.

- Use Unchecked_Conversion to convert the physical address to
   an access value (access Byte_Array_Type). This works only if
   access values are really implemented as addresses, which is not
   always the case.

If you always access the buffer as a vector of bytes, you could 
delegate problem (1) to problem (2) by setting up the overlay or 
the access value using Buffer.start_address without including the 
offset, then adding the offset part when you index the Byte_Array, 
using Vec(Buffer.offset), Vec(Buffer.offset+1) .. instead of 
Vec(0), Vec(1), ...

HTH

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



^ permalink raw reply	[relevance 4%]

* Re: Byte streams
  @ 2007-08-03  5:34  4% ` Jeffrey R. Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey R. Carter @ 2007-08-03  5:34 UTC (permalink / raw)


shaunpatterson@gmail.com wrote:
> 
> I've written a socket functions to send and receive data in C and then
> created a spec in Ada so I could use those same functions:
> 
> -- C functions --
> 
> unsigned char *readBytes (const unsigned int numBytes);
> void sendBytes (unsigned char *data, const unsigned int numBytes);
> 
> 
> --- Ada side
> type Byte is mod 256;
> for Byte'Size use 8;
> 
> type ByteStream is array (Integer range <>) of Byte;
> 
> 
> function readBytes (numBytes : Integer) return System.Address;
> pragma import (C, readBytes, "readBytes");

Integer? What would Readbytes (-7) mean?

> procedure sendBytes (data : ByteStream; numBytes : Integer);
> pragma import (C, sendBytes, "sendBytes");

For a direct translation, you should use the types in Interfaces.C and 
Interfaces.C.Strings (ARM B.3[.1]):

function Read_Bytes (Num_Bytes : in Interfaces.C.Unsigned)
return Interfaces.C.Strings.Chars_Ptr;

procedure Send_Bytes (Data      : in Interfaces.C.Char_Array;
                       Num_Bytes : in Interfaces.C.Unsigned);

More in the spirit rather than the letter of what the C is trying to 
say, you probably want to use System.Storage_Elements.Storage_Array:

procedure Send_Bytes
    (Data      : in System.Storage_Elements.Storage_Array;
     Num_Bytes : in Interfaces.C.Unsigned);

You send data by creating a subtype of 
System.Storage_Elements.Storage_Array with a length equal to the value 
you'll pass to Num_Bytes, and instantiating Ada.Unchecked_Conversion 
with this subtype as the target.

>                 type IntegerPtr is access all Integer;
>                 function to_IntegerPtr is new Unchecked_Conversion
>                       (source => System.Address, target =>
> IntegerPtr);
> 
> --- this works...and I can do all the conversions I need using an
> unchecked_conversion

This is highly compiler dependent. There is no guarantee that a 
System.Address and a C pointer are the same size, much less the same 
representation. There is no guarantee that a System.Address and an 
access value are the same size, much less the same representation. There 
are compilers where these things aren't and this won't work.

For situations where you must convert between System.Address and access 
values, there's System.Address_To_Access_Conversions, but this isn't one 
of those cases.

Reading is a little more complicated:

with System;

type Value is ...

type Value_Ptr is access all Value;
pragma Convention (C, Value_Ptr);

The pragma Convention is important; it tells the compiler to use the 
same representation as C. That may be different from Ada's default 
representation.

function Get (Num_Bytes : in Interfaces.C.Unsigned :=
                  Value'Size / System.Storage_Unit)
return Value_Ptr;

This is a way to do it at the low level (streams are another, and 
perhaps better, way). But Ada is usually about hiding the low level. You 
shouldn't want your application declaring access types and imported 
functions and doing unchecked conversions all over the place.

generic -- Socket_IF
    type Value (<>) is private;
package Socket_IF is
    procedure Send (Data : in Value);

    function Read return Value;
end Socket_IF;

with Ada.Unchecked_Conversion;
with Interfaces.C;
with System.Storage_Elements;

package Body Socket_IF is
    subtype Unsigned is Interfaces.C.Unsigned;
    use type Unsigned;

    Num_Bytes : constant Unsigned := Value'Size / System.Storage_Unit;

    procedure Send (Data : in Value) is
       subtype List is
          System.Storage_Elements.Storage_Array (1 .. Num_Bytes);

       function To_List is new Ada.Unchecked_Conversion
          (Source => Value, Target => List);

       procedure C_Send (Data : in List; Size : in Unsigned);
       pragma Import (C, C_Send, ...);
    begin -- Send
       C_Send (Data => To_List (Data), Size => Num_Bytes);
    end Send;

    function Read return Value is
       type Value_Ptr is access all Value;
       pragma Convention (C, Value_Ptr);

       function C_Read (Size : in Unsigned) return Value_Ptr;
       pragma Import (C, C_Read, ...);
    begin -- Read
       return C_Read (Num_Bytes).all;
    end Read;
end Socket_IF;

I haven't tested this, but it might even work.

Now your application only has to instantiate Socket_IF for each type of 
interest, and call the resulting Send and Read operations. Much 
replication of code is eliminated, and you only have to get this right once.

Something similar for the streams approach is left as an exercise for 
the reader.

-- 
Jeff Carter
"We call your door-opening request a silly thing."
Monty Python & the Holy Grail
17



^ permalink raw reply	[relevance 4%]

* Re: Pure, Storage_Size and Unchecked_Conversion
  2007-07-08  9:49  5% ` Georg Bauhaus
@ 2007-07-08 10:41  5%   ` Y.Tomino
  0 siblings, 0 replies; 200+ results
From: Y.Tomino @ 2007-07-08 10:41 UTC (permalink / raw)


gcc 4.1.2 and gcc 4.2.0 are different. The default mode of gcc 4.2.0
is Ada 2005.
And, Ada 2005 accepts access types with "for T'Storage_Size use 0" in
pure package.
"for T'Storage_Size use 0" means to disallow "new". T will be plain
address value, and has no side effect.
Please, see http://www.adaic.com/standards/05rm/html/RM-10-2-1.html

> Just guessing what your package is supposed to achieve,
> have you considered using System.Address_To_Access_Conversions?

System.Address_To_Access_Conversions fixes pointer type as access all.
Actually, I want to use the access constant, and expect inlining.

--
YT http://panathenaia.halfmoon.jp/alang/ada.html




^ permalink raw reply	[relevance 5%]

* Re: Pure, Storage_Size and Unchecked_Conversion
  @ 2007-07-08  9:49  5% ` Georg Bauhaus
  2007-07-08 10:41  5%   ` Y.Tomino
  0 siblings, 1 reply; 200+ results
From: Georg Bauhaus @ 2007-07-08  9:49 UTC (permalink / raw)


On Sat, 2007-07-07 at 17:24 -0700, Y.Tomino wrote:

> with Ada.Unchecked_Conversion;
> package Pure_SS_Unc is
>    pragma Pure;
>    type T is access Integer;
>    for T'Storage_Size use 0;
>    function F1 (X : Integer) return T;
>    function F2 is new Ada.Unchecked_Conversion (Integer, T);
> end Pure_SS_Unc;
> 
> [...]
> pure_ss_unc.ads:7:58: named access types not allowed in pure unit

The message should really apply to the declaration of T.
T is a named access type. If you remove all lines referring
to U_C, the compiler might say something like


GNAT 4.1.2 (Ubuntu 4.1.2-0ubuntu4)
Copyright 1992-2005 Free Software Foundation, Inc.

Compiling: pure_ss_unc.ads (source file time stamp: 2007-07-08 09:44:14)

     4.    type T is access Integer;
                |
        >>> named access type not allowed in pure unit

 8 lines: 1 error


Just guessing what your package is supposed to achieve,
have you considered using System.Address_To_Access_Conversions?






^ permalink raw reply	[relevance 5%]

* Re: Finding out minimal allocation unit
  @ 2007-04-06 12:38  4%         ` Stephen Leake
  0 siblings, 0 replies; 200+ results
From: Stephen Leake @ 2007-04-06 12:38 UTC (permalink / raw)


Stefan Bellon <sbellon@sbellon.de> writes:

> Are there examples of such a storage pool implementation around?

Here's the debug storage pool from SAL
(http://stephe-leake.org/ada/sal.html)

I wrote it to check for memory leaks in the SAL containers. It doesn't
resize the pool when it gets full, but you can add that using other
SAL containers :).

-- 
-- Stephe

--  Abstract:
--
--  A storage pool that keeps track of allocation and deallocation,
--  and allows queries. Used to verify storage management in container
--  tests. NOT task safe!
--
--  Copyright (C) 1997 - 1999, 2002 Stephen Leake.  All Rights Reserved.
--
--  This program is free software; you can redistribute it and/or
--  modify it under terms of the GNU General Public License as
--  published by the Free Software Foundation; either version 2, or
--  (at your option) any later version. This program is distributed in
--  the hope that it will be useful, but WITHOUT ANY WARRANTY; without
--  even the implied warranty of MERCHANTABILITY or FITNESS FOR A
--  PARTICULAR PURPOSE. See the GNU General Public License for more
--  details. You should have received a copy of the GNU General Public
--  License distributed with this program; see file COPYING. If not,
--  write to the Free Software Foundation, 59 Temple Place - Suite
--  330, Boston, MA 02111-1307, USA.

with System.Storage_Pools;
with System.Storage_Elements;
package Test_Storage_Pools is
   pragma Elaborate_Body; -- body depends on Ada.Text_IO;

   type String_Access_Constant_Type is access constant String;

   type Storage_Pool_Type
      (Pool_Size : System.Storage_Elements.Storage_Count;
       Name      : String_Access_Constant_Type) -- for debug messages
   is new System.Storage_Pools.Root_Storage_Pool with private;

   -----------
   --  Override Root_Storage_Pool operations

   procedure Allocate
      (Pool                     : in out Storage_Pool_Type;
       Storage_Address          :    out System.Address;
       Size_In_Storage_Elements : in     System.Storage_Elements.Storage_Count;
       Alignment                : in     System.Storage_Elements.Storage_Count);

   procedure Deallocate
      (Pool                     : in out Storage_Pool_Type;
       Storage_Address          : in     System.Address;
       Size_In_Storage_Elements : in     System.Storage_Elements.Storage_Count;
       Alignment                : in     System.Storage_Elements.Storage_Count);

   function Storage_Size (Pool : in Storage_Pool_Type) return System.Storage_Elements.Storage_Count;

   -----------
   --  New operations (alphabetical)

   function Allocate_Count (Pool : in Storage_Pool_Type) return Natural;
   --  Number of times Allocate has been called successfully.

   function Allocated_Elements (Pool : in Storage_Pool_Type) return Natural;
   --  Net allocated storage.

   procedure Check_Deallocated (Pool : in Storage_Pool_Type);
   --  If Allocated_Elements is not zero, print an error message and
   --  call Show_Storage.

   function Deallocate_Count (Pool : in Storage_Pool_Type) return Natural;
   --  Number of times Deallocate has been called.

   function Max_Allocated_Elements (Pool : in Storage_Pool_Type) return Natural;
   --  Max allocated storage, over lifetime of Pool.

   procedure Reset_Counts (Pool : in out Storage_Pool_Type);
   --  Reset Allocated and Deallocated counts to zero.

   procedure Set_Debug (Pool : in out Storage_Pool_Type; Debug : in Boolean);
   --  If Debug is True, Allocate, Deallocate, and Show_Storage print
   --  helpful messages to Standard_Output.

   procedure Show_Storage (Pool : in Storage_Pool_Type; Force_Debug : in Boolean := False);
   --  Print storage stats to Ada.Text_IO.Standard_Output, if
   --  Pool.Debug or Force_Debug is True.

private

   procedure Initialize (Pool : in out Storage_Pool_Type);

   type Block_Header_Type;
   type Block_Access_Type is access all Block_Header_Type;
   type Block_Header_Type is record
      Size : System.Storage_Elements.Storage_Count;
      Next : Block_Access_Type;
   end record;

   type Storage_Pool_Type
      (Pool_Size : System.Storage_Elements.Storage_Count;
       Name      : String_Access_Constant_Type)
   is new System.Storage_Pools.Root_Storage_Pool with
   record
      Debug                  : Boolean;
      Allocate_Count         : Natural;
      Deallocate_Count       : Natural;
      Allocated_Elements     : Natural;
      Max_Allocated_Elements : Natural;
      First_Free             : Block_Access_Type;
      Storage                : System.Storage_Elements.Storage_Array (1 .. Pool_Size);
      --  The first few elements of each free block contain the block
      --  header. Small requested blocks are padded up to at least the
      --  block header size. All blocks have alignment 8, to keep
      --  things simple.
   end record;

end Test_Storage_Pools;
--  Abstract:
--
--  see spec
--
--  Copyright (C) 1997 - 1999, 2002, 2003 Stephen Leake.  All Rights Reserved.
--
--  This program is free software; you can redistribute it and/or
--  modify it under terms of the GNU General Public License as
--  published by the Free Software Foundation; either version 2, or (at
--  your option) any later version. This program is distributed in the
--  hope that it will be useful, but WITHOUT ANY WARRANTY; without even
--  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
--  PURPOSE. See the GNU General Public License for more details. You
--  should have received a copy of the GNU General Public License
--  distributed with this program; see file COPYING. If not, write to
--  the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
--  MA 02111-1307, USA.

pragma License (GPL);

with Ada.Text_IO;
with System.Address_To_Access_Conversions;
with Ada.Exceptions;
package body Test_Storage_Pools is

   Block_Header_Size : constant System.Storage_Elements.Storage_Count :=
      System.Storage_Elements.Storage_Count (Block_Header_Type'Size /
                                             System.Storage_Elements.Storage_Element'Size);

   --  This would be cleaner if Address_To_Access_Conversions took the
   --  pointer type as parameter, instead of declaring it!
   package Address_To_Block_Access is new System.Address_To_Access_Conversions (Block_Header_Type);

   function To_Block_Access
      (Pool    : in Storage_Pool_Type;
       Address : in System.Address)
       return Block_Access_Type
   is
      use type System.Address;
   begin
      if Address < Pool.Storage (1)'Address or
         Address > Pool.Storage (Pool.Pool_Size)'Address
      then
         raise Storage_Error;
      end if;
      return Block_Access_Type (Address_To_Block_Access.To_Pointer (Address));
   end To_Block_Access;

   function To_Address (Value : in Block_Access_Type) return System.Address
   is begin
      return Address_To_Block_Access.To_Address (Address_To_Block_Access.Object_Pointer (Value));
   end To_Address;

   function Aligned_Address
      (Address     : in System.Storage_Elements.Integer_Address;
       Alignment   : in System.Storage_Elements.Storage_Count)
      return System.Storage_Elements.Integer_Address
      --  Adjust Address upwards to next Alignment.
   is
      use System.Storage_Elements;
      Aligned : constant Integer_Address := Address + Address rem Integer_Address (Alignment);
   begin
      return Aligned;
   end Aligned_Address;

   -----------
   --  Override Root_Storage_Pool operations

   procedure Allocate
      (Pool                     : in out Storage_Pool_Type;
       Storage_Address          :    out System.Address;
       Size_In_Storage_Elements : in     System.Storage_Elements.Storage_Count;
       Alignment                : in     System.Storage_Elements.Storage_Count)
   is
      pragma Unreferenced (Alignment);

      use System.Storage_Elements;
      use Ada.Exceptions;
      Block                : Block_Access_Type := Pool.First_Free;
      Block_Start          : Integer_Address;
      Remaining_Block      : Block_Access_Type;
      Aligned              : Integer_Address;
      Prev                 : Block_Access_Type := null;

      --  We store a block header in free'd blocks, to maintain the
      --  free block list. So each allocated block has to be at least
      --  that big.
      Padded_Size    : constant Storage_Count := Storage_Count'Max (Size_In_Storage_Elements, Block_Header_Size);
      Allocated_Size : Storage_Count;
   begin
      if Pool.Debug then
         Ada.Text_IO.Put_Line ("allocating " &
                               Storage_Count'Image (Size_In_Storage_Elements) &
                               " from " &
                               Pool.Name.all);
      end if;

      Find_Free_Fit :
      loop
         if Block = null then
            Raise_Exception (Storage_Error'Identity, "Allocate: pool full (or fragmented)");
         end if;
         exit Find_Free_Fit when Block.Size >= Padded_Size;
         Prev := Block;
         Block := Block.Next;
      end loop Find_Free_Fit;

      --  Aligned points past the end of the just-allocated block; it
      --  is the base of the block of remaining space.
      Block_Start := To_Integer (To_Address (Block));
      Aligned     := Aligned_Address
          (Address   => Block_Start + Integer_Address (Padded_Size),
           Alignment => 8);

      Allocated_Size  := Storage_Count (Aligned - Block_Start);

      --  Allocated_Size might be > Block.Size because of alignment.
      --  In that case, their is no remaining space, so it can't be a
      --  block.
      if Block.Size > Allocated_Size and then Block.Size - Allocated_Size >= Block_Header_Size then
         --  Ok, remaining space can be a real block. But check to see
         --  if it is outside the pool!
         begin
            Remaining_Block := To_Block_Access (Pool, To_Address (Aligned));
         exception
         when Storage_Error =>
            Raise_Exception (Storage_Error'Identity, "Allocate: pool full (or fragmented)");
         end;

         if Prev = null then
            --  Allocated from first free block.
            Pool.First_Free := Remaining_Block;
         else
            Prev.Next := Remaining_Block;
         end if;

         Remaining_Block.all :=
            (Size => Block.Size - Allocated_Size,
             Next => Block.Next);
      else
         --  Remaining space too small for a block. Just link to next
         --  free block.
         if Prev = null then
            --  Allocated from first free block.
            Pool.First_Free := Pool.First_Free.Next;
         else
            Prev.Next := Block.Next;
         end if;

      end if;

      Pool.Allocate_Count         := Pool.Allocate_Count + 1;
      --  Only track actual request in Allocated_Elements, since
      --  that's what will be deallocated.
      Pool.Allocated_Elements     := Pool.Allocated_Elements + Natural (Size_In_Storage_Elements);
      Pool.Max_Allocated_Elements := Natural'Max (Pool.Allocated_Elements, Pool.Max_Allocated_Elements);
      Storage_Address             := To_Address (Block);
   end Allocate;

   procedure Deallocate
      (Pool                     : in out Storage_Pool_Type;
       Storage_Address          : in     System.Address;
       Size_In_Storage_Elements : in     System.Storage_Elements.Storage_Count;
       Alignment                : in     System.Storage_Elements.Storage_Count)
   is
      pragma Unreferenced (Alignment);

      use System.Storage_Elements;
      Block : Block_Access_Type;
   begin
      if Pool.Debug then
         Ada.Text_IO.Put_Line ("deallocating " &
                               Storage_Count'Image (Size_In_Storage_Elements) &
                               " from " &
                               Pool.Name.all);
      end if;

      --  Store a free-list block header in the free'd block, add
      --  block to head of free list.

      Block := To_Block_Access (Pool, Storage_Address);

      Block.all :=
         (Size => Size_In_Storage_Elements,
          Next => Pool.First_Free);

      Pool.First_Free := Block;

      Pool.Deallocate_Count := Pool.Deallocate_Count + 1;
      Pool.Allocated_Elements := Pool.Allocated_Elements - Natural (Size_In_Storage_Elements);
   exception
   when Storage_Error =>
      Ada.Exceptions.Raise_Exception
         (Program_Error'Identity,
          "Address not from storage pool " & Pool.Name.all);
   end Deallocate;

   function Storage_Size (Pool : Storage_Pool_Type) return System.Storage_Elements.Storage_Count
   is begin
      return Pool.Pool_Size;
   end Storage_Size;

   -----------
   --  New operations

   function Allocate_Count (Pool : Storage_Pool_Type) return Natural
   is begin
      return Pool.Allocate_Count;
   end Allocate_Count;

   function Allocated_Elements (Pool : Storage_Pool_Type) return Natural
   is begin
      return Pool.Allocated_Elements;
   end Allocated_Elements;

   procedure Check_Deallocated (Pool : in Storage_Pool_Type)
   is begin
      if Pool.Allocated_Elements /= 0 then
         Ada.Text_IO.Put_Line ("Error : " & Pool.Name.all & " not deallocated");
         Show_Storage (Pool, Force_Debug => True);
      end if;
   end Check_Deallocated;

   function Deallocate_Count (Pool : Storage_Pool_Type) return Natural
   is begin
      return Pool.Deallocate_Count;
   end Deallocate_Count;

   function Max_Allocated_Elements (Pool : Storage_Pool_Type) return Natural
   is begin
      return Pool.Max_Allocated_Elements;
   end Max_Allocated_Elements;

   procedure Reset_Counts (Pool : in out Storage_Pool_Type)
   is begin
      Pool.Deallocate_Count := 0;
      Pool.Allocate_Count := 0;
      Pool.Max_Allocated_Elements := Pool.Allocated_Elements;
   end Reset_Counts;

   procedure Set_Debug (Pool : in out Storage_Pool_Type; Debug : in Boolean)
   is begin
      Pool.Debug := Debug;
   end Set_Debug;

   procedure Show_Storage (Pool : in Storage_Pool_Type; Force_Debug : in Boolean := False)
   is
      use Ada.Text_IO;
   begin
      if Pool.Debug or Force_Debug then
         Put_Line (Pool.Name.all & " : ");
         Put_Line ("Allocate_Count         => " & Natural'Image (Pool.Allocate_Count));
         Put_Line ("Deallocate_Count       => " & Natural'Image (Pool.Deallocate_Count));
         Put_Line ("Allocated_Elements     => " & Natural'Image (Pool.Allocated_Elements));
         Put_Line ("Max_Allocated_Elements => " & Natural'Image (Pool.Max_Allocated_Elements));
      end if;
   end Show_Storage;

   -----------
   --  Private operations

   procedure Initialize (Pool : in out Storage_Pool_Type)
   is
      use System.Storage_Elements;
      use Ada.Exceptions;
   begin
      if Pool.Pool_Size < Block_Header_Size then
         Raise_Exception (Storage_Error'Identity, "Initialize: pool_size < header_size");
      end if;

      Pool.Debug                  := False;
      Pool.Allocate_Count         := 0;
      Pool.Deallocate_Count       := 0;
      Pool.Allocated_Elements     := 0;
      Pool.Max_Allocated_Elements := 0;
      Pool.First_Free             := To_Block_Access
         (Pool,
          To_Address
            (Aligned_Address
               (Address   => To_Integer (Pool.Storage'Address),
                Alignment => 8)));
      Pool.First_Free.all         := (Pool.Pool_Size, null);
   end Initialize;

end Test_Storage_Pools;



^ permalink raw reply	[relevance 4%]

* Re: Fun with Tasking
  2007-03-28 16:55  0% ` Adam Beneschan
@ 2007-03-28 17:53  0%   ` mhamel_98
  0 siblings, 0 replies; 200+ results
From: mhamel_98 @ 2007-03-28 17:53 UTC (permalink / raw)


On Mar 28, 12:55 pm, "Adam Beneschan" <a...@irvine.com> wrote:
> On Mar 28, 8:53 am, mhamel...@yahoo.com wrote:
>
>
>
>
>
> > Below is sample code I made representing something I wanted to do with
> > a program, of course it doesn't work quite the way I would like.
> > Hopefully this sample doesn't cause eye (or brain) injury, it is more
> > symbolic than useful - the procedure "Exec" is, of course, really a
> > package (rather, several similar packages).
>
> > The problem is, how to "transport" a task?  As seen in the sample
> > below, I would like to use just a single address in the Control_Block
> > type, but it's never that simple, is it?  In actuality, how I get this
> > program in its full incarnation to work is to define the "test_task"s
> > in the acc_add_test part of the program.  I really don't like doing
> > this, as I mentioned, "exec" is representative of a family of several
> > different packages.  I would like the task definition to be local to
> > the "exec" pacakage(s), not all kludged together in acc_add_test,
> > which then requires all sorts of (ideally private) types being moved
> > out of the local "exec" packages into acc_add_test and then the
> > Control_Block record now has nearly a dozen different task pointers
> > stuffed into it, only one of which is going to be used at any given
> > time.
>
> > One last caveat, the Acc_Add_Test program should have *no* visibility
> > into the "exec" procedure/package.  The "exec" package(s), in fact,
> > "push" their procedures into the main program.  So is there something
> > simple I'm having a brain fart over in missing here, or is a complete
> > re-architecture required here?
>
> > with Text_Io;
> > with System;
> > with System.Address_To_Access_Conversions;
>
> > procedure Acc_Add_test is
>
> >   Exec_Count : constant Natural := 10;
>
> >   type Control_Block is
> >     record
> >       Task_Addr : System.Address;
> >     end record;
>
> >   type Mode_Type is (preprocess, process);
>
> >   procedure Exec (Mode : in     Mode_Type;
> >                   Cntl : in out Control_Block) is
>
> >     task type Test_Task is
> >       entry Start (Addr  : System.Address);
> >       entry Complete;
> >     end Test_Task;
>
> >     package Convert is new System.Address_To_Access_Conversions
> > (Test_Task);
> >     use Convert;
>
> >     task body Test_Task is
> >       Task_Ptr : Convert.Object_Pointer := null;
> >       Count    : Natural := 0;
> >     begin
> >       loop
> >         begin
> >           select
> >             accept Start (Addr : System.Address) do
> >               Task_Ptr := Convert.To_Pointer (Addr);
> >             end Start;
>
> >           or
> >             accept Complete do
> >               Count := Count + 1;
> >             end Complete;
> >             if Count = Exec_Count then
> >               Text_Io.Put_Line ("Completed All Tasks");
> >               abort Task_Ptr.all;
> >             end if;
> >           end select;
> >         end;
> >       end loop;
> >     end Test_Task;
>
> >   begin
> >     case Mode is
> >       when Preprocess =>
> >         declare
> >           Task_Ptr : Convert.Object_Pointer;
> >           Address  : System.Address;
> >         begin
> >           Task_Ptr := new Test_Task;
> >           Address := Convert.To_Address (Task_Ptr);
> >           Task_Ptr.Start (Address);
> >           Cntl.Task_Addr := Address;
> >         end;
>
> >       when Process =>
> >         declare
> >           Task_Ptr : Convert.Object_Pointer;
> >         begin
> >           Task_Ptr := Convert.To_Pointer (Cntl.Task_Addr);
> >           Task_Ptr.Complete;
> >         end;
> >     end case;
> >   end Exec;
>
> >   Controls : Control_Block;
>
> > begin
> >   Exec (Preprocess, Controls);
> >   for I in 1 .. Exec_Count loop
> >     Exec (Process, Controls);
> >   end loop;
> > end Acc_Add_Test;
>
> > Thanks for any input!
>
> Your main problem is that your tasks aren't going to live long
> enough.  When a task is created by an allocator, it depends on the
> "master" that declares the access type (or if the access type is a
> derived type, which isn't the case here, on the "ultimate ancestor" of
> the access type).  See RM section 9.3.  In this case, the master that
> declares the access type (Convert.Object_Pointer) is the Exec
> procedure.  This means that any task that you create using this access
> type depends on Exec, and Exec will not finish until any such tasks
> are completed.  It looks to me that you're trying to be able to call
> Exec multiple times, and have it start a task the first time and then
> use the same task the next time Exec is called.  This won't work if
> the task type is declared inside Exec, because any such tasks will not
> be allowed to keep running if Exec isn't running.  You'll need to move
> the task types (and the access type that points to the task type)
> outside Exec.
>
> This is the only thing that makes sense, anyway.  If your task type is
> declared inside Exec, the task body will have access to Exec's
> parameters and local variables; how then could it be possible for the
> task body to stay running while Exec isn't?
>
> I'm not real clear on what you're trying to do.  Your sample has
> "Exec" as a procedure, which makes it a master, but your discussion
> talks about "Exec" *packages*---and a package is not a master.  If you
> wanted an Exec *package* that declares its own task type and its own
> procedure to do the processing, but the task type isn't inside the
> procedure, then I suspect that you may be able to accomplish what
> you're trying to do; and there should be a way to keep certain things
> private without having to resort to hokeyness like System.Address or
> Address_To_Access_Conversions.  But I'm not up to trying to guess what
> you're trying to do; I'd recommend that you redo your example a bit to
> avoid the task dependence problem and then ask again if you still
> aren't sure how to do what you need to do.
>
>                                  -- Adam- Hide quoted text -
>
> - Show quoted text -

Thank you Adam.  While making this sample program a sneaking suspicion
started to creep up that I really didn't know what I was doing, and
you helped verify that suspicion.  What's really going on is I have a
number of tasks I'm going to run, and while themselves completely
independent of one another, they send updates to a single listening,
or collating, task.  That is the task at the heart of my initial
post.  My approach was to start up this collating task and give it's
pointer (or address) to the processing tasks.  This works fine if the
collating task definition is in the acc_add_test procedure and the
Control_Block has a pointer to that task within it.  However, I would
like the collating task definition to reside with the "exec" procedure/
package as the sample has it.  How would one declare and start up that
task, without any visibility into the package, just a procedure
pointer with a mode argument?  My (terribly flawed) idea was the
PreProcess element of the procedure would set that up, but as you
pointed out, the procedure would never exit while the task is
running.  So how to define the task and put it on "hold" until the
processing tasks can utilize it?  I don't expect it's possible without
incurring as much ugliness as the program has already, but I thought
I'd give it a try.  Thanks again =)




^ permalink raw reply	[relevance 0%]

* Re: Fun with Tasking
  2007-03-28 15:53  5% Fun with Tasking mhamel_98
@ 2007-03-28 16:55  0% ` Adam Beneschan
  2007-03-28 17:53  0%   ` mhamel_98
  0 siblings, 1 reply; 200+ results
From: Adam Beneschan @ 2007-03-28 16:55 UTC (permalink / raw)


On Mar 28, 8:53 am, mhamel...@yahoo.com wrote:

> Below is sample code I made representing something I wanted to do with
> a program, of course it doesn't work quite the way I would like.
> Hopefully this sample doesn't cause eye (or brain) injury, it is more
> symbolic than useful - the procedure "Exec" is, of course, really a
> package (rather, several similar packages).
>
> The problem is, how to "transport" a task?  As seen in the sample
> below, I would like to use just a single address in the Control_Block
> type, but it's never that simple, is it?  In actuality, how I get this
> program in its full incarnation to work is to define the "test_task"s
> in the acc_add_test part of the program.  I really don't like doing
> this, as I mentioned, "exec" is representative of a family of several
> different packages.  I would like the task definition to be local to
> the "exec" pacakage(s), not all kludged together in acc_add_test,
> which then requires all sorts of (ideally private) types being moved
> out of the local "exec" packages into acc_add_test and then the
> Control_Block record now has nearly a dozen different task pointers
> stuffed into it, only one of which is going to be used at any given
> time.
>
> One last caveat, the Acc_Add_Test program should have *no* visibility
> into the "exec" procedure/package.  The "exec" package(s), in fact,
> "push" their procedures into the main program.  So is there something
> simple I'm having a brain fart over in missing here, or is a complete
> re-architecture required here?
>
> with Text_Io;
> with System;
> with System.Address_To_Access_Conversions;
>
> procedure Acc_Add_test is
>
>   Exec_Count : constant Natural := 10;
>
>   type Control_Block is
>     record
>       Task_Addr : System.Address;
>     end record;
>
>   type Mode_Type is (preprocess, process);
>
>   procedure Exec (Mode : in     Mode_Type;
>                   Cntl : in out Control_Block) is
>
>     task type Test_Task is
>       entry Start (Addr  : System.Address);
>       entry Complete;
>     end Test_Task;
>
>     package Convert is new System.Address_To_Access_Conversions
> (Test_Task);
>     use Convert;
>
>     task body Test_Task is
>       Task_Ptr : Convert.Object_Pointer := null;
>       Count    : Natural := 0;
>     begin
>       loop
>         begin
>           select
>             accept Start (Addr : System.Address) do
>               Task_Ptr := Convert.To_Pointer (Addr);
>             end Start;
>
>           or
>             accept Complete do
>               Count := Count + 1;
>             end Complete;
>             if Count = Exec_Count then
>               Text_Io.Put_Line ("Completed All Tasks");
>               abort Task_Ptr.all;
>             end if;
>           end select;
>         end;
>       end loop;
>     end Test_Task;
>
>   begin
>     case Mode is
>       when Preprocess =>
>         declare
>           Task_Ptr : Convert.Object_Pointer;
>           Address  : System.Address;
>         begin
>           Task_Ptr := new Test_Task;
>           Address := Convert.To_Address (Task_Ptr);
>           Task_Ptr.Start (Address);
>           Cntl.Task_Addr := Address;
>         end;
>
>       when Process =>
>         declare
>           Task_Ptr : Convert.Object_Pointer;
>         begin
>           Task_Ptr := Convert.To_Pointer (Cntl.Task_Addr);
>           Task_Ptr.Complete;
>         end;
>     end case;
>   end Exec;
>
>   Controls : Control_Block;
>
> begin
>   Exec (Preprocess, Controls);
>   for I in 1 .. Exec_Count loop
>     Exec (Process, Controls);
>   end loop;
> end Acc_Add_Test;
>
> Thanks for any input!


Your main problem is that your tasks aren't going to live long
enough.  When a task is created by an allocator, it depends on the
"master" that declares the access type (or if the access type is a
derived type, which isn't the case here, on the "ultimate ancestor" of
the access type).  See RM section 9.3.  In this case, the master that
declares the access type (Convert.Object_Pointer) is the Exec
procedure.  This means that any task that you create using this access
type depends on Exec, and Exec will not finish until any such tasks
are completed.  It looks to me that you're trying to be able to call
Exec multiple times, and have it start a task the first time and then
use the same task the next time Exec is called.  This won't work if
the task type is declared inside Exec, because any such tasks will not
be allowed to keep running if Exec isn't running.  You'll need to move
the task types (and the access type that points to the task type)
outside Exec.

This is the only thing that makes sense, anyway.  If your task type is
declared inside Exec, the task body will have access to Exec's
parameters and local variables; how then could it be possible for the
task body to stay running while Exec isn't?

I'm not real clear on what you're trying to do.  Your sample has
"Exec" as a procedure, which makes it a master, but your discussion
talks about "Exec" *packages*---and a package is not a master.  If you
wanted an Exec *package* that declares its own task type and its own
procedure to do the processing, but the task type isn't inside the
procedure, then I suspect that you may be able to accomplish what
you're trying to do; and there should be a way to keep certain things
private without having to resort to hokeyness like System.Address or
Address_To_Access_Conversions.  But I'm not up to trying to guess what
you're trying to do; I'd recommend that you redo your example a bit to
avoid the task dependence problem and then ask again if you still
aren't sure how to do what you need to do.

                                 -- Adam






^ permalink raw reply	[relevance 0%]

* Fun with Tasking
@ 2007-03-28 15:53  5% mhamel_98
  2007-03-28 16:55  0% ` Adam Beneschan
  0 siblings, 1 reply; 200+ results
From: mhamel_98 @ 2007-03-28 15:53 UTC (permalink / raw)


Below is sample code I made representing something I wanted to do with
a program, of course it doesn't work quite the way I would like.
Hopefully this sample doesn't cause eye (or brain) injury, it is more
symbolic than useful - the procedure "Exec" is, of course, really a
package (rather, several similar packages).

The problem is, how to "transport" a task?  As seen in the sample
below, I would like to use just a single address in the Control_Block
type, but it's never that simple, is it?  In actuality, how I get this
program in its full incarnation to work is to define the "test_task"s
in the acc_add_test part of the program.  I really don't like doing
this, as I mentioned, "exec" is representative of a family of several
different packages.  I would like the task definition to be local to
the "exec" pacakage(s), not all kludged together in acc_add_test,
which then requires all sorts of (ideally private) types being moved
out of the local "exec" packages into acc_add_test and then the
Control_Block record now has nearly a dozen different task pointers
stuffed into it, only one of which is going to be used at any given
time.

One last caveat, the Acc_Add_Test program should have *no* visibility
into the "exec" procedure/package.  The "exec" package(s), in fact,
"push" their procedures into the main program.  So is there something
simple I'm having a brain fart over in missing here, or is a complete
re-architecture required here?

with Text_Io;
with System;
with System.Address_To_Access_Conversions;

procedure Acc_Add_test is

  Exec_Count : constant Natural := 10;

  type Control_Block is
    record
      Task_Addr : System.Address;
    end record;

  type Mode_Type is (preprocess, process);

  procedure Exec (Mode : in     Mode_Type;
                  Cntl : in out Control_Block) is

    task type Test_Task is
      entry Start (Addr  : System.Address);
      entry Complete;
    end Test_Task;

    package Convert is new System.Address_To_Access_Conversions
(Test_Task);
    use Convert;

    task body Test_Task is
      Task_Ptr : Convert.Object_Pointer := null;
      Count    : Natural := 0;
    begin
      loop
        begin
          select
            accept Start (Addr : System.Address) do
              Task_Ptr := Convert.To_Pointer (Addr);
            end Start;

          or
            accept Complete do
              Count := Count + 1;
            end Complete;
            if Count = Exec_Count then
              Text_Io.Put_Line ("Completed All Tasks");
              abort Task_Ptr.all;
            end if;
          end select;
        end;
      end loop;
    end Test_Task;

  begin
    case Mode is
      when Preprocess =>
        declare
          Task_Ptr : Convert.Object_Pointer;
          Address  : System.Address;
        begin
          Task_Ptr := new Test_Task;
          Address := Convert.To_Address (Task_Ptr);
          Task_Ptr.Start (Address);
          Cntl.Task_Addr := Address;
        end;

      when Process =>
        declare
          Task_Ptr : Convert.Object_Pointer;
        begin
          Task_Ptr := Convert.To_Pointer (Cntl.Task_Addr);
          Task_Ptr.Complete;
        end;
    end case;
  end Exec;

  Controls : Control_Block;

begin
  Exec (Preprocess, Controls);
  for I in 1 .. Exec_Count loop
    Exec (Process, Controls);
  end loop;
end Acc_Add_Test;

Thanks for any input!




^ permalink raw reply	[relevance 5%]

* Re: How to use Annex G.3 Vectors and Matrices in bindings to C arrays
  @ 2006-11-13 19:09  4%     ` Jeffrey R. Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey R. Carter @ 2006-11-13 19:09 UTC (permalink / raw)


Jerry wrote:
>>
> I'm afraid I'll have to apologize for not being accurate in my initial
> post. Indeed, I am not having any problems (as I erroneously claimed)
> with 1D arrays. The problem arises with 2D arrays, about which I
> pestered the list earlier. With further apologies for posting a bit
> more code that I would like, the following is a typical binding that I
> made in which it was necessary to gain access to 2D C arrays.

OK.

>     z              : in out Long_Float_Array_2D; -- height of surface
> at definition points

I don't see why this is in out.

>     package PL_Float_Pointers_Local is new Interfaces.C.Pointers
>        (Index              => Integer,
>         Element            => Long_Float,
>         Element_Array      => Long_Float_Array_1D,
>         Default_Terminator => 0.0);
>     use type PL_Float_Pointers_Local.Pointer; -- as in RM B.3.2
>     type PL_Float_Pointer_Array_Local is array (Integer range <>) of
> PL_Float_Pointers_Local.Pointer; -- array of pointers to Long_Floats
> which represent the first element of each row of z in C-land
> 
>     Index_Of_First_Column : Integer := z'First(2);
>     z_As_Pointers : PL_Float_Pointer_Array_Local (z'range(1));
> 
>     procedure
>     plmeshc_local(x : PL_Float_Array; y : PL_Float_Array; z :
> PL_Float_Pointer_Array_Local; nx : Integer; ny : Integer; opt :
> Integer; clevel : PL_Float_Array; nlevel : PLINT);
>     pragma Import(C, plmeshc_local, "c_plmeshc");
> 
> begin
>     for Index in z'range(1) loop
>         z_As_Pointers(Index) := z(Index, Index_Of_First_Column)'access;

To do this, Z must have aliased components. If you want to use the 
language-defined matrix type for this, you'll have to copy the values 
from Z into a local array. I'd probably do something like

type Row_Of_Z is new Vector (Z'range (2) );
pragma Convention (C, Row_Of_Z);

type Row_Ptr is access all Row_Of_Z;
pragma Convention (C, Row_Ptr);

type Z_For_C is array (Z'range (1) ) of Row_Ptr;
pragma Convention (C, Z_For_C);

Z_Ptr : Z_For_C;

for I in Z_Ptr'range loop
    Z_Ptr := new Row_Of_Z;

    for J in Z'Ptr (I)'range loop
       Z_Ptr (J) := Z (I, J);
    end loop;
end loop;

-- Call C with Z_Ptr
-- Free Z_Ptr

You could, of course, put the rows into an array of aliased Row_Of_Z and 
use the 'access of its elements to fill Z_Ptr. That would eliminate the 
need to free the pointers.

A messy way, that doesn't involve copying the elements, is to 
instantiate System.Address_To_Access_Conversions, and derive a 
convention-C access type from the access type defined in the 
instantiation. Then you take 'Address, convert it to an access type 
using To_Pointer, then convert that to your convention-C access type and 
store it in your array of pointers. (This is equivalent to using GNAT's 
'Unrestricted_Access, but portable.)

> The related array definitions are:
>     type Long_Float_Array_1D is array (Integer range <>) of aliased
> Long_Float;
>     type Long_Float_Array_2D is array (Integer range <>, Integer range
> <>) of aliased Long_Float;
> 
> The "thin" binding Ada procedure plmeshc is defined:
>     procedure plmeshc(x : PL_Float_Array; y : PL_Float_Array; z :
> PL_Float_Array_2D; nx : PLINT; ny : PLINT; opt : PLINT;
>           clevel : PL_Float_Array; nlevel : PLINT);
>     pragma Import(C, plmeshc, "c_plmeshc");

The declarations of the PL_... types would be useful, too, though we can 
make a good guess from the C.

-- 
Jeff Carter
"Now go away or I shall taunt you a second time."
Monty Python & the Holy Grail
07



^ permalink raw reply	[relevance 4%]

* Re: To collection (GNAT bug)
  2006-10-02  3:08  5%         ` Jeffrey R. Carter
@ 2006-10-02 13:02  0%           ` Frank J. Lhota
  0 siblings, 0 replies; 200+ results
From: Frank J. Lhota @ 2006-10-02 13:02 UTC (permalink / raw)


Jeffrey R. Carter wrote:
> Frank J. Lhota wrote:
> 
> Since you can instantiate System.Address_To_Access_Conversions with type 
> String, I don't see how its access type can be any different than one 
> you declare yourself.
> 

It can have pragmas and representation clauses needed to make sure that 
the To_Pointer and To_Address functions are meaningful. For example, the 
GNAT version of this package includes the representation clause

      for Object_Pointer'Size use Standard'Address_Size;

which precludes implementing Object_Pointer as a "fat" pointer.



^ permalink raw reply	[relevance 0%]

* Re: To collection (GNAT bug)
  @ 2006-10-02  3:08  5%         ` Jeffrey R. Carter
  2006-10-02 13:02  0%           ` Frank J. Lhota
  0 siblings, 1 reply; 200+ results
From: Jeffrey R. Carter @ 2006-10-02  3:08 UTC (permalink / raw)


Frank J. Lhota wrote:
> 
> The reason why Address_To_Access_Conversions declares its own access type is 
> to make sure that the access values used in these conversions are not "fat 
> pointers". In other words, this design was chosen precisely to avoid the 
> sort of problems exhibited in Test_String_Ptr.

Since you can instantiate System.Address_To_Access_Conversions with type 
String, I don't see how its access type can be any different than one 
you declare yourself.

-- 
Jeff Carter
"Monsieur Arthur King, who has the brain of a duck, you know."
Monty Python & the Holy Grail
09



^ permalink raw reply	[relevance 5%]

* Re: generic package with procedure paramter gives "not subtype conformant with declaration"
  @ 2006-10-01 21:26  4%       ` cl1
  0 siblings, 0 replies; 200+ results
From: cl1 @ 2006-10-01 21:26 UTC (permalink / raw)



Jeffrey R. Carter wrote:
> cl1 wrote:
> > <snip>
>
> The problem is that System.Address is not guaranteed to be the same as a
> C pointer, so using it to interface with C makes your code compiler
> dependent. In all versions of GNAT that I've used and bothered to check,
> System.Address has been the same as a C pointer, but that could change
> at any time.

I did not know this. I am forever learning, it seems.

>
> For types, any convention-C access type will work for a void pointer
> when the values come from C and are never dereferenced by the Ada. I
> generally use "access all Integer" for that case, though some people
> prefer to have a void type to designate:
>
> type Void is null record;
> type Void_Ptr is access all Void;
> pragma Convention (C, Void_Ptr);

This is a very good concept. Is there a mechanism in ada to allow:

My_Void_Ptr := My_C_Float'Access;

where My_C_Float could be My_New_Type or My_Integer, etc.
I ask, because my code does this and i was using the System.Address as
a catch all. Once i store the access in the pointer i no longer need to
know
what type it is. I just need the reference to pass to the C code. For
instance:

package avcall is
type Argument is
  record
    Value_Address : System.Address;
  end record;
end avcall;

generic
  type Any_Type is private;
package avcall.register_type
  package Any_Type_Conversion is new
System.Address_To_Access_Conversions(Any_Type);
  type Argument_Instance is
    record
      Instance_Value : Any_Type_Conversion.Object_Pointer;
    end record;
    function Concat(AList : Var_Args; Arg : Any_Type) return Var_Args
is
      Info : Argument_Instance;
    begin
      Info.Instance_Value := Arg;
      Info.Value_Address :=
Any_Type_Conversion.To_Address(Info.Instance_Value);
      return AList;
    end;
end avcall.register_type;

This is how i'm currently doing things. How would i change my
Argument.Value_Address from System.Address type to something like the
Void_Ptr type you proposed? So that i can change:

Info.Value_Address :=
Any_Type_Conversion.To_Address(Info.Instance_Value);

to work with the Void_Ptr type.


>
> Since values of Void_Ptr are never dereferenced, the designated type
> doesn't matter.
>
> For subprograms, it's more complicated because you have to match the
> subprogram parameter and return type profile. In your case, though
> (IIRC), the subprograms all have the same profile (that of your generic
> formal subprogram), so the use of a convention-C access type seems to be
> possible.
>
> > i'm using GPS which has gcc version 3.4.6 on mac os x 10.4.8
>
> GPS is an IDE, not a compiler, but gcc 3.4.6 is; it's an Ada-95
> compiler. The compiler version is of interest because Ada 95's
> accessibility rules differ from Ada 0X's.
>
> > I agree with you.
> > However, I am confused about this. The procedure could be declared
> > anywhere. How
> > does the compiler know what scope the procedure that is supplied to the
> > generic package is in? I mean can it ever know? If not, that means
> > there
> > is no foreseeable fix to this issue from my point of view.
>
> The compiler can't know the scope of the actual procedure in general;
> that's why you can never store the 'access of a generic formal
> procedure. The language assumes the worst case for safety.

to quote another post in this thread:

-And you wanted to do Av_Param_Instance'Access inside the generic?
-That won't work, because the compiler can't check the rules about
-X'Access, because it doesn't know enough about the actual parameter
-passed to Av_Param_Instance.  The accessibility rules come to mind.
-Also, the fact that you can't do X'Access if X is intrinsic

Now that i know that is the rule. I not only understand what was
causing
the problem, but why.

>
> --
> Jeff Carter
> "Monsieur Arthur King, who has the brain of a duck, you know."
> Monty Python & the Holy Grail
> 09




^ permalink raw reply	[relevance 4%]

* Re: To collection (GNAT bug)
  2006-10-01  1:21  5% ` Jeffrey R. Carter
@ 2006-10-01  8:00  0%   ` Dmitry A. Kazakov
    0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2006-10-01  8:00 UTC (permalink / raw)


On Sun, 01 Oct 2006 01:21:22 GMT, Jeffrey R. Carter wrote:

> Dmitry A. Kazakov wrote:
>> The following does not work in GCC 4.1.1 (20060525), as well as in 3.15p
> 
> Why should it? There's no guarantee that unchecked conversion between 
> access values and System.Address will give meaningful results.

See ARM 13.9 (17), which requires reversibility of Unchecked_Conversion.
That is clearly violated in the example given. Though it is legal not to
provide address to access type conversion through Unchecked_Conversion, it
is still illegal to provide it wrong.

> Use System.Address_To_Access_Conversions.

Address_To_Access_Conversions serves a different purpose. It declares a new
access type, moreover it is a general access type.

BTW, when Address_To_Access_Conversions is composed with an access to
access type conversion, the problem persists (it is a bug after all (:-))
Replace To_Ptr and To_Addr with:

   package Clutter is new Address_To_Access_Conversions (String);
   function To_Addr (X : Ptr) return Address is
   begin
      return Clutter.To_Address (X.all'Unchecked_Access);
   end To_Addr;
   function To_Ptr (X : Address) return Ptr is
      function Cast is
         new Ada.Unchecked_Conversion (Clutter.Object_Pointer, Ptr);
   begin
      return Cast (Clutter.To_Pointer (X));
   end To_Ptr;

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



^ permalink raw reply	[relevance 0%]

* Re: To collection (GNAT bug)
  @ 2006-10-01  1:21  5% ` Jeffrey R. Carter
  2006-10-01  8:00  0%   ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Jeffrey R. Carter @ 2006-10-01  1:21 UTC (permalink / raw)


Dmitry A. Kazakov wrote:
> The following does not work in GCC 4.1.1 (20060525), as well as in 3.15p

Why should it? There's no guarantee that unchecked conversion between 
access values and System.Address will give meaningful results. Use 
System.Address_To_Access_Conversions.

-- 
Jeff Carter
"Sir Lancelot saves Sir Gallahad from almost certain temptation."
Monty Python & the Holy Grail
69



^ permalink raw reply	[relevance 5%]

* generic package with procedure paramter gives "not subtype conformant with declaration"
@ 2006-09-30 21:20  5% cl1
    0 siblings, 1 reply; 200+ results
From: cl1 @ 2006-09-30 21:20 UTC (permalink / raw)


I don't understand why i can't pass Av_Param to the generic package (in
test_call_avcall_register_type.adb) and have its 'Access attribute used
in Concat (the offending code in avcall-register_type.adb)?

i'm getting the following error:
$ gnatmake -gnatc ./Ada_Source/test_avcall_register_type.adb
gcc -c -I./Ada_Source/ -gnatc -I-
./Ada_Source/test_avcall_register_type.adb
gcc -c -I./Ada_Source/ -gnatc -I- ./Ada_Source/avcall.adb
gcc -c -I./Ada_Source/ -gnatc -I- ./Ada_Source/avcall-register_type.adb
avcall-register_type.adb:13:34: not subtype conformant with declaration
at avcall.ads:37
avcall-register_type.adb:13:34: formal subprograms not allowed
gnatmake: "./Ada_Source/avcall-register_type.adb" compilation error

on this code:
<avcall.ads>
with System; use System;
package avcall is
	-- <snip>
	----------------------------------------------------------------------------
	-- This exeption is thrown when you try to add more than Max_Args to
the
	-- Var_Args type
	Max_Arg_Limit_Surpassed : exception;
	----------------------------------------------------------------------------
	-- The maximum number of arguments that can be used by avcall
	Max_Args : constant := 50;
	----------------------------------------------------------------------------
	-- this is the number of arguments in the Var_Args list
	subtype Arg_Count is Natural range 0..Max_Args;
	----------------------------------------------------------------------------
	-- This is the range used by the Var_Args list
	subtype Arg_Range is Natural range 1..Max_Args;
	----------------------------------------------------------------------------
	-- this represents an argument held in the Arg_List
	type Argument is tagged
		record
		------------------------------------------------------------------------
		-- This holds the correct av_<type> c function to call.
		Av_Param : access procedure(Av_List : System.Address;
									Value : System.Address);
		------------------------------------------------------------------------
		-- This holds the address of the value. This is assigned by the child
		-- type of this type in the Register_Type package during the
		-- Initialize procedure call of the child type.
		Value_Address : System.Address;
		------------------------------------------------------------------------
		end record;
	----------------------------------------------------------------------------
	-- This type is used by the Var_Args type to hold all of the
arguments.
	type Arg_List is array(Arg_Range range <>) of Argument;
	----------------------------------------------------------------------------
	-- This is the Var_Args type. This is used to hold all of the
arguments to
	-- the c function (the ... and all the arguments before that).
	-- The Start_Var_Args, "&", and Prepend methods and functions are used
to
	-- add arguments to Var_Args.
	type Var_Args is
		record
		------------------------------------------------------------------------
		-- this is a pointer to the c data type that makes this work.
		-- Av_List_Malloc and Av_List_Free (defined in the body) are used to
		-- obtain the reference and free it respectivly
		Av_List : System.Address;
		------------------------------------------------------------------------
		-- This is the number of arguments in the Arg_List
		Count : access Arg_Count;
		------------------------------------------------------------------------
		-- This is what holds all of the arguments.
		List : access Arg_List := new Arg_List(Arg_Range'Range);
		------------------------------------------------------------------------
		end record;
	----------------------------------------------------------------------------
	-- <snip>
end avcall;

<avcall-register_type.ads>
with System.Address_To_Access_Conversions;
with System; use System;
--------------------------------------------------------------------------------
generic
	type Any_Type is private;
	with procedure Av_Param_Instance(AList : System.Address; Value :
System.Address);
package avcall.register_type is
	----------------------------------------------------------------------------
	package Any_Type_Conversion is new
System.Address_To_Access_Conversions(Any_Type);
	----------------------------------------------------------------------------
	type Argument_Instance is new Argument with
		record
			Instance_Value : Any_Type_Conversion.Object_Pointer;
		end record;
	----------------------------------------------------------------------------
	function Concat(AList : Var_Args; Arg : Any_Type) return Var_Args;
	----------------------------------------------------------------------------
end avcall.register_type;

<avcall-register_type.adb>
package body avcall.register_type is
	----------------------------------------------------------------------------
	-- Adds the value in Arg to the next Var_Args.List
	function Concat(AList : Var_Args; Arg : Any_Type) return Var_Args is
		Info : Argument_Instance;
	begin
		Info.Av_Param := Av_Param_Instance'Access;
		Info.Instance_Value.all := Arg;
		Info.Value_Address :=
Any_Type_Conversion.To_Address(Info.Instance_Value);
		AList.Count.all := AList.Count.all + 1;
		AList.List(AList.Count.all) := Argument(Info);
		return AList;
	end Concat;
	----------------------------------------------------------------------------
end avcall.register_type;

<test_avcall_register_type.adb>
with avcall; use avcall;
with avcall.register_type;
with Ada.Text_IO; use Ada.Text_IO;
with System; use System;
--------------------------------------------------------------------------------
procedure test_avcall_register_type is
	procedure Av_Param(AList : System.Address; Value : System.Address) is
	begin
		null;
	end Av_Param;
	package Int_Registered is new avcall.register_type(Integer, Av_Param);
begin
	Put_Line("FOO");
end test_avcall_register_type;

<offending code>
--avcall-register_type.adb:13:34: not subtype conformant with
declaration at avcall.ads:37
--avcall-register_type.adb:13:34: formal subprograms not allowed
		Info.Av_Param := Av_Param_Instance'Access;
<end of code post>

I don't understand why i can't pass Av_Param to the generic package (in
test_call_avcall_register_type.adb) and have its 'Access attribute used
in Concat (the offending code in avcall-register_type.adb)?




^ permalink raw reply	[relevance 5%]

* Re: A novel design of linked lists
  2006-09-19 20:09  2% ` Adam Beneschan
@ 2006-09-20  8:35  0%   ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2006-09-20  8:35 UTC (permalink / raw)


On 19 Sep 2006 13:09:44 -0700, Adam Beneschan wrote:

> Dmitry A. Kazakov wrote:
>> [ It seems to me that some people have an impression that I am looking for
>> something extraordinary when asking for the object address, so I feel
>> necessary to provide an elaborated example where it were needed. ]
>>
>> Let's consider referential double-linked lists as an example. The drawbacks
>> of the Ada.Containers design are obvious. A typical design of such lists in
>> other languages would be adding Prev, Next pointers to the elements. Note
>> also, that we wished to have linked lists of elements which might
>> participate in many lists simultaneously. We also liked to statically check
>> the types of such lists, so that paths in different lists could never
>> converge.
>>
>> There are two ways to do add links Prevs and Nexts. One of them is to do it
>> upon inheritance. Another is by using new elements containing pointers to
>> the "true" elements.
>>
>> 1. The variant with inheritance is not an option in current Ada, because of
>> lack of MI. Even with MI it faces the problem that links has to be added to
>> the base type. That would require downcasting later, all over the program.
>> Adding links in the leaves of the type hierarchy would break it apart and
>> also freeze the types for future derivation. Ad-hoc supertypes could help,
>> but, firstly, they are not supported and, secondly, they barely could have
>> referential semantics. So the elements will require copying.
>>
>> 2. The variant with pointers is not a solution at all, because, honestly,
>> it would be a list of pointers rather than of the elements.
> 
> I'll have to admit that I don't see what "problem" you have that this
> isn't a solution to.  In fact, I'm not really clear on why it's
> important to you to adopt the approach you're adopting; your
> explanation is pretty sketchy.

That was an example illustrating the case - a need to get an intact object
address.

As for possible application areas of double-linked lists, honestly, I don't
know what sort of explanation you liked to hear from me...

> Part of my problem is that you seem to want to define a type, Item_Ptr,
> that gives you more than it's supposed to give you.  Your generic
> declares
> 
>    type Item_Ptr is access List_Type_Item;
> 
> where List_Type_Item is whatever type you're making a list out of.  I
> see a type like this, and I think it's just an access to the
> List_Type_Item, but there's actually additional baggage in this
> pointer, i.e. a "next" and a "previous" pointer.  So if I see code that
> calls Next on this Item_Ptr, my first thought is "Whooaa!  Item_Ptr is
> just an access to my Employee record, so where the heck is it going to
> get a pointer to another Employee?" It would be pretty confusing to me.

[ It would be nice to have user-defined fat access types, but,
unfortunately, Ada does not provide them. Ergo, you are not allowed to
think that way in Ada. You have to - "Aha, there must something in the
target object that allows this Next." ]

Item_Ptr is an ADT.

> Personally, if I'm going to have something that contains additional
> information, I'd prefer that it be a different type.

which is Item_Ptr. I hope that you'd agree that "contains additional
information" does not necessarily imply *physically* contains the
information.

> The need for
> downcasting, type conversion, or a Deref function in your generic that
> takes an Item_Ptr and returns the dereferenced item that I would use
> instead of .all, doesn't bother me at all.  So I don't see what problem
> there is that needs solving.

Hmm, if you consider a need in downcasting and explicit type conversions of
elements of a double-linked lists as OK, then we are on different pages.

> Plus, you introduce a problem.  Assuming the actual for List_Type_Item
> is T, you've defined Item_Ptr as an access to T; what happens if
> somewhere else in the program, there is another type that is also an
> access to T?  The language will let you convert between the two access
> types, but the result would be an absolute disaster.  But I just know
> that someone who doesn't really understand that Item_Ptr isn't just an
> access to T is going to try it.

No, it is illegal in Ada. You cannot freely convert between pool-specific
access types. Item_Ptr is pool-specific. You can convert it to a general
access type, but that would make no harm. A backward conversion is again
impossible. It does not leak, Ada is a safe language. [ I don't consider
Unchecked_Conversion issues, here. ]

> Put simply, you're trying to trick your Ada compiler into allowing
> programmers to use Ada syntax to write code in some other language than
> Ada, and someone who looks at the Ada code and assumes it's Ada is
> likely to be pretty darn confused.

Hmm, this definitely applies to the dopes of String objects. Is String Ada?

> Anyway, now that I've given you my tirade on why I think this is a bad
> approach, I'm going to give you an idea of how you might implement your
> bad approach.  The problem with your Next function is that if
> List_Item_Type is an unconstrained array, there will be extra data
> between the thing Item_Ptr points to and the Item_Header.  Since you've
> already admitted that this is going to be highly
> implementation-dependent, then you can probably assume that the size of
> this extra data is going to be the same always (for a given
> List_Item_Type), and then all you have to do is figure out what that
> size is the first time Next [or some other routine] is called.  Declare
> a variable in your package body:
> 
>     Dope_Offset : Storage_Offset := -1;
> 
> Fix your Allocate so that it saves the resulting Storage_Address in
> some global Global_Storage_Address in the package body before it
> returns.  Inside Next:
>
>    X : Item_Ptr;
>    ...
>    if Dope_Offset = -1 then
>      X := new List_Item_Type' (Item.all);
>      Dope_Offset := To_Address(X) - Global_Storage_Address;
>      Free(X);
>   end if;
> 
> where To_Address is from an instance of
> System.Address_To_Access_Conversions.  Now once Dope_Offset has been
> set up, you can use it as an offset and subtract it from your
> From_Item_Ptr calls.  

Unfortunately this will not work, because List_Item_Type is indefinite
limited. Then, construction - destruction of an item might be highly
undesirable, when Item is something like Device_Driver or DB_Connection.

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



^ permalink raw reply	[relevance 0%]

* Re: A novel design of linked lists (was: Address of an object)
  @ 2006-09-19 20:09  2% ` Adam Beneschan
  2006-09-20  8:35  0%   ` A novel design of linked lists Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Adam Beneschan @ 2006-09-19 20:09 UTC (permalink / raw)


Dmitry A. Kazakov wrote:
> [ It seems to me that some people have an impression that I am looking for
> something extraordinary when asking for the object address, so I feel
> necessary to provide an elaborated example where it were needed. ]
>
> Let's consider referential double-linked lists as an example. The drawbacks
> of the Ada.Containers design are obvious. A typical design of such lists in
> other languages would be adding Prev, Next pointers to the elements. Note
> also, that we wished to have linked lists of elements which might
> participate in many lists simultaneously. We also liked to statically check
> the types of such lists, so that paths in different lists could never
> converge.
>
> There are two ways to do add links Prevs and Nexts. One of them is to do it
> upon inheritance. Another is by using new elements containing pointers to
> the "true" elements.
>
> 1. The variant with inheritance is not an option in current Ada, because of
> lack of MI. Even with MI it faces the problem that links has to be added to
> the base type. That would require downcasting later, all over the program.
> Adding links in the leaves of the type hierarchy would break it apart and
> also freeze the types for future derivation. Ad-hoc supertypes could help,
> but, firstly, they are not supported and, secondly, they barely could have
> referential semantics. So the elements will require copying.
>
> 2. The variant with pointers is not a solution at all, because, honestly,
> it would be a list of pointers rather than of the elements.

I'll have to admit that I don't see what "problem" you have that this
isn't a solution to.  In fact, I'm not really clear on why it's
important to you to adopt the approach you're adopting; your
explanation is pretty sketchy.

Part of my problem is that you seem to want to define a type, Item_Ptr,
that gives you more than it's supposed to give you.  Your generic
declares

   type Item_Ptr is access List_Type_Item;

where List_Type_Item is whatever type you're making a list out of.  I
see a type like this, and I think it's just an access to the
List_Type_Item, but there's actually additional baggage in this
pointer, i.e. a "next" and a "previous" pointer.  So if I see code that
calls Next on this Item_Ptr, my first thought is "Whooaa!  Item_Ptr is
just an access to my Employee record, so where the heck is it going to
get a pointer to another Employee?"  It would be pretty confusing to
me. Personally, if I'm going to have something that contains additional
information, I'd prefer that it be a different type.  The need for
downcasting, type conversion, or a Deref function in your generic that
takes an Item_Ptr and returns the dereferenced item that I would use
instead of .all, doesn't bother me at all.  So I don't see what problem
there is that needs solving.

Plus, you introduce a problem.  Assuming the actual for List_Type_Item
is T, you've defined Item_Ptr as an access to T; what happens if
somewhere else in the program, there is another type that is also an
access to T?  The language will let you convert between the two access
types, but the result would be an absolute disaster.  But I just know
that someone who doesn't really understand that Item_Ptr isn't just an
access to T is going to try it.

Put simply, you're trying to trick your Ada compiler into allowing
programmers to use Ada syntax to write code in some other language than
Ada, and someone who looks at the Ada code and assumes it's Ada is
likely to be pretty darn confused.

Anyway, now that I've given you my tirade on why I think this is a bad
approach, I'm going to give you an idea of how you might implement your
bad approach.  The problem with your Next function is that if
List_Item_Type is an unconstrained array, there will be extra data
between the thing Item_Ptr points to and the Item_Header.  Since you've
already admitted that this is going to be highly
implementation-dependent, then you can probably assume that the size of
this extra data is going to be the same always (for a given
List_Item_Type), and then all you have to do is figure out what that
size is the first time Next [or some other routine] is called.  Declare
a variable in your package body:

    Dope_Offset : Storage_Offset := -1;

Fix your Allocate so that it saves the resulting Storage_Address in
some global Global_Storage_Address in the package body before it
returns.  Inside Next:

   X : Item_Ptr;
   ...
   if Dope_Offset = -1 then
     X := new List_Item_Type' (Item.all);
     Dope_Offset := To_Address(X) - Global_Storage_Address;
     Free(X);
  end if;

where To_Address is from an instance of
System.Address_To_Access_Conversions.  Now once Dope_Offset has been
set up, you can use it as an offset and subtract it from your
From_Item_Ptr calls.  

                         -- Adam




^ permalink raw reply	[relevance 2%]

* binding to C:  popen
@ 2006-02-21 14:37  6% Poul-Erik Andreasen
  0 siblings, 0 replies; 200+ results
From: Poul-Erik Andreasen @ 2006-02-21 14:37 UTC (permalink / raw)


Hi

i am trying to make a biding to the C function popen, it goes like this:

with System.Address_To_Access_Conversions;
with Interfaces.C_Streams;

package Pipe_Pkg is

    subtype Command_Pipe is Interfaces.C_Streams.FILEs;

    procedure Pipe_Open (Pipe    : in out Command_Pipe;
                         Command : in  String);
private

   function To_C (Input : in String) return Interfaces.C_Streams.Chars;

end Pipe_Pkg;


package body Pipe_Pkg is


    procedure Pipe_Open
      (Pipe    : in out Command_Pipe;
       Command : in  String)
    is
       use Interfaces.C_Streams;
       function C_Popen (C_Command : Chars;
                         C_Type    : Chars) return Command_Pipe;

       pragma Import (C, C_Popen, "popen");

    begin
       Pipe := C_Popen ((To_C (Command)), To_C ("w"));
    end Pipe_Open;

    function To_C (Input : in String) return Interfaces.C_Streams.Chars 


    is
      package String_Conversion is
         new System.Address_To_Access_Conversions (String);

      String_Pointer : String_Conversion.Object_Pointer :=
                          new String'(Input & ascii.nul);
    begin
       return String_Conversion.To_Address (String_Pointer);
    end;


end Pipe_Pkg;



This ictually going as it is suppose to, but i would like set in an 
exception if the piping dosn't have succes. Acording to the C manual
popen returns null if it fails. But how do i test on that in the FILEs type?







^ permalink raw reply	[relevance 6%]

* Re: Problem with "limited with" in a *real* application
  2005-10-14 15:03  3%           ` Lucretia
@ 2005-10-14 23:47  0%             ` Randy Brukardt
  0 siblings, 0 replies; 200+ results
From: Randy Brukardt @ 2005-10-14 23:47 UTC (permalink / raw)


"Lucretia" <lucretia9@lycos.co.uk> wrote in message
news:1129302185.489627.266900@g47g2000cwa.googlegroups.com...
> Inside the Sizer package I have an Add procedure which adds a
> Window_Type (e.g. Button_Type, Check_Box_Type, etc) into the derived
> type to Self, which is a Sizer_Type derived type. So, I want (ideally)
> to minimize the casting, so I changed the Window type to take a
> Window_Type'Class so that any type can be accepted. Now, this forces me
> to cast the Self type in the New_Minimal_Frame procedure (See the
> Add's) to the base Sizer_Type. Now in C++ the Add function can be
> overridden (as in the case of wxGridBagSizer and they're not virtuals)
> so in the case of mapping to Ada in this current form, the programmer
> must know which Add to use, i.e. which cast to use, which is fair
> enough, but surely it would be easier to let the compiler decide?
> Should I use a 'Class type here?

Probably not. If you need overriding and/or dispatching somewhere, you'll
want to avoid 'Class. My rule of thumb is that primitives should be specific
unless you're absolutely certain that you'll never want to override them in
any child types. (And when is that true?).

You have to use a (view) type conversion (what you've been calling a "cast")
to all the operations of the parent type. That's just the way you write that
in Ada. OTOH, it's usually not necessary to do that for most operations,
because they are inherited, and you can just call them for the type itself.

> So, with this in mind, it's a possibility that all of the wxAda
> primitives could take 'Class types so that no casting is ever needed,
> but surely this is wrong, Ada-wise?

It's probably wrong, but I'd have to see your entire design to know for
sure. Which I'd rather not do...

> The format of the following code might get a bit screwed by Google:
>
> <wx.Core.Sizer>
> package wx.Core.Sizer is
>
>   -- This is the actual type (wxSizer) we are creating here.
>   type Sizer_Type is new Object_Type with private;

-- All of the (primitive) operations of the parent type are inherited here,
-- so you can call them without using any type conversions.

>   procedure Add(
>     Self       : in out Sizer_Type;
>     Window     : in Window_Type'Class;
>     Proportion : in Sizer_Proportion_Type := 0;
>     Flags      : in Sizer_Flag_Type := 0;
>     Border     : in Integer := 0);
>
> end wx.Core.Sizer;
> </wx.Core.Sizer>
>
> <Minimal_Frame>
> package body Minimal_Frame is
>
>   procedure New_Minimal_Frame(Self : in out Minimal_Frame_Type) is
>
>     procedure Button_Connect is new
> wxEvtHandler.Connect(Command_Event_Function);
>     procedure Check_Box_Connect is new
> wxEvtHandler.Connect(Command_Event_Function);
>     procedure My_Test_Connect is new
> wxEvtHandler.Connect(On_My_Test_Function);
>     procedure Slider_Connect is new
> wxEvtHandler.Connect(Scroll_Event_Function);
>     procedure Size_Connect is new
> wxEvtHandler.Connect(Size_Event_Function);
>     procedure Paint_Connect is new
> wxEvtHandler.Connect(Paint_Event_Function);
>
>     Field_Widths : Field_Widths_Array(0 .. 1) := (-3, -1);
>
>     package Address_To_Object is new
> System.Address_To_Access_Conversions(Minimal_Frame_Type);
>     use Address_To_Object;
>
>   begin
>
>     New_Frame(Self, ID_ANY, "Minimal wxAda App", Point_Type'(400,
> 300));
>     Text_IO.Put_Line("Self'Access : " &
> System.Address_Image(To_Address(Self'Access)));
>
>     New_Panel(Self.Panel, Window_Type(Self), Id_Any);

Here, the second parameter of New_Panel probably should be class-wide. A
subprogram with two specific different tagged types as parameters is almost
always wrong. (Dmitry will tell you why in excrutating details if you want
to know. :-)

>     New_Validator(Self.Validator);
>
>     New_Button(Self.Button, Window_Type(Self.Panel),
> Id_Type(Id_Test_Button), "Test &Button", Default_Position,
> Default_Size, 0);

Same is true here. In Claw, the Create routines look something like:

     procedure Create (Button : in out Button_Type;
                                  Parent : in out Root_Window_Type'Class;
                                  Size : in Size_Type;
                                  Position : in Point_Type;
                                  ....);

>     Set_Validator(Window_Type(Self.Button), Self.Validator);

Presuming that this is an operation on the root window type, you should be
able to just call this (a Button will have inherited it).

       Set_Validator (Self.Button, Self.Validator);

(or, in C++-like notation in Ada 200Y:)
      Self.Button.Set_Validator (Self.Validator);

The latter notation avoids the need for use-clauses.

If this isn't an operation on the root window type, then there is something
wrong with your design. Either the prefix should be class-wide (and no type
conversion is needed), or it should be primitive so it is inherited (and
thus can be overridden) by other tagged types (window classes).

>     New_Check_Box(Self.Check_Box, Window_Type(Self.Panel), Id_Any,
> "Test &Check Box", Style => Check_Box_Align_Right);
>     New_Slider(Self.Slider, Window_Type(Self.Panel), Id_Any, 50, 0,
> 100, Style => Slider_Horizontal or Slider_Labels);
>     New_Spin(Self.Spin, Window_Type(Self.Panel), Id_Any, "0", Style =>
> Spin_Wrap or Spin_Arrow_Keys);
>     New_Scroll_Bar(Self.Scroll_Bar, Window_Type(Self.Panel),
> Id_Type(Id_Test_Slider));
>     Set_Scroll_Bar(Self.Scroll_Bar, 20, 10, 100, 1000);
>
>     New_Static_Box(Self.Box, Window_Type(Self.Panel), Id_Any,
> "Testing...");
>     New_Static_Box_Sizer(Self.Sizer, Self.Box'Unchecked_Access,
> Box_Sizer_Orientation_Vertical);
>     --New_Box_Sizer(Self.Sizer, Box_Sizer_Orientation_Vertical);
>     Add(Sizer_Type(Self.Sizer), Self.Button, 1, Sizer_Expand or
> Sizer_Border_All, 5);
>     Add(Sizer_Type(Self.Sizer), Self.Check_Box, 1, Sizer_Expand or
> Sizer_Border_All, 5);
>     Add(Sizer_Type(Self.Sizer), Self.Slider, 1, Sizer_Expand or
> Sizer_Border_All, 5);
>     Add(Sizer_Type(Self.Sizer), Self.Spin, 1, Sizer_Expand or
> Sizer_Border_All, 5);
>     Add(Sizer_Type(Self.Sizer), Self.Scroll_Bar, 1, Sizer_Expand or
> Sizer_Border_All, 5);

I don't see any need for the conversions to Sizer_Type here. If Self.Sizer
is derived from Sizer_Type, then Add is inherited. Use that one without a
conversion. (That way, if it becomes necessary to override it in the future,
you'll use the overriding version for the type.) If it is actually
Sizer_Type, you don't need it.

The only problem is figuring out where the routine ("Add" in this case) is
declared, because you can't see inherited declarations. There are a number
of solutions to that:
1) Have a use_clause for every package that declares a type that you use. (I
hate this one myself.)
2) Use dot notation to specify that the routine comes from the package where
the type is declared;
3) or use the prefixed view call notation introduced by Ada 200Y:
    Self.Sizer.Add (Self.Scroll_Bar, 1, Sizer_Expand or Sizer_Border_All,
5);

>     New_Status_Bar(Self.Status_Bar, Window_Type(Self), Id_Any);
>     Set_Fields_Count(Self.Status_Bar, Field_Widths);
>     Set_Status_Bar(Self, Self.Status_Bar);
>     Set_Status_Text(Self.Status_Bar, "Welcome to wxAda!");
> --    Set_Status_Widths(Test_Status_Bar, Field_Widths'Length,
> Field_Widths);
>
>     Set_Size_Hints(Sizer_Type(Self.Sizer),
> Self.Panel'Unchecked_Access);
> --    Set_Sizer(Window_Type(Self.Panel), Self.Sizer'Unchecked_Access);
>     Set_Sizer(Window_Type(Self.Panel), Sizer_Type(Self.Sizer)'Access);
> --    Set_Sizer(Self.Panel, Sizer_Type(Self.Sizer));
>
>     Test_Event.New_Test_Event(Self.My_Test);
>
>     --Button_Connect(Self, Id_Type(ID_TEST_BUTTON), Id_Any,
> wx.Base.Event.Command.Button_Clicked, On_Quit'Access);
>     Button_Connect(Self, Id_Type(Id_Test_Button), Id_Any,
> Evt_Button_Clicked, On_Quit'Access);
>     --Check_Box_Connect(Self, Id_Type(ID_TEST_BUTTON), Id_Any,
> wx.Base.Event.Command.Check_Box_Clicked, On_Quit'Access);
>     Slider_Connect(Self, Id_Type(Id_Test_Slider), Id_Any,
> Evt_Scroll_Thumb_Track, On_Scroll_Top'Access);
>     Size_Connect(Self, Id_Any, Id_Any, Evt_Size, On_Size'Access);
>     --Paint_Connect(Self.Panel, Id_Any, Id_Any, Evt_Paint,
> On_Paint'Access);
>     Dump(Self);
>     My_Test_Connect(Self, Id_Any, Id_Any, Test_Event.My_Test_Event,
> On_My_Test'Access);
>
>   end New_Minimal_Frame;
>
> end Minimal_Frame;
> </Minimal_Frame>

Hope this helps.

                  Randy.






^ permalink raw reply	[relevance 0%]

* Re: Problem with "limited with" in a *real* application
  @ 2005-10-14 15:03  3%           ` Lucretia
  2005-10-14 23:47  0%             ` Randy Brukardt
  0 siblings, 1 reply; 200+ results
From: Lucretia @ 2005-10-14 15:03 UTC (permalink / raw)


Inside the Sizer package I have an Add procedure which adds a
Window_Type (e.g. Button_Type, Check_Box_Type, etc) into the derived
type to Self, which is a Sizer_Type derived type. So, I want (ideally)
to minimize the casting, so I changed the Window type to take a
Window_Type'Class so that any type can be accepted. Now, this forces me
to cast the Self type in the New_Minimal_Frame procedure (See the
Add's) to the base Sizer_Type. Now in C++ the Add function can be
overridden (as in the case of wxGridBagSizer and they're not virtuals)
so in the case of mapping to Ada in this current form, the programmer
must know which Add to use, i.e. which cast to use, which is fair
enough, but surely it would be easier to let the compiler decide?
Should I use a 'Class type here?

So, with this in mind, it's a possibility that all of the wxAda
primitives could take 'Class types so that no casting is ever needed,
but surely this is wrong, Ada-wise?

The format of the following code might get a bit screwed by Google:

<wx.Core.Sizer>
package wx.Core.Sizer is

  -- This is the actual type (wxSizer) we are creating here.
  type Sizer_Type is new Object_Type with private;

  procedure Add(
    Self       : in out Sizer_Type;
    Window     : in Window_Type'Class;
    Proportion : in Sizer_Proportion_Type := 0;
    Flags      : in Sizer_Flag_Type := 0;
    Border     : in Integer := 0);

end wx.Core.Sizer;
</wx.Core.Sizer>

<Minimal_Frame>
package body Minimal_Frame is

  procedure New_Minimal_Frame(Self : in out Minimal_Frame_Type) is

    procedure Button_Connect is new
wxEvtHandler.Connect(Command_Event_Function);
    procedure Check_Box_Connect is new
wxEvtHandler.Connect(Command_Event_Function);
    procedure My_Test_Connect is new
wxEvtHandler.Connect(On_My_Test_Function);
    procedure Slider_Connect is new
wxEvtHandler.Connect(Scroll_Event_Function);
    procedure Size_Connect is new
wxEvtHandler.Connect(Size_Event_Function);
    procedure Paint_Connect is new
wxEvtHandler.Connect(Paint_Event_Function);

    Field_Widths : Field_Widths_Array(0 .. 1) := (-3, -1);

    package Address_To_Object is new
System.Address_To_Access_Conversions(Minimal_Frame_Type);
    use Address_To_Object;

  begin

    New_Frame(Self, ID_ANY, "Minimal wxAda App", Point_Type'(400,
300));
    Text_IO.Put_Line("Self'Access : " &
System.Address_Image(To_Address(Self'Access)));

    New_Panel(Self.Panel, Window_Type(Self), Id_Any);

    New_Validator(Self.Validator);

    New_Button(Self.Button, Window_Type(Self.Panel),
Id_Type(Id_Test_Button), "Test &Button", Default_Position,
Default_Size, 0);
    Set_Validator(Window_Type(Self.Button), Self.Validator);

    New_Check_Box(Self.Check_Box, Window_Type(Self.Panel), Id_Any,
"Test &Check Box", Style => Check_Box_Align_Right);
    New_Slider(Self.Slider, Window_Type(Self.Panel), Id_Any, 50, 0,
100, Style => Slider_Horizontal or Slider_Labels);
    New_Spin(Self.Spin, Window_Type(Self.Panel), Id_Any, "0", Style =>
Spin_Wrap or Spin_Arrow_Keys);
    New_Scroll_Bar(Self.Scroll_Bar, Window_Type(Self.Panel),
Id_Type(Id_Test_Slider));
    Set_Scroll_Bar(Self.Scroll_Bar, 20, 10, 100, 1000);

    New_Static_Box(Self.Box, Window_Type(Self.Panel), Id_Any,
"Testing...");
    New_Static_Box_Sizer(Self.Sizer, Self.Box'Unchecked_Access,
Box_Sizer_Orientation_Vertical);
    --New_Box_Sizer(Self.Sizer, Box_Sizer_Orientation_Vertical);
    Add(Sizer_Type(Self.Sizer), Self.Button, 1, Sizer_Expand or
Sizer_Border_All, 5);
    Add(Sizer_Type(Self.Sizer), Self.Check_Box, 1, Sizer_Expand or
Sizer_Border_All, 5);
    Add(Sizer_Type(Self.Sizer), Self.Slider, 1, Sizer_Expand or
Sizer_Border_All, 5);
    Add(Sizer_Type(Self.Sizer), Self.Spin, 1, Sizer_Expand or
Sizer_Border_All, 5);
    Add(Sizer_Type(Self.Sizer), Self.Scroll_Bar, 1, Sizer_Expand or
Sizer_Border_All, 5);

    New_Status_Bar(Self.Status_Bar, Window_Type(Self), Id_Any);
    Set_Fields_Count(Self.Status_Bar, Field_Widths);
    Set_Status_Bar(Self, Self.Status_Bar);
    Set_Status_Text(Self.Status_Bar, "Welcome to wxAda!");
--    Set_Status_Widths(Test_Status_Bar, Field_Widths'Length,
Field_Widths);

    Set_Size_Hints(Sizer_Type(Self.Sizer),
Self.Panel'Unchecked_Access);
--    Set_Sizer(Window_Type(Self.Panel), Self.Sizer'Unchecked_Access);
    Set_Sizer(Window_Type(Self.Panel), Sizer_Type(Self.Sizer)'Access);
--    Set_Sizer(Self.Panel, Sizer_Type(Self.Sizer));

    Test_Event.New_Test_Event(Self.My_Test);

    --Button_Connect(Self, Id_Type(ID_TEST_BUTTON), Id_Any,
wx.Base.Event.Command.Button_Clicked, On_Quit'Access);
    Button_Connect(Self, Id_Type(Id_Test_Button), Id_Any,
Evt_Button_Clicked, On_Quit'Access);
    --Check_Box_Connect(Self, Id_Type(ID_TEST_BUTTON), Id_Any,
wx.Base.Event.Command.Check_Box_Clicked, On_Quit'Access);
    Slider_Connect(Self, Id_Type(Id_Test_Slider), Id_Any,
Evt_Scroll_Thumb_Track, On_Scroll_Top'Access);
    Size_Connect(Self, Id_Any, Id_Any, Evt_Size, On_Size'Access);
    --Paint_Connect(Self.Panel, Id_Any, Id_Any, Evt_Paint,
On_Paint'Access);
    Dump(Self);
    My_Test_Connect(Self, Id_Any, Id_Any, Test_Event.My_Test_Event,
On_My_Test'Access);
    
  end New_Minimal_Frame;

end Minimal_Frame;
</Minimal_Frame>




^ permalink raw reply	[relevance 3%]

* Re: hashed_maps
  @ 2005-10-11 17:45  5% ` Jeffrey R. Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey R. Carter @ 2005-10-11 17:45 UTC (permalink / raw)


Lucretia wrote:

> What's the best way to create a hashed_map which maps from
> System.Address :-> an access type? I've a need for this in wxAda and
> have set up an ordered map which works, but I'm worried that I could
> end up with a populated map which is nothing more than a linked list in
> which the search is linear.

Does System.Address_To_Access_Conversions not fill this need?

-- 
Jeff Carter
"Go and boil your bottoms."
Monty Python & the Holy Grail
01



^ permalink raw reply	[relevance 5%]

* Re: volatile vs aliased
  2005-10-05 23:38  6%   ` Randy Brukardt
  2005-10-06 13:40  0%     ` REH
@ 2005-10-06 19:08  0%     ` REH
  1 sibling, 0 replies; 200+ results
From: REH @ 2005-10-06 19:08 UTC (permalink / raw)



Randy Brukardt wrote:
> This seems like a good time to mention that I think the explicit use of
> System.Address in Ada 95 and Ada 200Y code is usually a mistake. Since
> pragma Convention can be used to ensure that general access types have the
> appropriate representation, its rare that Address needs to be used for
> interfacing. (There is only a handful of uses of Address in Claw, for
> example.)
>
> Moreover, when you *do* need to use it, Address_to_Access_Conversions is the
> best way to convert it, not an overlay (which at best blocks optimizations
> and at worst won't even work right).
>
> type T is ...;
>
> procedure Read_Variable (At_Address : in  System.Address;
>                          Into       : out T) is
>    package AAC is new System.Address_to_Access_Conversions (T);
>    V : AAC.Object_Pointer := AAC.To_Pointer (At_Address);
> begin
>     -- perform my own explicit validation of the pointer's contents, perhaps
>     -- using 'Valid; then, copy into Into:
>     Into := V.all;
> end Read_Variable;
>
> But it is better still to declare an appropriate type and never use Address
> in the first place:
>
> type Pointer_T is access all T;
> pragma Convention (C, Pointer_T);
>
> Address clauses should be restricted to mapping to hardware, IMHO.
>
>                           Randy.

Can you folks point me to some literature (books, websites, etc.) that
goes into these gory issues (volatile, aliased, convention, import,
export, etc.) in more detail?  I have some great books on Ada, but they
all seem to gloss over these types of issues.  We are in the process of
converting all our Ada code to '95.  It is very low-level and does a
lot of register bit fiddling, OS calls, and such.  I'd like to get more
informed about these new (to me) features that '95 provides.

REH




^ permalink raw reply	[relevance 0%]

* Re: volatile vs aliased
  2005-10-05 23:38  6%   ` Randy Brukardt
@ 2005-10-06 13:40  0%     ` REH
  2005-10-06 19:08  0%     ` REH
  1 sibling, 0 replies; 200+ results
From: REH @ 2005-10-06 13:40 UTC (permalink / raw)



Randy Brukardt wrote:
> This seems like a good time to mention that I think the explicit use of
> System.Address in Ada 95 and Ada 200Y code is usually a mistake. Since
> pragma Convention can be used to ensure that general access types have the
> appropriate representation, its rare that Address needs to be used for
> interfacing. (There is only a handful of uses of Address in Claw, for
> example.)
>
> Moreover, when you *do* need to use it, Address_to_Access_Conversions is the
> best way to convert it, not an overlay (which at best blocks optimizations
> and at worst won't even work right).
>
> type T is ...;
>
> procedure Read_Variable (At_Address : in  System.Address;
>                          Into       : out T) is
>    package AAC is new System.Address_to_Access_Conversions (T);
>    V : AAC.Object_Pointer := AAC.To_Pointer (At_Address);
> begin
>     -- perform my own explicit validation of the pointer's contents, perhaps
>     -- using 'Valid; then, copy into Into:
>     Into := V.all;
> end Read_Variable;
>
> But it is better still to declare an appropriate type and never use Address
> in the first place:
>
> type Pointer_T is access all T;
> pragma Convention (C, Pointer_T);
>
> Address clauses should be restricted to mapping to hardware, IMHO.
>
>                           Randy.
Randy,
That's good stuff.  Will it still apply when the address is to a
subprogram?  Can Address_to_Access_Conversions be instantiated with a
subprogram?  That's what I've been trying to do, but I don't know how
to make a generic that takes an access to an arbitrary subprogram type.
 So, I think I am "stuck" using the for X'address specification.

Thanks,
REH




^ permalink raw reply	[relevance 0%]

* Re: volatile vs aliased
  @ 2005-10-05 23:38  6%   ` Randy Brukardt
  2005-10-06 13:40  0%     ` REH
  2005-10-06 19:08  0%     ` REH
  0 siblings, 2 replies; 200+ results
From: Randy Brukardt @ 2005-10-05 23:38 UTC (permalink / raw)


"Ludovic Brenta" <ludovic@ludovic-brenta.org> wrote in message
news:87mzlnomca.fsf@ludovic-brenta.org...
...
>  In your situation, it seems that you want something like this
> (which, incidentally, I use very often):
>
> type T is ...;
>
> procedure Read_Variable (At_Address : in  System.Address;
>                          Into       : out T) is
>    V : aliased T;
>    -- suppress default initialisation, I know what I'm doing.
>    pragma Import (Ada, V);
>    for V'Address use At_Address;
> begin
>    -- perform my own explicit validation of the variable, perhaps
>    -- using 'Valid; then, copy into Into:
>    Into := V;
> end Read_Variable;

This seems like a good time to mention that I think the explicit use of
System.Address in Ada 95 and Ada 200Y code is usually a mistake. Since
pragma Convention can be used to ensure that general access types have the
appropriate representation, its rare that Address needs to be used for
interfacing. (There is only a handful of uses of Address in Claw, for
example.)

Moreover, when you *do* need to use it, Address_to_Access_Conversions is the
best way to convert it, not an overlay (which at best blocks optimizations
and at worst won't even work right).

type T is ...;

procedure Read_Variable (At_Address : in  System.Address;
                         Into       : out T) is
   package AAC is new System.Address_to_Access_Conversions (T);
   V : AAC.Object_Pointer := AAC.To_Pointer (At_Address);
begin
    -- perform my own explicit validation of the pointer's contents, perhaps
    -- using 'Valid; then, copy into Into:
    Into := V.all;
end Read_Variable;

But it is better still to declare an appropriate type and never use Address
in the first place:

type Pointer_T is access all T;
pragma Convention (C, Pointer_T);

Address clauses should be restricted to mapping to hardware, IMHO.

                          Randy.






^ permalink raw reply	[relevance 6%]

* Re: Various Language Architecture Questions
  @ 2005-09-25  7:24  5%   ` Martin Dowie
  0 siblings, 0 replies; 200+ results
From: Martin Dowie @ 2005-09-25  7:24 UTC (permalink / raw)


jimmaureenrogers@worldnet.att.net wrote:
> Typecasting is not a way of life for Ada. It is somewhat unusual.
> Ada access types (similar to references in Java) cannot be cast
> from one type to another. Ada uses Unchecked_Conversion for that
> purpose.

You would have to ensure that the underlying representation of each 
access type was the same - Ada does not require that all access types be 
a simple address. Alternatively, you could use 
System.Address_To_Access_Conversions.

But the main point is that in Ada you have to be explicit and it is easy 
to spot these 'dangerous' behaviors.


> You cannot coerce a real number type to or from an integer number
> type.

Are you sure about that Jim? :-)

declare
    I : Integer := 10;
    F : Float   := 1.0;
begin
    F := Float (I);
    I := Integer (F);
end;

Or did you mean something else by 'coerce'?

Cheers

-- Martin



^ permalink raw reply	[relevance 5%]

* Re: ++ of C in ada
  @ 2005-07-25 20:15  5% ` Robert A Duff
  0 siblings, 0 replies; 200+ results
From: Robert A Duff @ 2005-07-25 20:15 UTC (permalink / raw)


"nicolas.b" <nicolas.blanpain@fr.thalesgroup.com> writes:

> How can i implement the operator ++ in ada :
> 
> type T_Ptr is access all T_Item;
> How can i implement : procedure Increment (Ptr : in out T_Ptr);

You can implement such a thing using System.Storage_Elements and
System.Address_To_Access_Conversions.

Why do you want to use address arithmetic on T_Ptr?

I'm sure you'll get lots of responses saying you *don't* want to do
that, but there are some rare cases where it might be a good idea.

- Bob



^ permalink raw reply	[relevance 5%]

* Re: GCC 4.0 Ada.Containers Cursor danger.
  @ 2005-07-17  3:55  4%                                 ` Dmitriy Anisimkov
  0 siblings, 0 replies; 200+ results
From: Dmitriy Anisimkov @ 2005-07-17  3:55 UTC (permalink / raw)


<<But Ada does support pointer arithmetic.>>

It is *Address* arithmetic, not pointer.
Address could be trasformet into access only via
System.Address_To_Access_Conversions and

----RM---------------
The To_Pointer and To_Address subprograms convert back and forth
between values of types Object_Pointer and Address.
To_Pointer(X'Address) is equal to X'Unchecked_Access for any X that
allows Unchecked_Access.
------------------

So, we have "Unchecked_". Pointer arithmetic in Ada. If the name of the
Cusrosrs would be Unchecked_Cursor, and there is in Ada.Containers
would be complete set of access routines without cursors, it would be
Ok.

<<If you don't like the design of the Ada standard container library,
then
you should have submitted a proposal sans cursors 2 years ago.>>

Yes, I'm late, but I guess not only me do not like such unsafety. (or
checking the cursors gotten from machine model unsafety.)
Maybe  we should review Ada.Containers interface. The implementation is
good, but we should have a safer interface i think.

<<You appear to not understand the machine model, upon which the
library
is based. >>

I think high level interfaces should not be based on machine model in
Ada. It is good for C, but not good for Ada. Ada have an access to
machine model, but it is all in Unchecked and system representation
parts. Machine model is isolated from safety programming in Ada.

<<I have recently started adding additional checks to detect dangling
cursors, that are enabled via pragma Assert.>>
<<But didn't just complain that there were too few checks?  Do you want
the library to detect dangling cursors, or not? >>

If there is a cursor, it should be checked for sure, not only with
turned on assert checking. But I prefer to work without cursors, so I
need the complete set of access routines without such checking cursors.
Every time you say "if you need, do it." i could, but i could guess
from this thread that not only me have a vision of containers library
interface without cursors.




^ permalink raw reply	[relevance 4%]

* POSIX.Memory_Mapping.Map_Memory
@ 2005-01-29 15:58  4% Adrian Hoe
  0 siblings, 0 replies; 200+ results
From: Adrian Hoe @ 2005-01-29 15:58 UTC (permalink / raw)


Hi,

I am working on video_device with Video_4_Linux based on the work of
Anders Gidenstam. According to latest V4L documentation, capturing with
Read has been deprecated and the only method now is by the use of mmap.

I open a device and read the device with the following procedures, Open
and Map_Image as below. In Procedure Map_Image, I make a call to
Map_Memory (POSIX.Memory_Mapping) and raise an exception:

POSIX.POSIX_ERROR : PERMISSION_DENIED

-----------------------------------------------------------------------
...
type Intensity is new Natural range 0..255;
for Intensity'Size use 8;
type Bitmap is array (Positive range <>) of Intensity;
type Bitmap_Access is access Bitmap;
...
private

type Image_Type is new Ada.Finalization.Controlled with
record
Class  : Image_Class;
Width  : Natural := 0;
Height : Natural := 0;
BM     : Bitmap_Access := null;
end record;



------------------------------------------------------------------------
procedure Open (Device    :    out Video_Device;
File_Name : in     String) is
Win : Video_Window;
begin
if Is_Character_Special_File (To_POSIX_String (File_Name)) then
Device.Fd := Open (To_POSIX_String (File_Name),
Read_Only);
Get_Capture_Window (Device, Win);
Device.Width  := Win.Width;
Device.Height := Win.Height;
else
raise IO_Error;
end if;
end Open;

-- Close video device.
procedure Close (Device : in Video_Device) is
begin
POSIX.IO.Close (Device.Fd);
Put_Line ("Device closed");
end Close;

-- Map image
procedure Map_Image (Device  : in     Video_Device;
Image   : in out Image_Type) is

package Convert is new System.Address_To_Access_Conversions
(Bitmap_Access);
use Convert;

Buf_Size : Natural;

begin
if Get_Width (Image) /= Device.Width or
Get_Height (Image) /= Device.Height then

case Get_Class (Image) is
when Grey =>
Buf_Size := Device.Width * Device.Height;

when Color =>
Buf_Size := Device.Width * Device.Height * 3;
end case;

declare
Map      : System.Address;
begin

-- Permission Denied exception was raised here at the line below!!!
Map := Map_Memory (System.Storage_Elements.Storage_Offset
(Buf_Size),
POSIX.Memory_Mapping.Allow_Read +
POSIX.Memory_Mapping.Allow_Write,
POSIX.Memory_Mapping.Map_Shared,
Device.Fd,
0);
Set_Bitmap (Image,
Device.Width,
Device.Height,
Bitmap_Access (Convert.To_Pointer (Map).all));
end;
end if;
end Map_Image;

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

What could I have missed? Any pointer please?
Best regards,
-- 
Adrian Hoe




^ permalink raw reply	[relevance 4%]

* Re: Ada equivalent for C-pointer?
  @ 2005-01-14 20:05  5% ` tmoran
  0 siblings, 0 replies; 200+ results
From: tmoran @ 2005-01-14 20:05 UTC (permalink / raw)


>a System.Address is what you would expect a pointer to be: a (eg) 32 bit
>number referring to a memory address, like a C pointer.
  Wrong.
>Most access types
>will be the same size as, and equivalent to, a System.Address, but some
  Wrong.
There is no requirement that a System.Address have any particular
representation.  For instance, quoting from the manual for a compiler
that handles the general segment:offset form of addressing in
Intel 8086 descended chips:
  type Address is record
    Offset : Offset_Type;
    Segment: Word;
  end record;
which is 48 bits.

>some access types may be bigger ("fat pointers") because ...
 Right.  Two different access types may have two different
representations, and neither is necessarily the same as a C pointer.

>       pragma Convention (C, C_Pointer);
  Right.  In Ada, one asks the compiler to handle such low-level stuff,
rather than worrying about it or trying to sneakily do it yourself.
That's why there is a pragma Convention to tell the compiler you want
something to be compatible with C (or Fortran, or whatever).

  Separately, and probably irrelevantly for the OP, there is a
package System.Address_to_Access_Conversions to let you tell the
compiler to convert between whatever form it is using for a particular
access type, and whatever form it is using for a System.Address.



^ permalink raw reply	[relevance 5%]

* Converting access values
@ 2005-01-05 22:31  3% Mark Lorenzen
  0 siblings, 0 replies; 200+ results
From: Mark Lorenzen @ 2005-01-05 22:31 UTC (permalink / raw)


Hello,

Imagine that we have a program that reads large amount of data from
(for example) a network connection into buffers. The data is just to
be seen as a sequence of octets.

We now want to copy parts ("slices") of the data to other tasks that
may do something interesting with these slices. The rate of data is
too high to simply copy the wanted slices, so instead we make "cheap
copies".

The idea is that these cheap copies simply point to slices within the
large buffer and this way all copies refer to a common buffer and no
real copying is going on.

We do not care about concurrent access to the buffers, allocation and
deallocation of the buffers. All this is taken care of by some safe
mechanism which would just clutter up the following little example.

I am able to actually create such a slice. It contains the correct
values, has the correct constraints and so on. The problem is simply
that my buffer has type access-to-unconstrained-array type and my copy
has an access-to-constrained-array type.

Question: How do i convert an access-to-constraint-array type to
access-to-unconstrained-array type in a (more or less) portable way?

As the example involves access types, adresses and conversions, I have
taken on my asbestos long-johns - so let the flaming begin!

Regards,
- Mark Lorenzen

type Buffer_Ptr is access Ada.Streams.Stream_Element_Array;

procedure Copy (Source : in Buffer_Ptr;
                Offset : in Ada.Streams.Stream_Element_Count;
                Length : in Ada.Streams.Stream_Element_Count;
                Target : out Buffer_Ptr) is
   use type Ada.Streams.Stream_Element_Offset;

   Slice_Begin : constant Ada.Streams.Stream_Element_Offset :=
     Source'First + Offset;
   Slice_End   : constant Ada.Streams.Stream_Element_Offset :=
     Slice_Begin + Length - 1;

   -- Subtype defining the desired constraints (ie. the slice) in
   --  the source buffer.
   subtype Constrained_Buffer is
     Ada.Streams.Stream_Element_Array (Slice_Begin .. Slice_End);

   package Conversions is
      new System.Address_To_Access_Conversions (Constrained_Buffer);

   Slice : Conversions.Object_Pointer;

   function To_Buffer_Ptr is
      new Ada.Unchecked_Conversion (Conversions.Object_Pointer, Buffer_Ptr);
begin
   -- Use the address of element Source(Offset) and convert it into
   --  an access-to-constrained-array type.

   Slice := Conversions.To_Pointer (Source(Slice_Begin)'Address);

   -- Now Slice actually points to a constrained array with the correct
   --  'First, 'Last and 'Length attributes. It's location in the storage
   --  also coincides with Source (Slice_Begin .. Slice_End). Fine!

   -- Problem: Slice is of type Conversions.Object_Pointer, but we
   --  really want a value of type Buffer_Ptr. How do we convert an
   --  access-to-constrained-array value to an
   --  access-to-unconstrained-array value in a (more or less)
   --  portable way?

   Target := ????
end Copy;



^ permalink raw reply	[relevance 3%]

* Re: Thick Ada bindings to C Win32
  @ 2004-11-28 23:45  4%             ` Brian May
  0 siblings, 0 replies; 200+ results
From: Brian May @ 2004-11-28 23:45 UTC (permalink / raw)


>>>>> "Brian" == Brian May <bam@snoopy.apana.org.au> writes:

    Brian> I seem to remember that I encountered problems doing things
    Brian> as simply as you suggest, but I can't remember why nor can
    Brian> I imagine why - I will try it again and report back here
    Brian> with details of any errors encountered.

Unfortunately, I was right, I did have problems:

     type Byte_Array_Access is access all Byte_Array;
     pragma Convention (C,Byte_Array_Access);

produces:

serial.adb:107:11: warning: this access type does not correspond to C pointer

and:

   function To_LPCVOID is new 
      Ada.Unchecked_Conversion (Byte_Array_Access, Win32.LPCVOID);

produces:

serial.adb:144:04: warning: types for unchecked conversion have different sizes

So I tried:

   Type Char_Array_Ptr is access all Interfaces.c.Char_Array;
   pragma Convention (C,Char_Array_Ptr);

which produces:

serial.adb:89:09: warning: this access type does not correspond to C pointer

I still am not sure of the proper way of creating a C pointer in
Ada. So far I have see advice don't user 'Access and don't use
'Address as neither of these are portable. What is the correct way?

This is why my complicated solution was so complicated, I ended up:

1. Creating an aliased Byte_Array.
2. Creating a Interfaces.C.Strings.Char_Array_Access,
   copy access type using uchecked_conversion.
3. Converting to C pointer using Interfaces.C.Strings.To_Chars_Ptr.
4. Convert to LPCVOID using unchecked conversion.

Hmmm... I wonder if what I need is
system.address_to_access_conversions and/or
System.Storage_Elements.To_Integer?

However, all of this is complicated by the fact LPVOID and LPCVOID in
Ada is defined as a subtype of System.Address in the Windows bindings,
which implies the correct way to pass the parameter to
Item'Address. This is also the simplest way.

So I know people have said this is wrong, but I am going to assume if
the windows bindings use System.Address then this method will work on
Windows.
-- 
Brian May <bam@snoopy.apana.org.au>



^ permalink raw reply	[relevance 4%]

* Re: Ada Pointer Size Problem
       [not found]       ` <1c2f5137.0410130505.57e03c@posting.google.com>
@ 2004-10-14  3:46  5%     ` Steve
  0 siblings, 0 replies; 200+ results
From: Steve @ 2004-10-14  3:46 UTC (permalink / raw)


The package "System.Address_To_Access_Conversions" is what you're looking
for.

http://www.adaic.org/standards/95lrm/html/RM-13-7-2.html

Steve
(The Duck)

"Hans Van den Eynden" <onsbomma@hotmail.com> wrote in message
news:1c2f5137.0410130505.57e03c@posting.google.com...
>[snip]
>
> > There are functions to convert an access to an Address
>
> Are there also functions that convert an Address to an access?? And
> what about Ada's type safety than ??
> I also can't anything about System.Address in the Ada95RM, a leftover
> from Ada83?





^ permalink raw reply	[relevance 5%]

* Re: Ada access vs C/C++ pointers and references
  @ 2004-08-19  0:21  4% ` Nick Roberts
  0 siblings, 0 replies; 200+ results
From: Nick Roberts @ 2004-08-19  0:21 UTC (permalink / raw)


On 18 Aug 2004 15:27:47 -0700, Keith H Duggar <duggar@mit.edu> wrote:

> [re array indexing]
> As you can see, method two saves one instruction by storing
> and manipulating a memory address directly.

In a loop, there is well known optimisation known (for reasons which
mystify me) as 'strength reduction', which allows a loop such as:

    for (i=0;i<n;i++) { ... a[i] ... };

to be transformed into the equivalent of:

    for (p=&a[0];p<&a[n];p++) { ... *p ... };

before emitting machine code. So an Ada loop such as:

    for i in 1..N loop
       ... A(i) ...
    end loop;

can be expected to be compiled into machine code which is as
efficient as the code that could be produced by using direct address
manipulation.

> First, is it correct to say that Ada access types are more
> similar to C++ references (T&) than they are to C/C++
> pointers (T*) ?

No. Ada access types are very similar to C and C++ pointers, and are
typically implemented and used in (almost) exactly the same way.

The rough Ada equivalent of C++ references are 'aliased objects'.

> Second, does Ada provide any facilities for direct and raw
> memory access by memory address and pointer arithmetic?

Yes it does. There are standard packages System.Storage_Elements and
System.Address_To_Access_Conversions, which provide facilities for
converting between access types and addresses, and performing integer
arithmetic on addresses, as well as Interfaces.C and
Interfaces.C.Pointers which enable Ada programs to access C strings,
arrays, and pointers.

> Third, if Ada does not provide arithmetic pointers do you
> know if this has played any part in acceptance of Ada for
> systems programming or efficiency critical applications?

I don't know (sorry).

> Fourth, have you experienced or can you think of any cases
> where pointer arithmetic has helped to solve a problem that
> would have been more difficult with Ada access types alone?

Not that I can recall.

-- 
Nick Roberts



^ permalink raw reply	[relevance 4%]

* Re: Longstanding GNAT bug, bad code, or both -- Answer..Bad code.
  @ 2004-08-08 11:26  5%     ` Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2004-08-08 11:26 UTC (permalink / raw)


Stephen Leake <stephen_leake@acm.org> writes:

> "Jeff C," <jcreem@yahoo.com> writes:
> 
> > Ok. I submitted a bugzilla report and it has already been
> > cancelled.  Apparently, declaring a variable as aliased makes it
> > contrained.  (According to one of the gcc Ada maintainers)
> 
> Ah. LRM 3.3.1 (9) says this. (I just searched for 'aliased' in the
> Emacs info version; guess I should have done that earlier :).

I work round this in the Booch Components using a horrible trick with
System.Address_To_Access_Conversions -- which works with GNAT &
ObjectAda (and I guess Rational Apex, I know there are/were users and
they haven't complained!)

-- 
Simon Wright                               100% Ada, no bugs.



^ permalink raw reply	[relevance 5%]

* Re: C array to ada record interface
  2004-07-29  5:56  6%     ` tmoran
@ 2004-07-29 19:58  0%       ` Robert I. Eachus
  0 siblings, 0 replies; 200+ results
From: Robert I. Eachus @ 2004-07-29 19:58 UTC (permalink / raw)


tmoran@acm.org wrote:

>   Presumably a 64 bit Ada compiler could be designed to work with a 32 bit
> C compiler, with pragma Convention(C, an_access_type) causing
> an_access_type to be a 32 bit pointer (with implied additional 32 bits
> from a segment or base or just zero, for instance) rather than a 64 bit
> pointer.  Such a compiler ought to be able to do System.Address <-> access
> type conversions for 32 bit, as well as 64 bit, access types, but Ada's
> System.Address_To_Access_Conversions could only work for one of those,
> right?  Perhaps the vendor of such a compiler would offer (non-standard)
> package System.Address_To_Access_Conversions.C
> for doing the (32 bit or convention C) conversions.

Doesn't even have to be a non-standard mode.  In theory you could 
validate a compiler in two modes that support different C compilers or 
different operating modes.  Of course, a compiler that wants to support 
two different C calling conventions usually has two additional 
convention names, and probably a compiler switch that tells which one 
corresponds to convention C.

The point I was trying to make was that which C compiler is chosen to 
bind to, and how it is chosen is outside the scope of the standard.  So, 
in general, the code as written will work.  But there is no 
implementation-independent way to guarantee it.

-- 

                                           Robert I. Eachus

"The flames kindled on the Fourth of July, 1776, have spread over too 
much of the globe to be extinguished by the feeble engines of despotism; 
on the contrary, they will consume these engines and all who work them." 
-- Thomas Jefferson, 1821




^ permalink raw reply	[relevance 0%]

* Re: C array to ada record interface
  2004-07-28  2:42  0%   ` Robert I. Eachus
@ 2004-07-29  5:56  6%     ` tmoran
  2004-07-29 19:58  0%       ` Robert I. Eachus
  0 siblings, 1 reply; 200+ results
From: tmoran @ 2004-07-29  5:56 UTC (permalink / raw)


>>     package B_Ptr_Conversion is new System.Address_To_Access_Conversions(B);
>>     pragma Convention (C, B_Ptr_Conversion.Object_Pointer);
>> is not legal.
> If the Ada compiler uses the same type of addresses as the C
>compiler there is no problem.  But if you have a 64-bit Ada compiler and
>a 32-bit C compiler (or vice-versa) it can't work.

  Presumably a 64 bit Ada compiler could be designed to work with a 32 bit
C compiler, with pragma Convention(C, an_access_type) causing
an_access_type to be a 32 bit pointer (with implied additional 32 bits
from a segment or base or just zero, for instance) rather than a 64 bit
pointer.  Such a compiler ought to be able to do System.Address <-> access
type conversions for 32 bit, as well as 64 bit, access types, but Ada's
System.Address_To_Access_Conversions could only work for one of those,
right?  Perhaps the vendor of such a compiler would offer (non-standard)
package System.Address_To_Access_Conversions.C
for doing the (32 bit or convention C) conversions.



^ permalink raw reply	[relevance 6%]

* Re: C array to ada record interface
  2004-07-27 21:04  5% ` tmoran
@ 2004-07-28  2:42  0%   ` Robert I. Eachus
  2004-07-29  5:56  6%     ` tmoran
  0 siblings, 1 reply; 200+ results
From: Robert I. Eachus @ 2004-07-28  2:42 UTC (permalink / raw)


tmoran@acm.org wrote:

>     package B_Ptr_Conversion is new System.Address_To_Access_Conversions(B);
>     subtype B_Ptr is B_Ptr_Conversion.Object_Pointer;
> which works on three different compilers.  But neither
> 
>     pragma Convention (C, B_Ptr);
> nor
>     pragma Convention (C, B_Ptr_Conversion.Object_Pointer);
> is then legal.

That is correct, see the limitations on where representation pragmas can 
appear in RM 13.1 as ammended.  (The wordsmithing in the 2000 Ammendment 
in this area is extensive, but I don't think it affected this issue one 
way or the other.)

> The program works without the pragma Convention on all three Ada compilers
> I tried, but it's not clear to me that's guaranteed to be OK, and if some
> system does need the pragma, is there a compiler-agnostic way to solve
> this problem?

No!  But remember here that what can't be compiler agnostic is the 
choice of C compiler and options to match the Ada compiler (and 
options).  If the Ada compiler uses the same type of addresses as the C 
compiler there is no problem.  But if you have a 64-bit Ada compiler and 
a 32-bit C compiler (or vice-versa) it can't work.

Well, not quite, but you know what I mean.  For example, with the new 
AMD64 chips--including Intel's newest Xeon--you can have a library that 
is compiled for IA-32, and another library compiled in long mode, and 
the hardware will convert the addresses if possible on the calls and 
returns so that a program can use either one.  But you can't link 32-bit 
code and long mode code into the same executable, you have to use .dlls.

The best you can do is to specify the sizes of the addresses, so that 
the compiler will reject your program if they don't match.  In fact a 
better example of why this is an insoluble problem is that the new Xeon 
(Nocona) does not have an IOMMU, while the Opteron and Athlon64 use the 
CPU's MMU for all memory references.  The net effect is that I/O drivers 
have to be written differently for the two families.  There is no magic 
wand that either a C compiler or an Ada compiler can wave to fix that 
semantic mismatch.

-- 

                                           Robert I. Eachus

"The flames kindled on the Fourth of July, 1776, have spread over too 
much of the globe to be extinguished by the feeble engines of despotism; 
on the contrary, they will consume these engines and all who work them." 
-- Thomas Jefferson, 1821




^ permalink raw reply	[relevance 0%]

* Re: C array to ada record interface
  @ 2004-07-27 21:04  5% ` tmoran
  2004-07-28  2:42  0%   ` Robert I. Eachus
  0 siblings, 1 reply; 200+ results
From: tmoran @ 2004-07-27 21:04 UTC (permalink / raw)


>   type B_Ptr is access all B;
>   pragma Convention (C, B_Ptr);
> ...
>       function To_Address is new Ada.Unchecked_Conversion
>          (Source => B_Ptr, Target => System.Address);

  Interesting possible problem:  One of the compilers I use rejected
the Unchecked_Conversion because its System.Address is not the same
size as B_Ptr.  So I dropped the Unchecked programming and used instead

    package B_Ptr_Conversion is new System.Address_To_Access_Conversions(B);
    subtype B_Ptr is B_Ptr_Conversion.Object_Pointer;
which works on three different compilers.  But neither

    pragma Convention (C, B_Ptr);
nor
    pragma Convention (C, B_Ptr_Conversion.Object_Pointer);
is then legal.

The program works without the pragma Convention on all three Ada compilers
I tried, but it's not clear to me that's guaranteed to be OK, and if some
system does need the pragma, is there a compiler-agnostic way to solve
this problem?

(Neither is    pragma Convention (C, Array_With_Known_Length);
legal but that seems even less likely to be necessary.)



^ permalink raw reply	[relevance 5%]

* Re: Question on interface Ada to C
  2004-05-25 21:38  6% ` Simon Wright
@ 2004-05-26 13:05  0%   ` James Alan Farrell
  0 siblings, 0 replies; 200+ results
From: James Alan Farrell @ 2004-05-26 13:05 UTC (permalink / raw)


Thank you for all the answers.

Why is it in out?  The quick answer is that is how it was done in the
code I inherited. 

 From what I understand, this was done to allow C to use a pointer
argument.  That does not match my understanding of how Ada works, but
I am new to Interfaces.C and do not have a good understanding of how
that works.

James Alan Farrell
GrammaTech


On 25 May 2004 22:38:07 +0100, Simon Wright <simon@pushface.org>
wrote:

>James Alan Farrell <anonymous@anonymous.com> writes:
>
>>  type stuff is integer; -- just for example
>> 
>>  type List_Type is array(Integer range <>) of stuff;
>>  
>>  package MyPointers is 
>>               new System.Address_To_Access_Conversions(List_Type);
>>  subtype List_Pointer is MyPointers.Object_Pointer;
>> 
>>  procedure MyProc
>>      (Items     : in out List_Pointer;
>>       Nitems    : in out Integer) is
>> 
>>       List : List_Type := function_that_returns_a_list;
>
>List is on the stack
>
>> 
>>    begin
>>       Nitems := List'Length;
>>       Items  := MyPointers.To_Pointer(List'Address);
>>    end;
>
>List has gone away!
>
>I think you're going to need to allocate the particular array and get
>the C code to free it (well, that's dangerous, perhaps you should
>supply an Ada subprogram to actually do the freeing so as to be sure
>the right storage pool is used; or perhaps you could import malloc?)
>
>And I don't think C will understand a List_Pointer, because List_Type
>is unconstrained so any concrete List may have bounds with it. There's
>no reason to suppose that List'Address is the same as List
>(List'First)'Address. The C is expecting effectively a System.Address,
>so make your Items parameter a System.Address (why is it in out, BTW?)
>
>One "trick" is to declare a local subtype which is constrained by the
>actual bounds.
>
>  List : List_Type := function_that_returns_a_list;
>  type actual_list_type is list_type (list'range); -- or suchlike
>  -- instantiate System.Address_To_Access_Conversions for actual_list_type
>  function malloc (n : natural) return system.address;
>  pragma import (c, malloc, "malloc");
>begin
>  Items := malloc (actual_list_type'max_size_in_storage_elements);
>  -- copy the contents of List using the System.Address_To_Access_Conversions
>  -- instantiation above
>
>Good grief, that looks complicated, I dare say I've missed something
>simple ..




^ permalink raw reply	[relevance 0%]

* Re: Question on interface Ada to C
  2004-05-25 21:00  4% Question on interface Ada to C James Alan Farrell
  2004-05-25 21:30  0% ` Dale Stanbrough
  2004-05-25 21:38  6% ` Simon Wright
@ 2004-05-26  7:34  0% ` Martin Krischik
  2 siblings, 0 replies; 200+ results
From: Martin Krischik @ 2004-05-26  7:34 UTC (permalink / raw)


James Alan Farrell wrote:

> Hello all,

> I've inherited a project that is half written in C and Ada.

Nothing wrong with that. You should carfully read Annex B. Currently I do a
lot of Ada / C mixed programming as well. It works quite well.

> My boss at first thought this was good code but when he took a second
> look he wasn't so sure.  So he's asked me to investigate.  What
> exactly happens with the memory used by list in this situation?

The code is indeed not very good.

> We're using GNAT, but I don't think that's an issue -- I would think
> this code would behave (or misbehave) the same no matter what
> compiler.

That depends if you use GNAT with gcc's own C or GNAT with some other C. 

> Thanks,
> James Alan Farrell
> GrammaTech.
> 
>  type stuff is integer; -- just for example
> 
>  type List_Type is array(Integer range <>) of stuff;
>  
>  package MyPointers is
>               new System.Address_To_Access_Conversions(List_Type);
>  subtype List_Pointer is MyPointers.Object_Pointer;
> 
>  procedure MyProc
>      (Items     : in out List_Pointer;
>       Nitems    : in out Integer) is
> 
>       List : List_Type := function_that_returns_a_list;
> 
>    begin
>       Nitems := List'Length;
>       Items  := MyPointers.To_Pointer(List'Address);
>    end;

List will be short lived after MyProc ends. Also list is indefinite - C has
no conzept of indefinite.

You should return a record like this (Example for Character):

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

   --
   --  C/Ada String Type
   --
   type C_Array
   is array
      (Natural range <>)
   of aliased
      Character;

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

   package C_Pointers
   is new
      Interfaces.C.Pointers (
         Index              => Natural,
         Element            => Character,
         Element_Array      => C_Array,
         Default_Terminator => Character'First);

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

   type C_String
   is record
      Data : C_Pointers.Pointer;
      Size : Interfaces.C.size_t;
   end record;

With GNAT you can use function as well. Returning a record from Ada to C
work OK.

C_String.Data should be allocated and freed with malloc. See:

http://cvs.sourceforge.net/viewcvs.py/adacl/CUnicode/Include/c-generic_strings.adb?rev=1.5&view=auto

If you use GNAT only then you can import malloc directly.

With Regards

Martin

-- 
mailto://krischik@users.sourceforge.net
http://www.ada.krischik.com




^ permalink raw reply	[relevance 0%]

* Re: Question on interface Ada to C
  2004-05-25 21:00  4% Question on interface Ada to C James Alan Farrell
  2004-05-25 21:30  0% ` Dale Stanbrough
@ 2004-05-25 21:38  6% ` Simon Wright
  2004-05-26 13:05  0%   ` James Alan Farrell
  2004-05-26  7:34  0% ` Martin Krischik
  2 siblings, 1 reply; 200+ results
From: Simon Wright @ 2004-05-25 21:38 UTC (permalink / raw)


James Alan Farrell <anonymous@anonymous.com> writes:

>  type stuff is integer; -- just for example
> 
>  type List_Type is array(Integer range <>) of stuff;
>  
>  package MyPointers is 
>               new System.Address_To_Access_Conversions(List_Type);
>  subtype List_Pointer is MyPointers.Object_Pointer;
> 
>  procedure MyProc
>      (Items     : in out List_Pointer;
>       Nitems    : in out Integer) is
> 
>       List : List_Type := function_that_returns_a_list;

List is on the stack

> 
>    begin
>       Nitems := List'Length;
>       Items  := MyPointers.To_Pointer(List'Address);
>    end;

List has gone away!

I think you're going to need to allocate the particular array and get
the C code to free it (well, that's dangerous, perhaps you should
supply an Ada subprogram to actually do the freeing so as to be sure
the right storage pool is used; or perhaps you could import malloc?)

And I don't think C will understand a List_Pointer, because List_Type
is unconstrained so any concrete List may have bounds with it. There's
no reason to suppose that List'Address is the same as List
(List'First)'Address. The C is expecting effectively a System.Address,
so make your Items parameter a System.Address (why is it in out, BTW?)

One "trick" is to declare a local subtype which is constrained by the
actual bounds.

  List : List_Type := function_that_returns_a_list;
  type actual_list_type is list_type (list'range); -- or suchlike
  -- instantiate System.Address_To_Access_Conversions for actual_list_type
  function malloc (n : natural) return system.address;
  pragma import (c, malloc, "malloc");
begin
  Items := malloc (actual_list_type'max_size_in_storage_elements);
  -- copy the contents of List using the System.Address_To_Access_Conversions
  -- instantiation above

Good grief, that looks complicated, I dare say I've missed something
simple ..

-- 
Simon Wright                               100% Ada, no bugs.



^ permalink raw reply	[relevance 6%]

* Re: Question on interface Ada to C
  2004-05-25 21:00  4% Question on interface Ada to C James Alan Farrell
@ 2004-05-25 21:30  0% ` Dale Stanbrough
  2004-05-25 21:38  6% ` Simon Wright
  2004-05-26  7:34  0% ` Martin Krischik
  2 siblings, 0 replies; 200+ results
From: Dale Stanbrough @ 2004-05-25 21:30 UTC (permalink / raw)


James Alan Farrell <anonymous@anonymous.com> wrote:


> Thanks,
> James Alan Farrell
> GrammaTech.
> 
>  type stuff is integer; -- just for example
> 
>  type List_Type is array(Integer range <>) of stuff;
>  
>  package MyPointers is 
>               new System.Address_To_Access_Conversions(List_Type);
>  subtype List_Pointer is MyPointers.Object_Pointer;
> 
>  procedure MyProc
>      (Items     : in out List_Pointer;
>       Nitems    : in out Integer) is
> 
>       List : List_Type := function_that_returns_a_list;
> 
>    begin
>       Nitems := List'Length;
>       Items  := MyPointers.To_Pointer(List'Address);
>    end;

You are right in thinking it is not good code.

The variable List is allocated on the stack/secondary head, and should
go away when the procedure ends. The pointer to it will no longer
be valid once you return from this procedure.


Better to have function_that_returns_a_list be
   function_that_returns_a_pointer_to_a_list

and return that....


      type List_Type_Access is access all List_Type;
      -- declare this type where it is visible to your
      -- other function.


      List_Ptr :+ list_type_access := function_that_returns_a_pointer...
   begin
      Nitems := List.all'Length;
      Items  := MyPointers.To_Pointer(List.all(1)'Address);
   end;


there's probably other stuff you should look at in the Interfaces.C.*
package family - there will be a better way than this.


Dale

-- 
dstanbro@spam.o.matic.bigpond.net.au



^ permalink raw reply	[relevance 0%]

* Question on interface Ada to C
@ 2004-05-25 21:00  4% James Alan Farrell
  2004-05-25 21:30  0% ` Dale Stanbrough
                   ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: James Alan Farrell @ 2004-05-25 21:00 UTC (permalink / raw)


Hello all,
I've inherited a project that is half written in C and half in Ada.
I'm finding a lot of code  like that below (this is psuedocode and I
do not know that it will compile.  It gives the idea of what is going
without revealing company proprietary information)

The procedure is called by C.  It passes back a pointer to list, which
the C code uses to read data from list.

It seems to me that this is not safe because of the possibility that
the memory that holding the data will "go away" (be deallocated,
removed from the stack or whatever happens in this situation).

My boss at first thought this was good code but when he took a second
look he wasn't so sure.  So he's asked me to investigate.  What
exactly happens with the memory used by list in this situation?

We're using GNAT, but I don't think that's an issue -- I would think
this code would behave (or misbehave) the same no matter what
compiler.

Thanks,
James Alan Farrell
GrammaTech.

 type stuff is integer; -- just for example

 type List_Type is array(Integer range <>) of stuff;
 
 package MyPointers is 
              new System.Address_To_Access_Conversions(List_Type);
 subtype List_Pointer is MyPointers.Object_Pointer;

 procedure MyProc
     (Items     : in out List_Pointer;
      Nitems    : in out Integer) is

      List : List_Type := function_that_returns_a_list;

   begin
      Nitems := List'Length;
      Items  := MyPointers.To_Pointer(List'Address);
   end;



^ permalink raw reply	[relevance 4%]

* Re: C bindings, Interfaces.C.Pointers etc.
  @ 2004-05-12  6:30  5% ` Martin Krischik
  0 siblings, 0 replies; 200+ results
From: Martin Krischik @ 2004-05-12  6:30 UTC (permalink / raw)


Dr. Adrian Wrigley wrote:

> Hi folks!
> 
> I have a problem creating a binding to a C library.
> 
> The library makes extensive use of arrays of arrays of structs.
> Both levels of arrays are of variable length.
> 
>  struct node { int index; double value; };
>  struct problem { node **x; };
> 
> When I attempt to define Ada types for this type of thing,
> I find I can't use access types to the arrays with the
> necessary C convention.
> "warning: this access type does not correspond to C pointer"
> is the compiler error.
> 
> I have tried using Interfaces.C.Pointers, but I have run
> into (soluble?) problems.
> 
> 1)  How to I allocate an array (in Ada) and assign it to a
>    C pointer? (in a single expression?)

Ada_Array : <some array>

C_Pointer  :  constant C_Pointers.Pointer := Ada_Array (0)'Unchecked_Access;

Depending on how Ada_Array is defined it might work without Unchecked_.
 
> 2)  How do I free the allocaed array from the C pointer?
>    Do I need to keep track of the return values from "new"
>    separately from the pointers?

Since the Pointer are for use with C you might consider:

   function malloc (Size : size_t) return System.Address;
   pragma Import (C, malloc, "malloc");
   procedure free (Ptr : System.Address);
   pragma Import (C, free, "free");

You can either combine it with package System.Address_To_Access_Conversions
or a special Storrage_Pool.
 
> 3)  How do I access the n'th element of the Array, given the
>    C pointer.

Depending on actual use You can either convert the C array to an Ada array
or use:

Access_Pointer := Base_Pointer + n;

... Base_Pointer.all ...

> 4)  Is there some convenient shortcut to avoid using I.C.P?
>    perhaps by declaring an Ada constrained array much larger than
>    intended, and using a subset.
>    Using I.C.P seems massively verbose (10x) for this application.

From you example down I suggest "aliased" Elements

type NodeArray_T is array (Interfaces.C.Size_T range <>) of  aliased Node_T;
type NodeArrayArray_T is array (Interfaces.C.Size_T range <>) of aliased 
NodeArray_A;

then you can use I.C.P.Value and I.C.P.Copy_Array as alternative to pure
Pointer use. Giving you more flexibility.
 
> As I understand it, if the array is unconstrained, an access type
> to the array contains the dope information, and can't be used
> as a C pointer.
> 
> I have given an example of my problem code below (without I.C.P).

Well, it does look Ok to me. Apart from the missing "aliased". All elements
in an C array need an address while in Ada they don't. (Look for pragma
Pack and the attributes 'Size and 'Component_Size for details).

With Regards

Martin
-- 
mailto://krischik@users.sourceforge.net
http://www.ada.krischik.com




^ permalink raw reply	[relevance 5%]

* Re: Access type conversions, how?
  @ 2004-04-14 12:07  5%                   ` Lutz Donnerhacke
  0 siblings, 0 replies; 200+ results
From: Lutz Donnerhacke @ 2004-04-14 12:07 UTC (permalink / raw)


* Luke Guest wrote:
> "Lutz Donnerhacke" <lutz@iks-jena.de> wrote in message
>> Please use Address_To_Access_Conversion and map the adresses.
>
> Why? Is this a standard function?

ARM95: 13.7.2 The Package System.Address_To_Access_Conversions

>> Or (better) define a variable of the different type at the same location.
>
> I don't know what you mean here.

Mapping two repesentation at the same memory location does not generate any
code, but provide the required access.

>> An example is available in my recent posting here on "Efficient Stream_IO"
>
> Well, I've just looked and I couldn't see any use of that function.

There is no function. Only a variable of a different type mapped to the same
location. You might use "pragma Union(Variable_Record);" on GNAT to get the
same result.



^ permalink raw reply	[relevance 5%]

* Re: [Q] non-limited record and "self-pointer"
  @ 2004-02-09 15:45  4%       ` Georg Bauhaus
  0 siblings, 0 replies; 200+ results
From: Georg Bauhaus @ 2004-02-09 15:45 UTC (permalink / raw)


Stephen Leake <stephen_leake@acm.org> wrote:
: Georg Bauhaus <sb463ba@l1-hrz.uni-duisburg.de> writes:
: 
:> Stephen Leake <stephen_leake@acm.org> wrote:
:> : I'm not clear what you are asking. 
:> 
:> I'm puzzled too by the compiler's silence, because AFAIK a record cannot
:> silently become limited?
: 
: Post a complete, compilable example, and I'll take another look at it.

There it is, ObjectAda 7.2.2 does not complain either.


with sets;
package some_sets is new sets(Integer);

with some_sets;  use some_sets;
procedure simple_test is
   s1, s2: Read_Only_Set;
   s: Set;
   p: Set_Ptr;
begin
   s1 := s2;
   p := value_in_place(s);
end simple_test;



with Charles.Sets.Sorted.Unbounded;
generic
   type Element is private;

   with function "<"(L, R: Element) return Boolean is <>;
   with function "="(L, R: Element) return Boolean is <>;

   --with function wide_image(e: Element) return Wide_String is <>;
package Sets is



   type Read_Only_Set is tagged private;


   --  Modifiable Sets

   type Set is new Read_Only_Set with private;


   type Set_Ptr is access all Read_Only_Set'class;

   function value_in_place(container: Set) return Set_Ptr;
   --  a pointer to container (avoids copying)


private
   package Implementation is
      new Charles.Sets.Sorted.Unbounded(Element);

   type Read_Only_Set is tagged
      record
         container: Implementation.Container_Type;

         self: Set_Ptr := Read_Only_Set'unchecked_access;
         --  used in value_in_place

      end record;

   type Set is new Read_Only_Set with record
      frozen: Boolean := true;
   end record;


end Sets;



package body Sets is

   use Implementation;



   -- ----------------
   -- value_in_place
   -- ----------------
   --  every object of type Set points to itself

   function value_in_place(container: Set) return Set_Ptr is
      -- cont: aliased Set;
      -- for cont'address use container'address;
      -- cannot overlay controlled
      -- package set_ptrs is new System.Address_to_Access_conversions(Set);
   begin
      return container.self;
   end value_in_place;



end Sets;



^ permalink raw reply	[relevance 4%]

* gnat/linux:setitimer
@ 2004-01-03 18:52  6% TIlman Glotzner
  0 siblings, 0 replies; 200+ results
From: TIlman Glotzner @ 2004-01-03 18:52 UTC (permalink / raw)


Hello,

below my attempt to connect the linux system timer to an ada program.
1) In the process list, I see the program distributed over 5
processes. Each signal handler is mapped onto one process. One
process is probably needed for the main program. On which part
of the program are the other 2 processes mapped to ?

2) When the timer expires, the timer signal (SIGALRM) is not catched
by the signal handler.  The signal handlers itselves apparrently work as
the handlers react to signals sent by a unix kill command. As
process number I need to give the PID of the appropriate signal
handler. I suspect that the signal is sent to the process that
started the itimer. As the signal signal handlers  run as
separated processes, the SIGALRM signal issued from the itimer does not 
reach the signal handlers. What do I need to do to make it work ?

3) Is there a unix utility that allows me to monitor signals,
 i.e. which program issues which signal, and which program catches it ?

4) I first tried to import the system call "setitimer", and hand over
setitimer's parameters by access types(ITimervalPtrs'address). The
program also compiles if handing over the variables directly (not
references to the variables). Is gnat/ada doing a parameter conversion to
a reference implicitly for me ?

Thank you,

Tilman

--------------------------------------------------------------
-- Filename: timer.ads
--------------------------------------------------------------
with Type_Defs,System.Address_To_Access_Conversions,Ada.Interrupts.Names;
use Type_Defs,Ada.Interrupts, Ada.Interrupts.Names;

package Timer is

   -- Timers run in real time.
   ITIMER_REAL: constant := 0;

   -- Timers run only when the process is executing.
   ITIMER_VIRTUAL: constant := 1;

   --  Timers run when the process is executing and when
   --  the system is executing on behalf of the process.
   ITIMER_PROF: constant := 2;

   type T_Time is new Long_Integer;

   type T_Timeval is record
      Tv_Sec : T_Time;        -- seconds
      Tv_Usec: T_Time;        -- microseconds
   end record;

   type T_Itimerval is record
      It_Interval: T_Timeval;    -- next value
      It_Value:    T_Timeval;    -- current Value
   end record;

   package TimevalPtrs is new System.Address_To_Access_Conversions( 
T_Timeval );
   package ITimervalPtrs is new System.Address_To_Access_Conversions( 
T_Itimerval );


  
   protected SignalHandler is
      -- SIGINT (Control-C) signals will be intercepted by
      -- HandleControlC
      procedure HandleControlPwrFail;
      pragma Attach_Handler( HandleControlPwrFail, SIGPWR );

      -- Signal handler for SIGALARM issued from a timer
      procedure HandleAlarm;
      pragma Attach_Handler( HandleAlarm,  SIGALRM );
   end SignalHandler;

   procedure Setitimer(RC:out  Integer; Which: in Integer ;
                       Value: in out T_Itimerval;
                       Ovalue: in out T_Itimerval);
   pragma Import (C,Setitimer);
  pragma Import_Valued_Procedure(Setitimer);

end Timer;

--------------------------------------------------------------
-- Filename: timer.adb
--------------------------------------------------------------
with Timer, System.Address_To_Access_Conversions,Text_IO;
use Timer,Text_Io;
package body Timer is
   protected body SignalHandler is
      -- This protected type contains all our signal handlers
      procedure HandleAlarm is
         -- Alarm signal handler
      begin
         Put_Line( "HandleAlarm: ALARMSIG catched." );
      end HandleAlarm;

      procedure HandleControlPwrFail is
         -- Power fail signal handler
      begin
         Put_Line( "HandleControlPwrFail activated by catched signal SIGPWR" 
);
      end HandleControlPwrFail;
   end SignalHandler;
end Timer;

--------------------------------------------------------------
-- Filename: timer_test.adb
--------------------------------------------------------------
with Text_Io,Timer,Ada.Interrupts,Ada.Interrupts.Names;
use Text_Io,Timer,Ada.Interrupts,Ada.Interrupts.Names;

procedure Timer_Test_B is
   Handler : Parameterless_Handler;
   Counter: Integer := 0;
   Timer: aliased T_Itimerval := ((0,10000),(0,10000));
   OldTimer:  aliased T_Itimerval := ((0,0),(0,0));
   I: Integer := 20;
begin
   Put_Line("Timer_Test");
   Put_Line("==========");


   Timer.It_Value.Tv_Sec := 0;
   Timer.It_Value.Tv_Usec := 100000;
   Timer.It_Interval.Tv_Sec  := 0;
   Timer.It_Interval.Tv_Usec := 100000;

   if Is_Reserved( SIGALRM ) then
      Put_Line( "The ALARMSIG handler is reserved" );
   else
      Put_Line( "The ALARMSIG handler isn't reserved" );
  end if;

   if Is_Attached( SIGALRM ) then
      Put_Line( "The ALARMSIG handler is attached" );
   else
      Put_Line( "The ALARMSIG handler isn't attached" );
   end if;

   if Is_Reserved( SIGPWR ) then
      Put_Line( "The SIGPWR handler is reserved" );
   else
      Put_Line( "The SIGPWR handler isn't reserved" );
   end if;

   if Is_Attached( SIGPWR ) then
      Put_Line( "The SIGPWR handler is attached" );
   else
      Put_Line( "The SIGPWR handler isn't attached" );
   end if;

   New_Line;
   Put_Line( "Testing SIGALRM handler..." );

   Handler := Current_Handler( SIGALRM );
   -- Current_Handler gives a callback to the handler
   Handler.all;
   Put_Line( "End testing SIGALRM handler..." );


   New_Line;
   Put_Line( "Testing SIGPWR handler..." );
   Handler := Current_Handler( SIGPWR );
   -- Current_Handler gives a callback to the handler
   Handler.all;
   Put_Line( "End testing SIGPWR handler..." );
   New_Line;

   Put_Line("Timer parameters");
   Put_Line("----------------");
   Put_Line("Time.sec = " & Timer.It_Value.Tv_Sec'Img );
   Put_Line("Time.usec= " & Timer.It_Value.Tv_Usec'Img );
   Put_Line("Preset.sec = " & Timer.It_Interval.Tv_Sec'Img );
   Put_Line("Preset.usec= " & Timer.It_Interval.Tv_Usec'Img );

   New_Line;
   Put("Arming timer...");

   Setitimer(I,ITIMER_REAL,Timer,OldTimer);
--                 ITimervalPtrs.To_Address(Timer'Unchecked_access),
--                 ITimervalPtrs.To_Address(OldTimer'Unchecked_Access));


   Put_Line("  Timer armed.");
   New_Line;

   Put_Line("I := " & I'Img);
   while (Counter <=  I) loop
      null;
--         Counter := Counter + 1;

--         delay(1.0);
      end loop;

end Timer_Test_B;

-- 
Tilman Gloetzner
ETAS Korea Ltd, Seoul, Korea



^ permalink raw reply	[relevance 6%]

* Re: C array to Ada pointer to unconstrained array without copying memory
  2003-10-07 18:30  4% ` tmoran
@ 2003-10-07 19:24  0%   ` Duncan Sands
  0 siblings, 0 replies; 200+ results
From: Duncan Sands @ 2003-10-07 19:24 UTC (permalink / raw)
  To: tmoran, comp.lang.ada

On Tuesday 07 October 2003 20:30, tmoran@acm.org wrote:
> >subtype Array2 is Ada_Array (1 .. Length);
> >
> >X : Array2;
> >for X'Address use Ptr; -- ok, Ptr should be of type System'Address, but
> > hey!
> >
> >And then you can make use of X.  However being defined on the stack, it
> >can be quite awkward to use.
>
>    I don't understand.  Nothing is defined on, or off, the stack here.

The bounds of X are on the stack if this is in a procedure; sorry I wasn't
clear here (in my head X was declared as a local variable in a procedure,
and that leaked out into the email).

> You are saying that X is at location 12345 (or whatever) in RAM.

That has no meaning - since (GNAT) X has two parts: data and bounds.
The data is at location 12345, the bounds are somewhere else.

> Whether X happens to be in the same area as the stack depends on
> whether (System.Address_to_Access_Conversions .To_Address of) Ptr
> happens to point into the stack or not.
>
> >It would be nice to have the same thing but with X dynamically allocated.
>
>   If Ptr points into your program's heap memory, that's where X will be.
> Or do you mean C is allocating memory, and setting its memory allocation
> structures, and you want an Ada Access type, and Ada's memory allocation
> structures, to be set as if that memory was allocated by an Ada "new"?

Not really.  The fact the memory wasn't allocated by Ada will only be
problematic if it is deallocated by Ada.

> >The problem is the bounds of course.
>
>   If a call to C gave you an address and a length, then those, not a
> constrained array, are what you have to work with.  Just as in C,
> you'll have to write things like
>   if Index in 1 .. Length then
>     Y := X(Index);
>   else
>     raise Constraint_Error;
>   end if;

This may be what you should do - but I'm not asking that.  I'm asking
how to do something unwise, as in your next paragraph.

> >For example, GNAT usually uses
> >fat pointers, consisting of two normal pointers where one points to the
> >data, and the other to the bounds.  So the "clever stuff" will need to
> >allocate some memory to hold the bounds and set up the fat pointer
> >appropriately.
>
>   So you're talking about using embedded assembly language to fake out the
> compiler?  If it's the only way to get to the moon, someone will have to
> put themselves on top of an enormous can of explosives and light the
> outlets.  Most real problems, however, can be solved in less dangerous
> ways.  What's the real problem you are trying to solve here?

Exactly.  Well, there need be no assembly language, just some unchecked
conversions.  As to why, let's just say I enjoy living dangerously.  It seems to
me that such a trick is possible (if not desirable, and not portable between
compilers) - and the degree of danger is not clear to me.  If it can be done,
I would like to know - that doesn't mean I'm going to do it.  Anyway, someone
with a good knowledge of GNAT internals should be able to say if it would work
like a charm or the opposite.

Thanks for your help,

Duncan.



^ permalink raw reply	[relevance 0%]

* Re: C array to Ada pointer to unconstrained array without copying memory
  @ 2003-10-07 18:30  4% ` tmoran
  2003-10-07 19:24  0%   ` Duncan Sands
  0 siblings, 1 reply; 200+ results
From: tmoran @ 2003-10-07 18:30 UTC (permalink / raw)


>subtype Array2 is Ada_Array (1 .. Length);
>
>X : Array2;
>for X'Address use Ptr; -- ok, Ptr should be of type System'Address, but hey!
>
>And then you can make use of X.  However being defined on the stack, it
>can be quite awkward to use.
   I don't understand.  Nothing is defined on, or off, the stack here.
You are saying that X is at location 12345 (or whatever) in RAM.
Whether X happens to be in the same area as the stack depends on
whether (System.Address_to_Access_Conversions .To_Address of) Ptr
happens to point into the stack or not.

>It would be nice to have the same thing but with X dynamically allocated.
  If Ptr points into your program's heap memory, that's where X will be.
Or do you mean C is allocating memory, and setting its memory allocation
structures, and you want an Ada Access type, and Ada's memory allocation
structures, to be set as if that memory was allocated by an Ada "new"?

>The problem is the bounds of course.
  If a call to C gave you an address and a length, then those, not a
constrained array, are what you have to work with.  Just as in C,
you'll have to write things like
  if Index in 1 .. Length then
    Y := X(Index);
  else
    raise Constraint_Error;
  end if;

>For example, GNAT usually uses
>fat pointers, consisting of two normal pointers where one points to the
>data, and the other to the bounds.  So the "clever stuff" will need to
>allocate some memory to hold the bounds and set up the fat pointer
>appropriately.
  So you're talking about using embedded assembly language to fake out the
compiler?  If it's the only way to get to the moon, someone will have to
put themselves on top of an enormous can of explosives and light the
outlets.  Most real problems, however, can be solved in less dangerous
ways.  What's the real problem you are trying to solve here?



^ permalink raw reply	[relevance 4%]

* Re: Limited_Controlled types as 'out' arguments
  2003-07-31 10:54  6%               ` Lutz Donnerhacke
@ 2003-07-31 11:50  0%                 ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2003-07-31 11:50 UTC (permalink / raw)


On Thu, 31 Jul 2003 10:54:44 +0000 (UTC), Lutz Donnerhacke
<lutz@iks-jena.de> wrote:

>* Dmitry A Kazakov wrote:
>>>> 1. to leave "out" parameters uninitialized. This is bad.
>>>
>>>This is the most common implementation on most types. (most = unless you
>>>define an Initialize procedure, default component data, or provide
>>>initialization data)
>>
>> No they all are initialized, but probably with a garbage. (:-))
>
>It's not that funny, if you need those data to manage ressources. Managing
>data which is possibly garbage is very hard.

The point is that formally the constructor exists, though does
nothing. So everything is initialized. You might be just unsatisfied
with the way of a particular initialization is done. Well, I was alone
against chorus chanting "we do not need user constructors for all
types". Wellcome in club. (:-))

>>>3) Finalize the current data of the 'limited out' parameter.
>>>   Adjust the assigned data of the 'unlimited out' paramter after return.
>>
>> It would be inconsistent. Adjust is called after a raw copy is made,
>> your subprogram uses a valid type interface instead. And you better
>> don't do it after Finalize [+ other destructors] were called. Consider
>> a task object as a member of your limited type.
>
>I still do not get it completely.
>
>------------------------------------------------------------------------
>with Ada.Finalization;
>
>package t1 is
>   type Char_Access is access Character;
>   type Test is new Ada.Finalization.Limited_Controlled with record
>      a : Char_Access;
>   end record;
>   procedure Initialize(o : in out Test);
>   procedure Finalize(o : in out Test);
>   procedure Set(o1, o2 : out Test; i : Test);
>end t1;
>------------------------------------------------------------------------
>with Ada.Text_IO;
>with System.Storage_Elements, System.Address_To_Access_Conversions;
>with Unchecked_Deallocation;
>use Ada.Text_IO;
>
>package body t1 is
>   procedure Debug (msg : String; p : Char_Access) is
>      use System.Storage_Elements;
>      package Convert is new System.Address_To_Access_Conversions(Character);
>   begin
>      Put_Line(msg &
>        Integer_Address'Image(To_Integer(
>            Convert.To_Address(Convert.Object_Pointer(p)))) &
>        '(' & p.all & ')');
>   end Debug;
>   
>   global : Character := '0';
>   
>   procedure Initialize(o : in out Test) is
>   begin
>      o.a := new Character'(global);
>      Debug("Initializing", o.a);
>      global := Character'Succ(global);
>   end Initialize;
>   
>   procedure Free is new Unchecked_Deallocation(Character, Char_Access);
>   procedure Finalize(o : in out Test) is
>   begin
>      Debug("Finalizing  ", o.a);
>      Free(o.a);
>   end Finalize;
>   
>   procedure Set(o1, o2 : out Test; i : Test) is
>   begin
>      Debug("Setting from", i.a);
>      Debug("Setting o1  ", o1.a);
>      Debug("Setting o2  ", o2.a);
>      Finalize(o1);
>      Finalize(o2);
>      
>      o1.a := new Character'(global);
>      Debug("Setting to1 ", o1.a);
>      global := Character'Succ(global);
>
>      o2.a := new Character'(i.a.all);
>      Debug("Setting to2 ", o2.a);
>   end Set;
>end t1;
>------------------------------------------------------------------------
>with t1;
>use t1;
>
>procedure t is
>   a, b : Test;
>begin
>   Set(a, a, b);
>end t;
>------------------------------------------------------------------------
>
>Results in:
>Initializing 134630800(0)
>Initializing 134630816(1)
>Setting from 134630816(1)
>Setting o1   134630800(0)
>Setting o2   134630800(0)
>Finalizing   134630800(0)
>raised PROGRAM_ERROR : t1.adb:14
>Finalizing   134630816(1)
>
>I'am mad?

Sort of, if you are calling Finalize from a normal subprogram! (:-))
As for error, you call Set (a, a, b); which finalizes a twice! It is a
language design fault that a destructor can be called explicitly. Your
example shows why.

---
Regards,
Dmitry Kazakov
www.dmitry-kazakov.de



^ permalink raw reply	[relevance 0%]

* Re: Limited_Controlled types as 'out' arguments
  @ 2003-07-31 10:54  6%               ` Lutz Donnerhacke
  2003-07-31 11:50  0%                 ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Lutz Donnerhacke @ 2003-07-31 10:54 UTC (permalink / raw)


* Dmitry A Kazakov wrote:
>>> 1. to leave "out" parameters uninitialized. This is bad.
>>
>>This is the most common implementation on most types. (most = unless you
>>define an Initialize procedure, default component data, or provide
>>initialization data)
>
> No they all are initialized, but probably with a garbage. (:-))

It's not that funny, if you need those data to manage ressources. Managing
data which is possibly garbage is very hard.

>>Discriminants of 'out' types have mode 'in'. Always.
>
> Not always:
>
> type A (I : Integer := 10) is null record;

Ok.

>>3) Finalize the current data of the 'limited out' parameter.
>>   Adjust the assigned data of the 'unlimited out' paramter after return.
>
> It would be inconsistent. Adjust is called after a raw copy is made,
> your subprogram uses a valid type interface instead. And you better
> don't do it after Finalize [+ other destructors] were called. Consider
> a task object as a member of your limited type.

I still do not get it completely.

------------------------------------------------------------------------
with Ada.Finalization;

package t1 is
   type Char_Access is access Character;
   type Test is new Ada.Finalization.Limited_Controlled with record
      a : Char_Access;
   end record;
   procedure Initialize(o : in out Test);
   procedure Finalize(o : in out Test);
   procedure Set(o1, o2 : out Test; i : Test);
end t1;
------------------------------------------------------------------------
with Ada.Text_IO;
with System.Storage_Elements, System.Address_To_Access_Conversions;
with Unchecked_Deallocation;
use Ada.Text_IO;

package body t1 is
   procedure Debug (msg : String; p : Char_Access) is
      use System.Storage_Elements;
      package Convert is new System.Address_To_Access_Conversions(Character);
   begin
      Put_Line(msg &
        Integer_Address'Image(To_Integer(
            Convert.To_Address(Convert.Object_Pointer(p)))) &
        '(' & p.all & ')');
   end Debug;
   
   global : Character := '0';
   
   procedure Initialize(o : in out Test) is
   begin
      o.a := new Character'(global);
      Debug("Initializing", o.a);
      global := Character'Succ(global);
   end Initialize;
   
   procedure Free is new Unchecked_Deallocation(Character, Char_Access);
   procedure Finalize(o : in out Test) is
   begin
      Debug("Finalizing  ", o.a);
      Free(o.a);
   end Finalize;
   
   procedure Set(o1, o2 : out Test; i : Test) is
   begin
      Debug("Setting from", i.a);
      Debug("Setting o1  ", o1.a);
      Debug("Setting o2  ", o2.a);
      Finalize(o1);
      Finalize(o2);
      
      o1.a := new Character'(global);
      Debug("Setting to1 ", o1.a);
      global := Character'Succ(global);

      o2.a := new Character'(i.a.all);
      Debug("Setting to2 ", o2.a);
   end Set;
end t1;
------------------------------------------------------------------------
with t1;
use t1;

procedure t is
   a, b : Test;
begin
   Set(a, a, b);
end t;
------------------------------------------------------------------------

Results in:
Initializing 134630800(0)
Initializing 134630816(1)
Setting from 134630816(1)
Setting o1   134630800(0)
Setting o2   134630800(0)
Finalizing   134630800(0)
raised PROGRAM_ERROR : t1.adb:14
Finalizing   134630816(1)

I'am mad?



^ permalink raw reply	[relevance 6%]

* Re: Limited_Controlled types as 'out' arguments
    @ 2003-07-30 15:52  5%         ` Lutz Donnerhacke
  1 sibling, 0 replies; 200+ results
From: Lutz Donnerhacke @ 2003-07-30 15:52 UTC (permalink / raw)


* Lutz Donnerhacke wrote:
> * Dmitry A Kazakov wrote:
>> On Wed, 30 Jul 2003 12:32:17 +0000 (UTC), Lutz Donnerhacke
>>>In my implementation, the type Test contains an array_access, I have to
>>>deallocate, before assigning a new value. I can not deallocate this access
>>>variable, because the procedure Free (unchecked_deallocate) requires an
>>>'in out' Parameter. But I only have an 'out' paramter. So I can't read it,
>>>before the first write.
>>
>> You can in Ada 95.
> 
> Oops. Why? This is a clear data flow error, which should be avoided.

To stress this point even more. The approbriate counterpart using assignment
statments and controlled types result in:

------------------------------------------------------------------------
with Ada.Finalization;

package t1 is
   type Char_Access is access Character;
   type Test is new Ada.Finalization.Controlled with record
      a : Char_Access;
   end record;
   procedure Initialize(o : in out Test);
   procedure Finalize(o : in out Test);
   procedure Adjust(o : in out Test);
end t1;
------------------------------------------------------------------------
with t1;
use t1;

procedure t is
   a, b, c : Test;
begin
   a := b;
   a := c;
end t;
------------------------------------------------------------------------
with Ada.Text_IO;
with System.Storage_Elements, System.Address_To_Access_Conversions;
with Unchecked_Deallocation;
use Ada.Text_IO;

package body t1 is
   procedure Debug (msg : String; p : Char_Access) is
      use System.Storage_Elements;
      package Convert is new System.Address_To_Access_Conversions(Character);
   begin
      Put_Line(msg &
        Integer_Address'Image(To_Integer(
            Convert.To_Address(Convert.Object_Pointer(p)))) &
        '(' & p.all & ')');
   end Debug;
   
   global : Character := '0';
   
   procedure Initialize(o : in out Test) is
   begin
      o.a := new Character'(global);
      Debug("Initializing", o.a);
      global := Character'Succ(global);
   end Initialize;
   
   procedure Finalize(o : in out Test) is
      procedure Free is new Unchecked_Deallocation(Character, Char_Access);
   begin
      Debug("Finalizing", o.a);
      Free(o.a);
   end Finalize;
   
   procedure Adjust(o : in out Test) is
      procedure Free is new Unchecked_Deallocation(Character, Char_Access);
      tmp : Char_Access := new Character'(' '); -- occupy some memory
   begin
      Debug("Adjusting from", o.a);
      o.a := new Character'(o.a.all);
      Debug("Adjusting to  ", o.a);
      Free(tmp);
   end Adjust;
end t1;
------------------------------------------------------------------------

Results in:
  Initializing 134630032(0)
  Initializing 134630048(1)
  Initializing 134630064(2)
  Finalizing 134630032(0)
  Adjusting from 134630048(1)
  Adjusting to   134630080(1)
  Finalizing 134630080(1)
  Adjusting from 134630064(2)
  Adjusting to   134630032(2)
  Finalizing 134630064(2)
  Finalizing 134630048(1)
  Finalizing 134630032(2)

Despite the upthead argument "there are only three instances, so finalizing
them suffice", here are also only three instances, which are finalized before
assigment.

Trying it with an 'out' parameter
   procedure Set(o : out Test) is
   begin
      Debug("Setting from", o.a);
      o.a := new Character'(global);
      Debug("Setting to  ", o.a);
      global := Character'Succ(global);
   end Set;
[...]
with t1;
use t1;

procedure t is
   a, b, c : Test;
begin
   a := b;
   a := c;
   Set(a);
   Set(a);
end t;
------------------------------------------------------------------------

gives:
  Initializing 134630064(0)
  Initializing 134630080(1)
  Initializing 134630096(2)
  Finalizing 134630064(0)
  Adjusting from 134630080(1)
  Adjusting to   134630112(1)
  Finalizing 134630112(1)
  Adjusting from 134630096(2)
  Adjusting to   134630064(2)
  Setting from 134630064(2)
  Setting to   134630112(3)
  Setting from 134630112(3)
  Setting to   134630128(4)
  Finalizing 134630096(2)
  Finalizing 134630080(1)
  Finalizing 134630128(4)
  
which is clearly wrong in the same way.

So the only result of this can be: Do not provide 'out' Parameters to
controlled types in the same library unit.



^ permalink raw reply	[relevance 5%]

* Re: Limited_Controlled types as 'out' arguments
  @ 2003-07-30 12:57  6%   ` Lutz Donnerhacke
  0 siblings, 0 replies; 200+ results
From: Lutz Donnerhacke @ 2003-07-30 12:57 UTC (permalink / raw)


* Matthew Heaney wrote:
> Controlled types, like all tagged types, are passed by reference.

'out' Parameters can't be read.

> Three objects (a, b, c) are Initialize'd , and the same three objects are
> Finalize'd.
> 
> Which objects do you think aren't being finalized?

Extended example:
------------------------------------------------------------------------
with Ada.Finalization;

package t1 is
   type Char_Access is access Character;
   type Test is new Ada.Finalization.Limited_Controlled with record
      a : Char_Access;
   end record;
   procedure Initialize(o : in out Test);
   procedure Finalize(o : in out Test);
   procedure Copy(to : out Test; from : Test);
end t1;
------------------------------------------------------------------------
with t1;
use t1;

procedure t is
   a, b, c : Test;
begin
   Copy(a, b);
   Copy(a, c);
end t;
------------------------------------------------------------------------
with Ada.Text_IO;
with System.Storage_Elements, System.Address_To_Access_Conversions;
with Unchecked_Deallocation;
use Ada.Text_IO;

package body t1 is
   procedure Debug (msg : String; p : Char_Access) is
      use System.Storage_Elements;
      package Convert is new System.Address_To_Access_Conversions(Character);
   begin
      Put_Line(msg &
        Integer_Address'Image(To_Integer(
            Convert.To_Address(Convert.Object_Pointer(p)))) &
        '(' & p.all & ')');
   end Debug;
   
   global : Character := '0';
   
   procedure Initialize(o : in out Test) is
   begin
      o.a := new Character'(global);
      Debug("Initializing", o.a);
      global := Character'Succ(global);
   end Initialize;
   
   procedure Finalize(o : in out Test) is
      procedure Free is new Unchecked_Deallocation(Character, Char_Access);
   begin
      Debug("Finalizing", o.a);
      Free(o.a);
   end Finalize;
   
   procedure Copy(to : out Test; from : Test) is
   begin
      to.a := new Character'(global);
      Debug("Copying from", from.a);
      Debug("Copying to  ", to.a);
      global := Character'Succ(global);
   end Copy;
end t1;
------------------------------------------------------------------------


Results in a beautiful memory leak:
   Initializing 134630832(0)
   Initializing 134630848(1)
   Initializing 134630864(2)
   Copying from 134630848(1)
   Copying to   134630880(3)
   Copying from 134630864(2)
   Copying to   134630896(4)
   Finalizing 134630864(2)
   Finalizing 134630848(1)
   Finalizing 134630896(4)

134630832 and 134630880 are never freed.



^ permalink raw reply	[relevance 6%]

* Re: sqlite binding
  @ 2003-07-07 14:16  5% ` Andreas Almroth
  0 siblings, 0 replies; 200+ results
From: Andreas Almroth @ 2003-07-07 14:16 UTC (permalink / raw)


Ching Bon Lam wrote:
> hello everyone,
> 
> I've been trying to make some sort of sqlite binding. SQLite itself is at 
> http://www.sqlite.org/ . For now i just want to import the core api 
> consisting of three functions (taken from sqlite.h):
> 
> -- Code -----------------------------------------------------------------
> 
> sqlite *sqlite_open(const char *filename, int mode, char **errmsg);
> 

function Sqlite_Open(Filename : in Interfaces.C.Strings.Chars_Ptr;
		     mode     : Interfaces.C.Int;
                      Errmsg   : access interfaces.C.Strings.Chars_Ptr)
		return Sqlite_T;
pragma Import(C,Sqlite_Open,"sqlite_open);

> void sqlite_close(sqlite *);
> 
> int sqlite_exec(
>   sqlite*,          /* An open database */
>   const char *sql,  /* SQL to be executed */
>   sqlite_callback,  /* Callback function */
>   void *,           /* 1st argument to callback function */
>   char **errmsg     /* Error msg written here */
> );
> 
> -------------------------------------------------------------------------
> 
> with:
> 
> -- Code -----------------------------------------------------------------
> 
> typedef struct sqlite sqlite; /* opaque struct */
> typedef int (*sqlite_callback)(void*,int,char**, char**);
> 
> -------------------------------------------------------------------------
> 
> What I did till now is:
> 
> -- Code -----------------------------------------------------------------
> 
> -- typedef struct sqlite sqlite; /* opaque struct */
> subtype sqlite is Interfaces.C.Extensions.opaque_structure_def;
> 

Without knowing the details, but I would probably use System.Address as
pointer, so;

type Sqlite_T is System.Address;

This takes that you will never access anything within the record, and 
only reference it as pointer.

As for the callback, you define a type for the callback pointer;

type Sqlite_Callback_T is access function(P  : System.Address;
					  I  : Interfaces.C.Int;
					  C1 : System.Address;
					  C2 : System.Address)
					return Interfaces.C.Int;

OK,ok, using System.Address is a bit of a hack, but one should probably 
look into using access interfaces.c.strings.chars_ptr instead.
Could make it easier instead of using 
System.Address_To_Access_Conversions feature...


> -------------------------------------------------------------------------
> 
> i don't know how to do the rest with the tons of pointers as arguments..
> if someone would give me some pointers/guidance/hints, i would be really 
> grateful.
> 
> greetings,
> CBL


Cheers,
Andreas




^ permalink raw reply	[relevance 5%]

* Re: The old "Object.Method" syntax debate
  @ 2003-05-28 12:36  5%                     ` Lutz Donnerhacke
  0 siblings, 0 replies; 200+ results
From: Lutz Donnerhacke @ 2003-05-28 12:36 UTC (permalink / raw)


* Dmitry A. Kazakov wrote:
> However, overriding attributes raises an interestring question of making
> everything that could appear on the left side of an attribute a first-class
> object.

Furthermore it allows an envolving solution to the original question:

Drop the restriction which attributes are allowed. Several attributes might
have a predefined meaning, but other than the predefined attributes might be
allowed in Ada200x.

So if you want to apply an 'object.method' syntax, do

  type object ...;
  procedure method(a : in out object; ...);
  for object'method use method;

done.

But there are more important features missing an Ada 95:
************************************************************************
Newsgroups: comp.lang.ada
Subject: AdaYY wish list from current projects
Organization: IKS GmbH Jena
Message-ID: <96ulad$r9e$1@belenus.iks-jena.de>

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; 
************************************************************************

There is an interesting discussion on the usual archives following this
proposal.



^ permalink raw reply	[relevance 5%]

* Re: Allocating Memory with "new"
  @ 2003-04-25 22:19  6% ` Peter Richtmyer
  0 siblings, 0 replies; 200+ results
From: Peter Richtmyer @ 2003-04-25 22:19 UTC (permalink / raw)


Thanks, all the responses have been helpful, and I have tried to
incorporate
the suggestions.

So my new (still ugly) solution, for 1 to 256 bytes (thats enough for
me):

with system;
with System.Storage_Elements;
with system.address_to_access_conversions;
with Text_Io;
use  text_io;
with unchecked_conversion;

procedure Hi is
    
    subtype mem_bytes is natural range 1 .. 256; 
    type nat_8 is new natural range 0 .. 255;
    for nat_8'size use 8;    

    type array_t is array (nat_8 range <>) of character;
     
    type Mem_Block_T ( n_minus_1 : nat_8) is 
       record
         t : array_t (1 .. n_minus_1);
       end record;   
    for Mem_Block_T use 
       record
         n_minus_1 at 0 range 0 .. 7;
       end record;
    pragma pack (Mem_Block_T);    
     
    package Mem_Block_Ptr_Pkg is new
system.address_to_access_conversions (Mem_Block_T);

    Mem_Block_Ptr :  Mem_Block_Ptr_Pkg.Object_Pointer := null;
    --------------------------------------------------------------------
    procedure alloc (nbytes : mem_bytes) is
    
      n_minus_1 : nat_8 := nat_8 (nbytes - 1);
	
	addr : system.address;
	
	In_Work_Area : String (1 .. 12) := "            ";
	        
        package data_io is new integer_io(integer);    
         			   
	    
     begin     
                    
	Mem_Block_Ptr := new Mem_Block_T (n_minus_1);
	Addr := Mem_Block_Ptr_Pkg.to_address (Mem_Block_Ptr);
      put ("Bytes allocated: " & Integer'image(Mem_Block_Ptr.all'size
/ 8));

	Data_Io.Put (In_Work_Area, Integer(System.Storage_Elements.to_integer
(addr)), 16);
	put_line (" at " & In_Work_Area);
	
     end alloc;
     --------------------------------------------------------------------
begin 
    
    for i in 1 .. 256 loop
      Put ("len" & integer'image(i) & " : ");
      alloc (i);
    end loop; 

end Hi;

============================
some output:

len 1 : Bytes allocated:  1 at  16#2602450#
len 2 : Bytes allocated:  2 at  16#2602520#
len 3 : Bytes allocated:  3 at  16#2602538#
len 4 : Bytes allocated:  4 at  16#2602550#
len 5 : Bytes allocated:  5 at  16#2602568#
           .              .
           :              :
len 252 : Bytes allocated:  252 at  16#260C140#
len 253 : Bytes allocated:  253 at  16#260C248#
len 254 : Bytes allocated:  254 at  16#260C350#
len 255 : Bytes allocated:  255 at  16#260C458#
len 256 : Bytes allocated:  256 at  16#260C560#



^ permalink raw reply	[relevance 6%]

* Re: Allocating Memory with "new"
  2003-04-24 19:30  5% Allocating Memory with "new" Peter Richtmyer
@ 2003-04-25  6:05  0% ` Vincent Smeets
  0 siblings, 0 replies; 200+ results
From: Vincent Smeets @ 2003-04-25  6:05 UTC (permalink / raw)


Hello,

I would say that the Sun version is correct! You defined the package
Mem_Block_Ptr_Pkg inside the procedure alloc. Every time the procedure is
left, the package becomes out of scope and so does the access type defined
in that package. The next time you call the procedure, a new package will be
instantiated and with that a new access type will be defined.

Every time an access type comes out of scope, the memory allocated by that
access type can be freed (garbage collection).

Conclusion:
Your program is erroneous.
Move the package Mem_Block_Ptr_Pkg to an outer scoop.



Vincent Smeets

"Peter Richtmyer" <prichtmyer@yahoo.com> wrote in message
news:1b585154.0304241130.35fa0a97@posting.google.com...
> I am stumped ...
>
> My memory allocation scheme worked OK on Gnat / Win2K,
> but on Sun Blade with Rational Ada it does not give me
> what I expected. See after program for output.
>
> I built a test program to illustrate my problem:
> (forgive me, it is quick and ugly)
>
> thanks
> Peter
> --------------------------------------------------------------
> with system;
> with system.address_to_access_conversions;
> with Text_Io;
> use  text_io;
> with unchecked_conversion;
>
> procedure Hi is
>
>     first_time : boolean := true;
>
>     procedure alloc (nbytes : integer) is
>
>         type Mem_Block_T is array (1 .. Nbytes) of Character;
>         package Mem_Block_Ptr_Pkg is new
>              system.address_to_access_conversions (Mem_Block_T);
> Mem_Block_Ptr :  Mem_Block_Ptr_Pkg.Object_Pointer := null;
>
> addr : system.address;
>
> In_Work_Area : String (1 .. 12) := "            ";
>
>         function Addr_to_int is new Unchecked_Conversion
>             (system.address, integer);
>
>         package data_io is new integer_io(integer);
>
>      begin
>         if first_time then
>            first_time := false;
>            put_line ("Mem_Block_Ptr_Pkg.Object_Pointer'size = " &
>                 Integer'image(Mem_Block_Ptr_Pkg.Object_Pointer'size));
>         end if;
>
> Mem_Block_Ptr := new Mem_Block_T;
> Addr := Mem_Block_Ptr_Pkg.to_address (Mem_Block_Ptr);
>
> Data_Io.Put (In_Work_Area, addr_to_int (addr), 16);
> put_line ("allocated " & In_Work_Area);
>
>      end alloc;
>
>
> begin
>
>     put_line ("system.address'size = " &
Integer'image(system.address'size));
>     put_line ("integer'size = " & Integer'image(integer'size));
>
>     for i in 1 .. 10 loop
>       Put ("len 1: ");
>       alloc (1);
>     end loop;
>
>     for i in 1 .. 10 loop
>       Put ("len 8: ");
>       alloc (8);
>     end loop;
>
>      for i in 1 .. 50 loop
>       Put ("len" & integer'image(i * 8) & " : ");
>       alloc (i * 8);
>     end loop;
>
> end Hi;
>
> -- Rational Apex Ada on SUN Blade:
>
> -- system.address'size =  32
> -- integer'size =  32
> -- len 1: Mem_Block_Ptr_Pkg.Object_Pointer'size =  32
> -- allocated    16#F8A88#
> -- len 1: allocated    16#F8A88#
> -- len 1: allocated    16#F8A88#
> -- len 1: allocated    16#F8A88#
> -- len 1: allocated    16#F8A88#
> -- len 1: allocated    16#F8A88#
> -- len 1: allocated    16#F8A88#
> -- len 1: allocated    16#F8A88#
> -- len 1: allocated    16#F8A88#
> -- len 1: allocated    16#F8A88#
> -- len 8: allocated    16#F8A88#
> -- len 8: allocated    16#F8A88#
> -- len 8: allocated    16#F8A88#
> -- len 8: allocated    16#F8A88#
> -- len 8: allocated    16#F8A88#
> -- len 8: allocated    16#F8A88#
> -- len 8: allocated    16#F8A88#
> -- len 8: allocated    16#F8A88#
> -- len 8: allocated    16#F8A88#
> -- len 8: allocated    16#F8A88#
> -- len 8 : allocated    16#F8A88#
> -- len 16 : allocated    16#F8A80#
> -- len 24 : allocated    16#F8A78#
> -- len 32 : allocated    16#F8A70#
> -- len 40 : allocated    16#F8A68#
> -- len 48 : allocated    16#F8A60#
> -- len 56 : allocated    16#F8A58#
> -- len 64 : allocated    16#F8A50#
> -- len 72 : allocated    16#F8A48#
> -- len 80 : allocated    16#F8A40#
> -- len 88 : allocated    16#F8A38#
> -- len 96 : allocated    16#F8A30#
>
> -- continues decreasing by 8
>
> -------------------------------------------------------
> -- Gnat 3.15P on Win2000       (OK)
>
> --system.address'size =  32
> --integer'size =  32
> --len 1: Mem_Block_Ptr_Pkg.Object_Pointer'size =  32
> --allocated  16#2602450#
> --len 1: allocated  16#2602520#
> --len 1: allocated  16#2602538#
> --len 1: allocated  16#2602550#
> --len 1: allocated  16#2602568#
> --len 1: allocated  16#2602580#
> --len 1: allocated  16#2602598#
> --len 1: allocated  16#26025B0#
> --len 1: allocated  16#26025C8#
> --len 1: allocated  16#26025E0#
> --len 8: allocated  16#26025F8#
> --len 8: allocated  16#2602610#
> --len 8: allocated  16#2602628#
> --len 8: allocated  16#2602640#
> --len 8: allocated  16#2602658#
> --len 8: allocated  16#2602670#
> --len 8: allocated  16#2602688#
> --len 8: allocated  16#26026A0#
> --len 8: allocated  16#26026B8#
> --len 8: allocated  16#26026D0#
> --len 8 : allocated  16#26026E8#
> --len 16 : allocated  16#2602700#
> --len 24 : allocated  16#2602718#
> --len 32 : allocated  16#2602740#
> --len 40 : allocated  16#2602768#
> --len 48 : allocated  16#26027A0#
> --len 56 : allocated  16#26027D8#
> --len 64 : allocated  16#2602820#
> --len 72 : allocated  16#26039C8#
> --len 80 : allocated  16#2603A20#
> --len 88 : allocated  16#2603A78#
> --len 96 : allocated  16#2603AE0#
> --len 104 : allocated  16#2603B48#
> --len 112 : allocated  16#2603BC0#
> --len 120 : allocated  16#2603C38#
> --len 128 : allocated  16#2603CC0#
> --len 136 : allocated  16#2603D48#




^ permalink raw reply	[relevance 0%]

* Allocating Memory with "new"
@ 2003-04-24 19:30  5% Peter Richtmyer
  2003-04-25  6:05  0% ` Vincent Smeets
  0 siblings, 1 reply; 200+ results
From: Peter Richtmyer @ 2003-04-24 19:30 UTC (permalink / raw)


I am stumped ...

My memory allocation scheme worked OK on Gnat / Win2K,
but on Sun Blade with Rational Ada it does not give me
what I expected. See after program for output.

I built a test program to illustrate my problem:
(forgive me, it is quick and ugly)

thanks
Peter
--------------------------------------------------------------
with system;
with system.address_to_access_conversions;
with Text_Io;
use  text_io;
with unchecked_conversion;

procedure Hi is

    first_time : boolean := true;
    
    procedure alloc (nbytes : integer) is
    
        type Mem_Block_T is array (1 .. Nbytes) of Character;
        package Mem_Block_Ptr_Pkg is new 
             system.address_to_access_conversions (Mem_Block_T);
	Mem_Block_Ptr :  Mem_Block_Ptr_Pkg.Object_Pointer := null;
	
	addr : system.address;
	
	In_Work_Area : String (1 .. 12) := "            ";
	
        function Addr_to_int is new Unchecked_Conversion
         			   (system.address, integer);
        
        package data_io is new integer_io(integer);    
         			   
     begin
        if first_time then
           first_time := false;
           put_line ("Mem_Block_Ptr_Pkg.Object_Pointer'size = " & 
                Integer'image(Mem_Block_Ptr_Pkg.Object_Pointer'size));
        end if;
                    
	Mem_Block_Ptr := new Mem_Block_T;
	Addr := Mem_Block_Ptr_Pkg.to_address (Mem_Block_Ptr);

	Data_Io.Put (In_Work_Area, addr_to_int (addr), 16);
	put_line ("allocated " & In_Work_Area);
	
     end alloc;


begin 

    put_line ("system.address'size = " & Integer'image(system.address'size));
    put_line ("integer'size = " & Integer'image(integer'size));

    for i in 1 .. 10 loop
      Put ("len 1: ");
      alloc (1);
    end loop; 
    
    for i in 1 .. 10 loop
      Put ("len 8: ");
      alloc (8);
    end loop; 
    
     for i in 1 .. 50 loop
      Put ("len" & integer'image(i * 8) & " : ");
      alloc (i * 8);
    end loop; 

end Hi;

-- Rational Apex Ada on SUN Blade:

-- system.address'size =  32
-- integer'size =  32
-- len 1: Mem_Block_Ptr_Pkg.Object_Pointer'size =  32
-- allocated    16#F8A88#
-- len 1: allocated    16#F8A88#
-- len 1: allocated    16#F8A88#
-- len 1: allocated    16#F8A88#
-- len 1: allocated    16#F8A88#
-- len 1: allocated    16#F8A88#
-- len 1: allocated    16#F8A88#
-- len 1: allocated    16#F8A88#
-- len 1: allocated    16#F8A88#
-- len 1: allocated    16#F8A88#
-- len 8: allocated    16#F8A88#
-- len 8: allocated    16#F8A88#
-- len 8: allocated    16#F8A88#
-- len 8: allocated    16#F8A88#
-- len 8: allocated    16#F8A88#
-- len 8: allocated    16#F8A88#
-- len 8: allocated    16#F8A88#
-- len 8: allocated    16#F8A88#
-- len 8: allocated    16#F8A88#
-- len 8: allocated    16#F8A88#
-- len 8 : allocated    16#F8A88#
-- len 16 : allocated    16#F8A80#
-- len 24 : allocated    16#F8A78#
-- len 32 : allocated    16#F8A70#
-- len 40 : allocated    16#F8A68#
-- len 48 : allocated    16#F8A60#
-- len 56 : allocated    16#F8A58#
-- len 64 : allocated    16#F8A50#
-- len 72 : allocated    16#F8A48#
-- len 80 : allocated    16#F8A40#
-- len 88 : allocated    16#F8A38#
-- len 96 : allocated    16#F8A30#

-- continues decreasing by 8

-------------------------------------------------------
-- Gnat 3.15P on Win2000       (OK)

--system.address'size =  32
--integer'size =  32
--len 1: Mem_Block_Ptr_Pkg.Object_Pointer'size =  32
--allocated  16#2602450#
--len 1: allocated  16#2602520#
--len 1: allocated  16#2602538#
--len 1: allocated  16#2602550#
--len 1: allocated  16#2602568#
--len 1: allocated  16#2602580#
--len 1: allocated  16#2602598#
--len 1: allocated  16#26025B0#
--len 1: allocated  16#26025C8#
--len 1: allocated  16#26025E0#
--len 8: allocated  16#26025F8#
--len 8: allocated  16#2602610#
--len 8: allocated  16#2602628#
--len 8: allocated  16#2602640#
--len 8: allocated  16#2602658#
--len 8: allocated  16#2602670#
--len 8: allocated  16#2602688#
--len 8: allocated  16#26026A0#
--len 8: allocated  16#26026B8#
--len 8: allocated  16#26026D0#
--len 8 : allocated  16#26026E8#
--len 16 : allocated  16#2602700#
--len 24 : allocated  16#2602718#
--len 32 : allocated  16#2602740#
--len 40 : allocated  16#2602768#
--len 48 : allocated  16#26027A0#
--len 56 : allocated  16#26027D8#
--len 64 : allocated  16#2602820#
--len 72 : allocated  16#26039C8#
--len 80 : allocated  16#2603A20#
--len 88 : allocated  16#2603A78#
--len 96 : allocated  16#2603AE0#
--len 104 : allocated  16#2603B48#
--len 112 : allocated  16#2603BC0#
--len 120 : allocated  16#2603C38#
--len 128 : allocated  16#2603CC0#
--len 136 : allocated  16#2603D48#



^ permalink raw reply	[relevance 5%]

* Re: Q re pack & aliased
  @ 2003-04-23 17:18  4% ` tmoran
  0 siblings, 0 replies; 200+ results
From: tmoran @ 2003-04-23 17:18 UTC (permalink / raw)


|   x : bunches (1 .. 10);
|   for x'Size use 240;
  Unfortunately, one rarely knows the width of an image file at
compile time.  What does your program print with and without
the "for x'Size use 240;"?

>a conversion between a 24-bit-type like you used before and the
>triples-record is quite easy without breaking too much...
  I'm sorry if that wasn't clear.  My "24-bit-type" is indeed
a record, just like your example.  The sole difference is the
addition of a specific layout for the color components:
    for Triple_Color_Type use record
        Blue  at 0 range 0 .. 7;
        Green at 1 range 0 .. 7;
        Red   at 2 range 0 .. 7;
    end record;

Dropping the word "aliased" and changing to:
--  type Triple_Color_Ptr_Type is access all Triple_Color_Type;
    package Gnat315_Workaround
      is new System.Address_To_Access_Conversions(Object=>Triple_Color_Type);
    subtype Triple_Color_Ptr_Type is Gnat315_Workaround.Object_Pointer;
    ...
    Image_Ptr : Triple_Color_Ptr_Type
--      := x(i)'Unchecked_Access;
      := Gnat315_Workaround.To_Pointer
           (x(i)'address);
makes the program work under Gnat, at the expense of ugliness, additional
special case documentation, and obscuring the fact that pixels are aliased.



^ permalink raw reply	[relevance 4%]

* Re: Q re pack & aliased
  @ 2003-04-22 22:25  4% ` tmoran
  0 siblings, 0 replies; 200+ results
From: tmoran @ 2003-04-22 22:25 UTC (permalink / raw)


>Seems like the old and new behavior are the same.  In both versions, the
>compiler refuses to pack aliased 24-bit components.  Or did I
>misunderstand the ealier posting?
  3.15p (& 3.16a) refuses to pack.  It generates a warning and then
ignores the pragma pack.  Replacing pragma pack with "'component_size
use 24" causes a fatal compilation error.
Prior to 3.15, it packed automatically without being asked (the
components have for xxx'size use 24, which I thought suggests that
I want them to be 24, not 32, bits.).  Janus similarly automatically
packs.  I tried it on OA 7.2.2 where pragma pack is silently ignored,
but 'component_size is properly obeyed without complaint.

>But it's not fine to make X.all slow even when X points to a component
>of an unpacked array, or into the heap.
  It's even less fine to make the program no longer run.  Something about
"make it work right, then worry about speed" ;)

  The original question was "How can I get around this limitation."
System.Address_To_Access_Conversions comes to mind, but seems awfully
heavy handed.  Compiling with no optimization makes no difference.



^ permalink raw reply	[relevance 4%]

* Re: "access constant" discriminant
  @ 2003-02-20  2:17  4% ` Matthew Heaney
  0 siblings, 0 replies; 200+ results
From: Matthew Heaney @ 2003-02-20  2:17 UTC (permalink / raw)


tmoran@acm.org wrote in message news:<lnJ1a.50689$SD6.3473@sccrnsc03>...
> Can this be done?  How?

I discuss how in my design patterns tutorial, which I'll be giving in
Toulouse in June.

You basically have two options:

1) If your type is limited, you can use the Rosen Trick:


type T;

type Handle_Type (O : access T) is 
   limited null record;

type T is
   limited record
      H : Handle_Type (T'Access);
      <other components here>
   end record;

Now you can do this:

procedure Op (Read_Only : in T) is
 
   Read_Write : T renames Read_Only.H.O.all;
begin
   <modify Read_Write as necessary>
end;

This is completly portable and safe.


2) If your type isn't limited, you can't use the Rosen Trick.  But you
can do something similar if you have a pass-by-reference type.

Tagged types are pass-by-reference, as are types with volatile
components.

So you do something like this:

type T is tagged record ... end record;

package P is
   new System.Address_To_Access_Conversions (T);

procedure Op (Read_Only : in T) is

   Pointer : constant P.Object_Pointer := 
      P.To_Pointer (Read_Only'Address);

   Read_Write : T renames Pointer.all;
begin
   <modify Read_Write as necessary>
end;


You might also be able to use the GNAT 'Unrestricted_Access attribute.

It is indeed unfortunate that method #2 requires that we circumvent
the type system just to cast away const.  The GNAT attribute has the
benefit that strong typing is preserved.

I acually use the Rosen Trick to implement the bounded vectors in the
Charles library.  Incredibly, types whose full view is limited aren't
implicitly aliased when passed as subprogram parameters (that's only
true for tagged types -- don't ask me why...), so you need to use the
Rosen Trick to get an aliased view.

http://home.earthlink.net/~matthewjheaney/charles/charles-vectors-bounded.html
http://home.earthlink.net/~matthewjheaney/charles/index.html



^ permalink raw reply	[relevance 4%]

* Re: AdaSDL and glTexImage2D
  2003-01-29 20:15  6% ` Chad R. Meiners
@ 2003-01-30  9:52  0%   ` Stefan Soos
  0 siblings, 0 replies; 200+ results
From: Stefan Soos @ 2003-01-30  9:52 UTC (permalink / raw)


Hello,

On Wed, 29 Jan 2003 15:15:44 -0500, Chad R. Meiners wrote:
> In AdaSDL-Video-Drawing.adb around line 273 you will find:
>             declare
>                subtype Current_Screen is Screen_Eight(1..Array_Size);
>                package Convert is new  System.Address_To_Access_Conversions
>                  (Current_Screen);
>             begin
>                Eight_Bit_Draw
>                  ( On => Convert.To_Pointer (Item.Item.Pixels).all,  -- The
> important conversion
>                    Colors => To_Palette_Provider (Item),
>                    Coordinates => Coords);
>             end;
> 
> Here is a example of converting the Image.Pixels (in this case
> Item.Item.Pixels ;) into an access to an array of size Array_Size.  Notice
> that we had to declare a subtype of the Screen_Eight array with a specified
> range so that the compiler can reconstruct the range information.

I've only looked at the thin binding in adsdl.ad[bs] and
adsdl_framebuf and there he's doing some tricky stuff with
SDL.Types.Uint[8|16|32]_Ptrs. I've seen the package
Address_To_Access_Conversions in varios sources before but I didn't
know what it was good for ;)


> Now I am guessing that GLubyte_Array is an array of bytes.  So for your code
> your solution might look like this
> 
> declare
>     Bytes_Per_Pixel : constant := 4;  -- I believe RGBA is 32 bit color, but
> if I am wrong in your case change this value
>     subtype Current_Buffer is
> GLubyte_Array(0..(Width*Height*Bytes_Per_Pixel)-1);
>     package Convert is new
> System.Address_To_Access_Conversions(Current_Buffer);
> begin
>           glTexImage2D (GL_TEXTURE_2D,
>                         0,
>                         GLint (GL_RGBA),
>                         GLsizei (Width), GLsizei (Height),
>                         0,
>                         GL_RGBA,
>                         GL_UNSIGNED_BYTE,
>                         Convert.To_Pointer (Image.Pixels).all);
> end;

That's exactly how it works. Thank you very much.
The Bytes_Per_Pixel information is stored in Image.format.BytesPerPixel.

> Now remember this might need some tinkering to get it right since I don't
> have the packages to test this out.

There was a little bit of tinkering because I have to do some color
conversion and flipping of the textures but your code worked just
right out of the box ;) Again, thank you so much.


> I hope this solves your problem,
> 
> Chad R. Meiners

Indeed, it did. Thanks and bye,
Stefan


-- 




^ permalink raw reply	[relevance 0%]

* Re: AdaSDL and glTexImage2D
  @ 2003-01-29 20:15  6% ` Chad R. Meiners
  2003-01-30  9:52  0%   ` Stefan Soos
  0 siblings, 1 reply; 200+ results
From: Chad R. Meiners @ 2003-01-29 20:15 UTC (permalink / raw)



"Stefan Soos" <stefan.soos@gmx.de> wrote in message
news:49981b.cu.ln@ID-soos.user.dfncis.de...
>
> Hello,
>
> I'm doing some programming in Ada with the thin binding to the SDL
> library. I'd like to create some textured objects, but there I run
> into some problems. My texture data is stored in an SDL surface:
>
> Image : SDL.Video.Surface_ptr;
>
> The actual data can be read from Image.Pixels. Now, I'd like to call
> glTexImage2D:
>          glTexImage2D (GL_TEXTURE_2D,
>                        0,
>                        GLint (GL_RGBA),
>                        GLsizei (Width), GLsizei (Height),
>                        0,
>                        GL_RGBA,
>                        GL_UNSIGNED_BYTE,
>                        GLubyte_Array (Image.Pixels));
> but this doesn't work. How can I convert Image.Pixels (wich is
> actually defined as System.Address) to an array of GLubyte?

Well what you want to do is bit more complicated than what a simple type
conversion function can do for you automatically.
Image.Pixels is of type System.address.  First System.Address doesn't have
any bounds information, but there is hope because Ada gives you a very nice
package called System.Address_To_Access_Conversions.  This package is IMHO a
very cool package because it lets you transform System.Address into any type
you would like.  However invoking it in this case will be a little bit
tricky since your array will need bounds information added to it.  I don't
have immediate access to the GL libraries so I can't give you the exact code
to solve your problem, but I can point you to an example in the AdaSDL thick
binding where a similar conversion takes place.

In AdaSDL-Video-Drawing.adb around line 273 you will find:
            declare
               subtype Current_Screen is Screen_Eight(1..Array_Size);
               package Convert is new  System.Address_To_Access_Conversions
                 (Current_Screen);
            begin
               Eight_Bit_Draw
                 ( On => Convert.To_Pointer (Item.Item.Pixels).all,  -- The
important conversion
                   Colors => To_Palette_Provider (Item),
                   Coordinates => Coords);
            end;

Here is a example of converting the Image.Pixels (in this case
Item.Item.Pixels ;) into an access to an array of size Array_Size.  Notice
that we had to declare a subtype of the Screen_Eight array with a specified
range so that the compiler can reconstruct the range information.

Now I am guessing that GLubyte_Array is an array of bytes.  So for your code
your solution might look like this

declare
    Bytes_Per_Pixel : constant := 4;  -- I believe RGBA is 32 bit color, but
if I am wrong in your case change this value
    subtype Current_Buffer is
GLubyte_Array(0..(Width*Height*Bytes_Per_Pixel)-1);
    package Convert is new
System.Address_To_Access_Conversions(Current_Buffer);
begin
          glTexImage2D (GL_TEXTURE_2D,
                        0,
                        GLint (GL_RGBA),
                        GLsizei (Width), GLsizei (Height),
                        0,
                        GL_RGBA,
                        GL_UNSIGNED_BYTE,
                        Convert.To_Pointer (Image.Pixels).all);
end;

Now remember this might need some tinkering to get it right since I don't
have the packages to test this out.

I hope this solves your problem,

Chad R. Meiners





^ permalink raw reply	[relevance 6%]

* Re: Generic and Access problem
@ 2003-01-09 10:33  6% Sebastian Madunic
  0 siblings, 0 replies; 200+ results
From: Sebastian Madunic @ 2003-01-09 10:33 UTC (permalink / raw)


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

Strange I didn't have any problems opening it, anyway here is another try...

/S

"Grein, Christoph" <christoph.grein@eurocopter.com> wrote in message
news:<mailman.1042107482.19914.comp.lang.ada@ada.eu.org>...
> At least here, the attachment looks like:
> 
> > 
> > begin 600 generic_pool.ads
> > M9V5N97)I8PT*("`@+2T@5&AI<R!I<R!T:&4@='EP92!F;W(@=&AE(&]B:F5C
> > M=',@=&AA="!C;VUP<FES97,@=&AE('!O;VP-"B`@('1Y<&4@271E;5]4>7!E
> 
> Rest omitted.


[-- Attachment #2: generic_pool.adb --]
[-- Type: application/octet-stream, Size: 878 bytes --]

--with System.Address_To_Access_Conversions;

package body Generic_Pool is
------------------------------------------------------------------------
   -- Public types and objects
   Dummy_Item : aliased Item_Type;


   -- create an access-to-variable view of the pool:
--   package Access_Conversions is new
--      System.Address_To_Access_Conversions (Id_Type);

------------------------------------------------------------------------
   -- Returns a reference to the indexed item. 

   function Item (P : Id_Type; Ix : Index_Type) return Reference_Type is
      -- create an access-to-variable view of the pool:
--      P_Ref : constant Access_Conversions.Object_Pointer :=
--         Access_Conversions.To_Pointer(P'Address);
   begin
         return P.Buf(Ix)'access;
   end Item;

------------------------------------------------------------------------
end Generic_Pool;

[-- Attachment #3: generic_pool.ads --]
[-- Type: application/octet-stream, Size: 1000 bytes --]

generic
   -- This is the type for the objects that comprises the pool
   type Item_Type is private;

   -- This is the type for the index that are used to access the objects
   -- of the pool. 
   type Index_Type is (<>);

package Generic_Pool is
------------------------------------------------------------------------
   -- Public types and objects

   type Id_Type is private;
   type Reference_Type is access all Item_Type;

------------------------------------------------------------------------
   -- Returns a reference to the indexed item. 
   function Item (
      P : Id_Type;
      Ix : Index_Type)
      return Reference_Type;

------------------------------------------------------------------------
   -- Private types
private
   type Buffer_Type is array (Index_Type) of aliased Item_Type;

   type Id_Type is
   record
      Buf       : Buffer_Type;
      None_Allocated_Yet : Boolean := True;
      Last_Used   : Index_Type := Index_Type'First;
   end record;
   
end Generic_Pool;

^ permalink raw reply	[relevance 6%]

* Re: Size of a pointer to a tagged record
  2002-12-04 17:56  4%       ` Steven Murdoch
@ 2002-12-04 19:10  0%         ` Robert A Duff
  0 siblings, 0 replies; 200+ results
From: Robert A Duff @ 2002-12-04 19:10 UTC (permalink / raw)


news01+Steven.Murdoch@cl.cam.ac.uk (Steven Murdoch) writes:

> If I take out the "Parameter_Access(...)" I get the following error message:
> lua.adb:172:35: expected type "Parameter_Access" defined at lua.ads:13
> lua.adb:172:35: found type "System.Address_To_Access_Conversions.Object_Pointer" from instance at line 36
> so it seems that the result of To_Pointer is Object_Pointer rather than Parameter_Access.

Oh yeah, you're right.  I had forgotten how A_T_A_C works.
Sorry about that.

> Sorry, that's what I meant. 32 byte addresses would be a rather larger
> address space that would be necessary :-)

;-)

- Bob



^ permalink raw reply	[relevance 0%]

* Re: Size of a pointer to a tagged record
  2002-12-04 17:17  0%     ` Robert A Duff
@ 2002-12-04 17:56  4%       ` Steven Murdoch
  2002-12-04 19:10  0%         ` Robert A Duff
  0 siblings, 1 reply; 200+ results
From: Steven Murdoch @ 2002-12-04 17:56 UTC (permalink / raw)


In article <wccvg29d7q8.fsf@shell01.TheWorld.com>,
 Robert A Duff <bobduff@shell01.TheWorld.com> writes:

>> >> addr:=Get_Void_Pointer; --Void* from C
>> >> param:=Parameter_Access(User_Data_Convert.To_Pointer(Address));
>> >         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> >That code is wrong, so I'm not sure what you mean.
>> 
>> Well it compiles.
>
>I see nothing called User_Data_Convert in the above code.
>Perhaps you meant Convert?

Yes, sorry (I forgot to simplify that when I pasted it in)

>Also, the result of To_Pointer is Parameter_Access,
>so you don't need to additionally convert to Parameter_Access
>(by saying "Parameter_Access(...)").  That would compile,
>but it's silly to convert from a type to itself.

If I take out the "Parameter_Access(...)" I get the following error message:
lua.adb:172:35: expected type "Parameter_Access" defined at lua.ads:13
lua.adb:172:35: found type "System.Address_To_Access_Conversions.Object_Pointer" from instance at line 36
so it seems that the result of To_Pointer is Object_Pointer rather than Parameter_Access.

>> >Anyway, why not declare Get_Void_Pointer to return the access type?
>> >I see no need for Address_To_Access_Conversions.
>> 
>> What would it's type in C be in that case?
>
>void *

OK, I will try that, it would clean up my code substantially.

>> On GNAT 3.13p it is 32 (I assume bytes) which is indeed the same
>> size as System.Address.
>
>'Size is in bits, not bytes.

Sorry, that's what I meant. 32 byte addresses would be a rather larger
address space that would be necessary :-)

>One thing you might think about is taking 'Size on the Ada side,
>converting that to bytes (using System.Storage_Unit), and passing
>that to the C code at some point.  The C code might be able to
>use that size, or else assert that it is correct.

I will try that too, the size is set during run time so there
should not be any problem setting it. IIRC Malloc takes a number of
octets so I could use a variant of Jeff Carters suggestion such as
(Parameter_Access'Size + 7) / 8
This should be the right thing to pass in, even if Storage_Unit is not 8

Thanks again,
Steven Murdoch.



^ permalink raw reply	[relevance 4%]

* Re: Size of a pointer to a tagged record
  2002-12-04 15:44  0%   ` Steven Murdoch
@ 2002-12-04 17:17  0%     ` Robert A Duff
  2002-12-04 17:56  4%       ` Steven Murdoch
  0 siblings, 1 reply; 200+ results
From: Robert A Duff @ 2002-12-04 17:17 UTC (permalink / raw)


news01+Steven.Murdoch@cl.cam.ac.uk (Steven Murdoch) writes:

> Thanks for your reply.

You're welcome.

> >> type Parameter is tagged private;
> >> type Parameter_Access is access all Parameter'Class;
> >> 
> >> package Convert is new
> >>      System.Address_To_Access_Conversions(Parameter);
> >> 
> >> addr: System.Address;
> >> param: Parameter_Access;
> >> 
> >> addr:=Get_Void_Pointer; --Void* from C
> >> param:=Parameter_Access(User_Data_Convert.To_Pointer(Address));
> >         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> >That code is wrong, so I'm not sure what you mean.
> 
> Well it compiles.

I see nothing called User_Data_Convert in the above code.
Perhaps you meant Convert?

Also, the result of To_Pointer is Parameter_Access,
so you don't need to additionally convert to Parameter_Access
(by saying "Parameter_Access(...)").  That would compile,
but it's silly to convert from a type to itself.

If you want to clarify the type (just to make the code more readable),
use a qualified expression, as in "Parameter_Access'(...)".
                                                   ^
                                                   ^

> >Anyway, why not declare Get_Void_Pointer to return the access type?
> >I see no need for Address_To_Access_Conversions.
> 
> What would it's type in C be in that case?

void *

>... Currently is returns
> a "void *" which I believe is equivalent to a System.Address. What
> would it's type be if it it returned an "Parameter_Access"?
> Is it safe to mark a pragma Import(C) function as returning a
> Parameter_Access?

No, it's not safe.  But interfacing across languages is never safe --
you always have to make sure the sizes of things match.

> ...Would this be a better idea?

I have no opinion either way.

> >You can find out the size of a pointer by writing a little test program
> >that prints out Parmeter_Access'Size, and running it on as many Ada
> >compilers as you can get your hands on.
> 
> On GNAT 3.13p it is 32 (I assume bytes) which is indeed the same
> size as System.Address.

'Size is in bits, not bytes.

One thing you might think about is taking 'Size on the Ada side,
converting that to bytes (using System.Storage_Unit), and passing
that to the C code at some point.  The C code might be able to
use that size, or else assert that it is correct.

- Bob



^ permalink raw reply	[relevance 0%]

* Re: Size of a pointer to a tagged record
  2002-12-04 15:16  0% ` Robert A Duff
@ 2002-12-04 15:44  0%   ` Steven Murdoch
  2002-12-04 17:17  0%     ` Robert A Duff
  0 siblings, 1 reply; 200+ results
From: Steven Murdoch @ 2002-12-04 15:44 UTC (permalink / raw)


Thanks for your reply.

In article <wcc3cpd3jd7.fsf@shell01.TheWorld.com>,
 you write:
>All the Ada compilers I am familiar with represent access-to-tagged as a
>single address.  The tag is stored in the tagged record, not in the
>pointer.

OK, that is what I hoped.

>However, I don't understand what you're trying to do.  How can C code
>produce a pointer to a tagged type?  I mean, the tag has to be
>initialized on the Ada side.  And why must the *pointer* be heap
>allocated?

The tagged record and pointer are created by a Ada "new" statement
the the pointer is passed to the Lua API and stored by it.
In order to store things in Lua you give it the contents of the object
and size (in bytes). This is effectively passed to malloc and the space
for the pointer is allocated (plus some Lua internals).

Control then passes to Lua and at some point it will ask the Ada
program to perform some action on the data so will pass the data
back to Ada, which is the same as the contents passed in
earlier, i.e. a pointer to a tagged record. 

>If the tag *were* stored in the pointer, then you would not only have to
>allocate space for it, but somehow set it to the right value.

Ada would handle setting the tag, the C part just takes a value 
and stores it, it eventually returns it.

>
>> --
>> 
>> type Parameter is tagged private;
>> type Parameter_Access is access all Parameter'Class;
>> 
>> package Convert is new
>>      System.Address_To_Access_Conversions(Parameter);
>> 
>> addr: System.Address;
>> param: Parameter_Access;
>> 
>> addr:=Get_Void_Pointer; --Void* from C
>> param:=Parameter_Access(User_Data_Convert.To_Pointer(Address));
>         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>That code is wrong, so I'm not sure what you mean.

Well it compiles.

>I presume Get_Void_Pointer is pragma Import(C).  And it does a "malloc",
>passing sizeof(void *).

Get_Void_Pointer doesn't do a malloc, it returns a pointer
to a tagged record, which was stored somewhere in the heap.

At a previous point a malloc was done to create a memory location X,
in which was stored the address of a tagged record. The address of
X is hidden by Lua, but it's contents are passed back to Ada by
Get_Void_Pointer.

> So it's returning a pointer to a pointer.  Is
> that right?

No, just a pointer to a tagged record.

>Anyway, why not declare Get_Void_Pointer to return the access type?
>I see no need for Address_To_Access_Conversions.

What would it's type in C be in that case? Currently is returns
a "void *" which I believe is equivalent to a System.Address. What
would it's type be if it it returned an "Parameter_Access"?
Is it safe to mark a pragma Import(C) function as returning a
Parameter_Access? Would this be a better idea?

>You can find out the size of a pointer by writing a little test program
>that prints out Parmeter_Access'Size, and running it on as many Ada
>compilers as you can get your hands on.

On GNAT 3.13p it is 32 (I assume bytes) which is indeed the same
size as System.Address.

Thank you,
Steven Murdoch.



^ permalink raw reply	[relevance 0%]

* Re: Size of a pointer to a tagged record
  2002-12-04 14:01  5% Size of a pointer to a tagged record Steven Murdoch
@ 2002-12-04 15:16  0% ` Robert A Duff
  2002-12-04 15:44  0%   ` Steven Murdoch
  0 siblings, 1 reply; 200+ results
From: Robert A Duff @ 2002-12-04 15:16 UTC (permalink / raw)


news01+Steven.Murdoch@cl.cam.ac.uk (Steven Murdoch) writes:

> I am writing a binding to the Lua (http://www.lua.org/)
> scripting language (which is written in C). One thing I
> need to do is store a pointer to a tagged record in a
> memory location allocated by malloc. For this reason I need
> to know the size.
> 
> If a pointer to a tagged record is equivalent to a
> System.Address then I can store this in a memory location
> of sizeof(void *), however if the tag is stored in the
> pointer rather than the record then I would need to
> allocate space for the tag as well.
> 
> If a pointer to a tagged record is equivalent to a
> System.Address then I would use the following code:

All the Ada compilers I am familiar with represent access-to-tagged as a
single address.  The tag is stored in the tagged record, not in the
pointer.

I don't think it's even feasible to store the tag with the pointer,
because of a last-minute change to Ada 95 -- all tagged parameters are
aliased.

However, I don't understand what you're trying to do.  How can C code
produce a pointer to a tagged type?  I mean, the tag has to be
initialized on the Ada side.  And why must the *pointer* be heap
allocated?

If the tag *were* stored in the pointer, then you would not only have to
allocate space for it, but somehow set it to the right value.

> --
> 
> type Parameter is tagged private;
> type Parameter_Access is access all Parameter'Class;
> 
> package Convert is new
>      System.Address_To_Access_Conversions(Parameter);
> 
> addr: System.Address;
> param: Parameter_Access;
> 
> addr:=Get_Void_Pointer; --Void* from C
> param:=Parameter_Access(User_Data_Convert.To_Pointer(Address));
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
That code is wrong, so I'm not sure what you mean.

I presume Get_Void_Pointer is pragma Import(C).  And it does a "malloc",
passing sizeof(void *).  So it's returning a pointer to a pointer.  Is
that right?

Anyway, why not declare Get_Void_Pointer to return the access type?
I see no need for Address_To_Access_Conversions.

> At the end of this code I would use param as a normal pointer
> to a tagged record. Does this look OK? Is there a better way
> to achieve the same thing.
> 
> I am using GNAT 3.13p but I would like the code to be as
> cross platform/compiler as possible.

You can find out the size of a pointer by writing a little test program
that prints out Parmeter_Access'Size, and running it on as many Ada
compilers as you can get your hands on.

- Bob



^ permalink raw reply	[relevance 0%]

* Size of a pointer to a tagged record
@ 2002-12-04 14:01  5% Steven Murdoch
  2002-12-04 15:16  0% ` Robert A Duff
  0 siblings, 1 reply; 200+ results
From: Steven Murdoch @ 2002-12-04 14:01 UTC (permalink / raw)


I am writing a binding to the Lua (http://www.lua.org/)
scripting language (which is written in C). One thing I
need to do is store a pointer to a tagged record in a
memory location allocated by malloc. For this reason I need
to know the size.

If a pointer to a tagged record is equivalent to a
System.Address then I can store this in a memory location
of sizeof(void *), however if the tag is stored in the
pointer rather than the record then I would need to
allocate space for the tag as well.

If a pointer to a tagged record is equivalent to a
System.Address then I would use the following code:

--

type Parameter is tagged private;
type Parameter_Access is access all Parameter'Class;

package Convert is new
     System.Address_To_Access_Conversions(Parameter);

addr: System.Address;
param: Parameter_Access;

addr:=Get_Void_Pointer; --Void* from C
param:=Parameter_Access(User_Data_Convert.To_Pointer(Address));

--

At the end of this code I would use param as a normal pointer
to a tagged record. Does this look OK? Is there a better way
to achieve the same thing.

I am using GNAT 3.13p but I would like the code to be as
cross platform/compiler as possible.

Thanks in advance,
Steven Murdoch.



^ permalink raw reply	[relevance 5%]

* Re: Format of .adp files?
  2002-11-14  9:43  0%             ` Preben Randhol
@ 2002-11-14 14:57  0%               ` Timo Warns
  0 siblings, 0 replies; 200+ results
From: Timo Warns @ 2002-11-14 14:57 UTC (permalink / raw)


Preben Randhol wrote:
>  Stephen Leake wrote:
>  
> > "with system.address_to_access_conversions" 
>  
>  in Vim for the standard library packages (and procedures and functions)
>  I intended to make this possible:
>  
>     with System.Add and then you should be able to hit <Tab> to complete the
>     rest.

You could add Ada support to exuberant-ctags then. Thus, other programs
would benefit as well.

> > It helps meet style guidelines. I would never enforce the
>  
>  Can you point me to where this is? I'm a bit uncertain if this is a GNAT
>  style guide or the Ada style guide. As I understand, Ada is not case
>  sensitive although I use casing myself.


Have a look at
http://www.informatik.uni-stuttgart.de/ifi/ps/ada-doc/\
style_guide/sec_3a.html#3.1.3

Timo



^ permalink raw reply	[relevance 0%]

* Re: Format of .adp files?
  2002-11-13 17:30  6%           ` Stephen Leake
@ 2002-11-14  9:43  0%             ` Preben Randhol
  2002-11-14 14:57  0%               ` Timo Warns
  0 siblings, 1 reply; 200+ results
From: Preben Randhol @ 2002-11-14  9:43 UTC (permalink / raw)


Stephen Leake wrote:
> Well, just because you don't like it doesn't mean vim shouldn't
> support it. But ok, one more score for Emacs :).

My point is more why should I bother to support it in the first place
:-) But I think it shouldn't be to hard. The problem is of course
dealing with strings over one line.

> "with system.address_to_access_conversions" 

in Vim for the standard library packages (and procedures and functions)
I intended to make this possible:

   with System.Add and then you should be able to hit <Tab> to complete the
   rest.

> So I never have to hit the shift key (helps avoid Carpal-Tunnel). In

Never? In my Norwegian keyboard I have to hit Shift every time I want "_"

> It helps meet style guidelines. I would never enforce the

Can you point me to where this is? I'm a bit uncertain if this is a GNAT
style guide or the Ada style guide. As I understand, Ada is not case
sensitive although I use casing myself.

> There is a file of exceptions to the normal capitalization rule, so
> things like Ada.Text_IO are done correctly (the _IO violates the
> normal rule). That's the file that should be specified in the .adp
> file.

Where can I find a copy? The Ada-mode for Emacs I have installed on
linux does not capitalize this correctly. Version: 3.5-3

-- 
Preben Randhol ------------------------ http://www.pvv.org/~randhol/ --
�There are three things you can do to a woman. You can love her, suffer
 for her, or turn her into literature.�  - Justine, by Lawrence Durrell



^ permalink raw reply	[relevance 0%]

* Re: Format of .adp files?
  @ 2002-11-13 17:30  6%           ` Stephen Leake
  2002-11-14  9:43  0%             ` Preben Randhol
  0 siblings, 1 reply; 200+ results
From: Stephen Leake @ 2002-11-13 17:30 UTC (permalink / raw)


Preben Randhol <randhol+news@pvv.org> writes:

> Stephen Leake wrote:
> > Allow setting the casing exceptions file in the project file (you'll
> > also have to implement the ada-mode casing support :).
> 
> Nonono I hate that auto-casing thing. 

Well, just because you don't like it doesn't mean vim shouldn't
support it. But ok, one more score for Emacs :).

> I don't understand what it is useful for.

I can type 

"with system.address_to_access_conversions" 

and the editor automagically converts that to

"with System.Address_To_Access_Conversions". 

So I never have to hit the shift key (helps avoid Carpal-Tunnel). In
addition, if I'm unsure of the proper capitalization of a previously
typed word, I can hit M-w and the word is re-capitalized.

It helps meet style guidelines. I would never enforce the
capitalization style if the editor did not support it (however, I will
tell people that's a reason to switch to Emacs).

There is a file of exceptions to the normal capitalization rule, so
things like Ada.Text_IO are done correctly (the _IO violates the
normal rule). That's the file that should be specified in the .adp
file.

-- 
-- Stephe



^ permalink raw reply	[relevance 6%]

* Re: Pragma Import don't suppress access initialization
  2002-10-07 17:25  5% ` Matthew Heaney
@ 2002-10-07 19:49  0%   ` Jeffrey Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey Carter @ 2002-10-07 19:49 UTC (permalink / raw)


Matthew Heaney wrote:
> "Fr�d�ric Ormancey" <frederic.ormancey@atosorigin.com> wrote in message
> news:9c9fb8b4.0210070410.fa84429@posting.google.com...
> 
>>   function Analyser_Formule (Varset : in System.ADDRESS)
>>    return Integer is
>>     V : Ty_Varset;
>>     for V use at Varset;
>>     pragma Import (Ada, V);
>>
>>where Ty_Varset is declared in another package :
>>
>>    type Varset(Nature : Character; Taille : Integer);
>>    type Ty_Varset is access Varset;
> 
> What's wrong with System.Address_To_Access_Conversions?
> 
>   V : Object_Pointer := To_Pointer (Varset);

Note that he is not using Varset as an access value as you are 
suggesting; he is using it as the address of an access object. That may 
be his problem, but we can't tell.

-- 
Jeff Carter
"Have you gone berserk? Can't you see that that man is a ni?"
Blazing Saddles




^ permalink raw reply	[relevance 0%]

* Re: Pragma Import don't suppress access initialization
  @ 2002-10-07 17:25  5% ` Matthew Heaney
  2002-10-07 19:49  0%   ` Jeffrey Carter
  0 siblings, 1 reply; 200+ results
From: Matthew Heaney @ 2002-10-07 17:25 UTC (permalink / raw)


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


"Fr�d�ric Ormancey" <frederic.ormancey@atosorigin.com> wrote in message
news:9c9fb8b4.0210070410.fa84429@posting.google.com...
>
> Code look like this :
>
>    function Analyser_Formule (Varset : in System.ADDRESS)
>     return Integer is
>      V : Ty_Varset;
>      for V use at Varset;
>      pragma Import (Ada, V);
>
> where Ty_Varset is declared in another package :
>
>     type Varset(Nature : Character; Taille : Integer);
>     type Ty_Varset is access Varset;

What's wrong with System.Address_To_Access_Conversions?

  V : Object_Pointer := To_Pointer (Varset);







^ permalink raw reply	[relevance 5%]

* Re: worth the hassle?
  @ 2002-07-23 12:16  6%       ` chris.danx
  0 siblings, 0 replies; 200+ results
From: chris.danx @ 2002-07-23 12:16 UTC (permalink / raw)


Is using address_to_access_conversions the correct solution?  Something
along the lines of

package List_Address_Conversions
      is new System.Address_To_Access_Conversions (List_Type);

function First (List : in List_Type) return Iterator_Type is
begin
   ...
   return Iterator_Type'(List_Address_Conversions.to_pointer(List'Address),
List.First);
end First;

?






^ permalink raw reply	[relevance 6%]

* Re: Simple Question - Direct Access to memory with ADA
  @ 2002-07-02 19:46  4% ` Pat Rogers
  0 siblings, 0 replies; 200+ results
From: Pat Rogers @ 2002-07-02 19:46 UTC (permalink / raw)


>   Sorry for the simple question - I was wondering the most efficient way
> (moral arguments aside) to get direct access to memory in ADA 95
> (specifically using the GNAT compiler) - assuming the OS allows access
> to it. Its quite
> easy to do in C (a couple of lines to write to a memory location)
>
> *my_int_ptr = (int *) 0xF00BA;
> etc..
> This can easily be macro/funcionalized.
>
>   I could use an Address Clause for each location in memory I wish to
> access,
> this could become tiresome for large chunks of memory. There doesnt seem
> to be any provided service from gnat system packages to perform this
> function (probably for very good reasons).

This need not be vendor-specific.

If the large chunk is contiguous, use an array type and map the entire array via
a single address clause (specifying the starting address of the array).  Use the
predefined array type System.Storage_Elements.Storage_Array because it is
guaranteed to be represented contiguously.  Then access memory by indexing into
the array.  However, at any index location the type of value is the component
type of Storage_Array, ie Storage_Element.  Storage_Element is a modular numeric
type (ie unsigned).  If accessing memory in terms of an unsigned numeric type
isn't what you want, you'll need to do something else.  For example, you could
define a record type, including its representation, to contain all the kinds of
different elements at different memory locations in terms of offsets from the
beginning of the record, and then map an object of that type with a single
address clause (like the array type above).

Alternatively, you can use the predefined facility intended for this purpose:

        System.Address_To_Access_Conversions

This is a generic package that gives you type-safe "peek and poke" access to
memory, much like the C code you showed.  It does the necessary work to convert
addresses to access values (which may or may not be identical to what you would
get with unchecked conversion).  Given the access values (ie, pointers) you then
dereference them to access the memory in terms of the type of value supposedly
at those memory locations (hence the "peek/poke" terminology of old).  This is a
much more dynamic approach, with corresponding flexibility, but will be a little
slower than mapping things once using the above approaches.

>   will I need to use the  pragma Atomic as well?

Are tasks concurrently accessing and updating the storage?

> Am I going to have to resort to Unchecked_Conversion?

Probably not, but if you did that would not be an "evil" thing unless you make
the clients do it all over the code.  If you have to do it, hide it behind a
functional interface so that it only occurs within your implementation.

> I hope I have made the question clear.

Hope that helps,

---
Patrick Rogers                       Consulting and Training in:
http://www.classwide.com          Real-Time/OO Languages
progers@classwide.com               Hard Deadline Schedulability Analysis
(281)648-3165                                 Software Fault Tolerance





^ permalink raw reply	[relevance 4%]

* Re: slice'access?
  @ 2002-05-25 18:28  4% ` tmoran
  0 siblings, 0 replies; 200+ results
From: tmoran @ 2002-05-25 18:28 UTC (permalink / raw)


> > Is there a nice way to create an access to a slice? eg
> The answer of course is no. The RM does not allow this
> and if you think for just a moment it is obvious why. The
> usual representation of bounds for an array is to have the
> bounds immediately before the data, but of course that

  The problem at hand is that a package maintains a private data
structure which contains, among other things, long strings.  I want
(read only) access to one of those strings.  Of course it's
possible to call the data package and have it return a string,
  subtype card is string(1 .. 80);
  function get_card(param) return card;
but speed matters.  It would be faster to get a pointer
  function get_card_pointer(param) return ptr_type;
For instance, getting character(8) of the card could be done with
  get_card(param)(8)
but
  get_card_pointer(param)(8)
is likely to be a lot faster.
  Using a fixed length subtype and system.address_to_access_conversions, a
quick test shows it works fine on two different compilers.  Or I can call
a subprogram and pass the slice, eg
  procedure callback_to_process_the_card(s : in card);
  fetch_card(param, callback_to_process_the_card'access);
and be very surprised if it's passed by copy.  Neither of those techniques
is very nice.  Is there a NICE way to create an access to a slice?



^ permalink raw reply	[relevance 4%]

* Help with Copying Shared Memory to Local
@ 2002-05-23 13:50  5% John Cupak
  0 siblings, 0 replies; 200+ results
From: John Cupak @ 2002-05-23 13:50 UTC (permalink / raw)


A colleague asked me to help him solve an memory copy problem.

The source memory location is in a "shared" area, and the
destination memory location is "local" to the application.

The original code, written in Ada83, works by copying two bytes
at a time. Evidently, the hardware crashes if they try to access
a single byte.

Here's the Ada 95 version of the original Ada83 code:

-- Assumed visibility of Project_Types
procedure Copy_Double_Byte(Destination : in System.Address;
                           Source      : in System.Address;
                           Length      : in Natural) is
   
  Destination_Pointer : Project_Types.Double_Byte_Pointer;
  Source_Pointer      : Project_Types.Double_Byte_Pointer;
   
begin -- Copy_Double_Byte
   
  -- Ensure source address in correct range
  if Source >= System.Addresses.Logical_Address(Project_Types.Virtual_Base_Address)
and
  Source < System.Addresses.Logical_Address(Project_Types.Virtual_Base_Address
+ 16#200_000#) then
      
     -- Must reference memory on double byte boundry
     -- The number of bytes to copy is specified by the Length
parameter
     for Index in 0..(Length/2) - 1 loop
         
        -- Create source and destination pointers from base address
plus double byte offsets
        Destination_Pointer := Project_Types.To_Double_Byte_Pointer(
                                
System.Deprecated.Incr_Addr(Destination, Index * 2));
        Source_Pointer      := Project_Types.To_Double_Byte_Pointer(
                                 System.Deprecated.Incr_Addr(Source,  
   Index * 2));
         
        -- Copy contents
        Destination_Pointer.all := Source_Pointer.all;
         
     end loop;
      
  end if; -- Source check
   
end Copy_Double_Byte;

I found a 1997 reference in this newsgroup (comp.lang.ada) to a
similar problem entitled
"Q: How to do memory access with gnat" from Michael Erdman
(boavista@berlin.snafu.de)
with references to the Ada95 System.Address_To_Access_Conversions
child package and
the System.Storage_Elements child package.

So, before I go off and write up a new version of the "memory copy"
procedure using
these two child packages, has anyone ever implemented such a solution
that would be
willing to share?

Comments and recommendations always appreciated.

John Cupak



^ permalink raw reply	[relevance 5%]

* Re: newbie to generic
       [not found]     <ac2hbs$ljq$1@newstoo.ericsson.se>
  2002-05-17  9:35  8% ` Preben Randhol
@ 2002-05-17 19:40  0% ` Jeffrey Carter
  1 sibling, 0 replies; 200+ results
From: Jeffrey Carter @ 2002-05-17 19:40 UTC (permalink / raw)


> Sebastian wrote:
> 
> whats wring with this?
> 
> function To_Add is new
> System.Address_To_Access_Conversions.To_Address(Procedure_Ptr_Type);
> 
> "Procedure_Ptr_Type" is my Object.

Why do you want to mess with addresses? If you don't understand generics
yet, you are unlikely to understand the very few circumstances in which
you need to deal with addresses in Ada.

-- 
Jeff Carter
"Monsieur Arthur King, who has the brain of a duck, you know."
Monty Python & the Holy Grail



^ permalink raw reply	[relevance 0%]

* Re: newbie to generic
       [not found]     <ac2hbs$ljq$1@newstoo.ericsson.se>
@ 2002-05-17  9:35  8% ` Preben Randhol
  2002-05-17 19:40  0% ` Jeffrey Carter
  1 sibling, 0 replies; 200+ results
From: Preben Randhol @ 2002-05-17  9:35 UTC (permalink / raw)


On Fri, 17 May 2002 11:13:12 +0200, Sebastian wrote:

> whats wring with this?

First stop posting HTML to a news group. Turn on text only in your
newsreader.

> function To_Add is new =
> System.Address_To_Access_Conversions.To_Address(Procedure_Ptr_Type);

because the package System.Address_To_Access_Conversions is defined as
this (arm95 - 13.7.2):

  generic
     type Object(<>) is limited private;
  package System.Address_To_Access_Conversions
  is
  pragma Preelaborate(Address_To_Access_Conversions);
  type Object_Pointer is access all Object;
  [...]
  function To_Address(Value : Object_Pointer) return Address;
  [...]
  end System.Address_To_Access_Conversions;


This means that you have to do:

   package My_Address_Conversion is 
      new System.Address_To_Access_Conversions (Object => Procedure_Type);

and then you call To_Address like this:

   My_Address_Conversion.To_Address(Procedure_Ptr_Type);

-- 
Preben



^ permalink raw reply	[relevance 8%]

* Re: newbie to generic
@ 2002-05-17  9:26  7% Grein, Christoph
  0 siblings, 0 replies; 200+ results
From: Grein, Christoph @ 2002-05-17  9:26 UTC (permalink / raw)


> whats wring with this?
> 
> function To_Add is new
> System.Address_To_Access_Conversions.To_Address(Procedure_Ptr_Type);
> 
> "Procedure_Ptr_Type" is my Object.
> 


System.Address_To_Access_Conversions is a generic package and you habe to 
instantiate to create a package. After instantiation, the instance package holds 
functions that you can call like any other function of a "normal" package.

package My_Conversion is new System.Address_To_Access_Conversions (My_Type);

X := My_Conversion.To_Address (Procedure_Ptr_Type);



^ permalink raw reply	[relevance 7%]

* Re: ANN: GMGPL Claw Page
  2002-04-30 18:20  5% ` tmoran
@ 2002-05-01 16:56  0%   ` Ted Dennison
  0 siblings, 0 replies; 200+ results
From: Ted Dennison @ 2002-05-01 16:56 UTC (permalink / raw)


tmoran@acm.org wrote in message news:<9gBz8.4052$wr1.2380283950@newssvr21.news.prodigy.com>...
>   Claw uses 'access', not system.address, which is not, in fact, always
> the same thing as a C pointer.

Right. I seem to rememer a discussion here a long time ago, where the
general conclusion was that, while in theory there is no guarantee
System.Adress is implemented in any specific way, in practice
System.Address is more likely to match up with a C pointer than an
access type is.

>   I really can't understand why, given the examples of
> System.Address_To_Access_Conversions, Interfaces.C.Strings,
> Interfaces.C.Pointers, and a given a demonstrated ability to move
> comfortably among different abstractions, anyone would use such a low
> level, implementation defined thing as System.Address.  Given the
> frequency with which it's done in c.l.a. postings, I guess it seems
> reasonable to more than a few people.  #.#

I think the only place I ever use it any more is in bindings (where
you are generally at a icky low level anyway). However, I'd have to
check my code to see exactly where it is used. I know I'm rather
liberal with Addresses on unused pointer parameters, but I can't
remember how I was doing *used* pointer parameters. I'm pretty sure I
don't make much use of Interfaces.C.Pointers. Perhaps that's a bad
move?

Anyway, the possible issues with System.Address is why I mentioned it.
I'm certianly willing to learn the proper portable way to get at C
pointers, and from the looks of things, the folks who wrote Claw would
know a thing or two about portability. :-)


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



^ permalink raw reply	[relevance 0%]

* Re: Is this a GNAT bug???
    2002-04-30 18:20  5%         ` tmoran
@ 2002-04-30 21:55  4%         ` Mark Johnson
  1 sibling, 0 replies; 200+ results
From: Mark Johnson @ 2002-04-30 21:55 UTC (permalink / raw)


Robert Quinn wrote:
> [snip]
> I guess the scenario I'm thinking of must not occur too frequently.
> I'll use specific numbers to make the example simple.  Suppose you
> have a sequence of 12 bytes 94 bits).  Suppose the first and last byte
> are header/tail info, leaving 10 bytes for data.  Suppose 65 bits of
> the 10 bytes represent one kind of data, the remaining 13 bits another
> kind of data.
This is going to be hard on several platforms - especially if
portability is to be considered. We are in the process of rehosting a
large SGI application (VADS) to PC's (GNAT) and we have several places
in our code where we had to address bit and byte order differences.
Annex C compliance means that all the Section 13 recommendations are
supported. What you describe does not appear to fit those
recommendations.

You may be better off with declarations that define the "data" in
smaller chunks (e.g., a sequence of bytes) and use functions to extract
and fill in the values needed. For example, based on the default bit
order, the array you defined can be represented in the following ways on
a big & little endian machine.

Big endian (Bit_Order == System.High_Order_First)
Byte 00000000 11111111 22222222 33333333 ...
Bit  01234567 01234567 01234567 01234567 ...
Ind  00000000 00111111 11112222 22222233
-ex  01234567 89012345 67890123 45678901

Little endian (Bit_Order == System.Low_Order_First)
Byte 00000000 11111111 22222222 33333333 ...
Bit  76543210 76543210 76543210 76543210 ...
Ind  00000000 11111100 22221111 33222222
-ex  76543210 54321098 32109876 10987654

Where the byte & bit offset are the first two rows & the last two rows
represent the index into the bit array (0..31 shown). Basically the rule
is to normalize to "Storage_Unit" (in this case 8) and then use the
specified (usually default) bit order for the order of bits. The
annotated ARM (13.5.1 and 13.5.2) has more explanation of this if
needed.

We had a few cases of these & had to swap the bits and the bytes [sigh]
to otherwise preserve the coding style. In other cases, we were able to
override the default bit order and get what we wanted. For type T, you
can set T'Bit_Order to High or Low_Order_First, but that doesn't solve
all the problems - I can list a few if needed.

Putting a level of abstraction around the data is probably best to hide
this kind of manipulation.

[snip]
> I could convert the sequence of bytes to an access type to this
> record.  For example:
> 
> type Message_Type_Access is access Message_Type;
> function Get_Message_Data is new Unchecked_Conversion
>    (SOURCE => System.ADDRESS,
>     TARGET => Message_Type_Access);
> 
How about System.Address_To_Access_Conversions [13.7.2] instead? Read
the definition carefully, we screwed up one one such conversion when
making the change.

[snip]

> So reading a sequence of bits >= 65 bits out of memory is just always
> going to be more work since you cannot convert it directly into a
> type, right?
> 
Actually, depending on the platform, 65 may be 33 - or in the future
129. Another reason to try to encapsulate the awful code and hide it
from the rest of your application.
  --Mark



^ permalink raw reply	[relevance 4%]

* Re: Is this a GNAT bug???
  @ 2002-04-30 18:20  5%         ` tmoran
  2002-04-30 21:55  4%         ` Mark Johnson
  1 sibling, 0 replies; 200+ results
From: tmoran @ 2002-04-30 18:20 UTC (permalink / raw)


> type Message_Type_Access is access Message_Type;
> function Get_Message_Data is new Unchecked_Conversion
>    (SOURCE => System.ADDRESS,
>     TARGET => Message_Type_Access);
  This is not good Ada.  You almost certainly want to convert an
access type for one way of looking at the data to an access type
for a different way.  No "system.address" involved.  If, most
unusually, you actually do need to convert a System.Address to
an access type, use the standard System.Address_To_Access_Conversions,
which is defined exactly for that purpose, and which the compiler
will implement so it actually works.  There is no reason to
assume an unchecked conversion from System.Address to an access
type will work as you hope.



^ permalink raw reply	[relevance 5%]

* Re: ANN: GMGPL Claw Page
  @ 2002-04-30 18:20  5% ` tmoran
  2002-05-01 16:56  0%   ` Ted Dennison
  0 siblings, 1 reply; 200+ results
From: tmoran @ 2002-04-30 18:20 UTC (permalink / raw)


> portability issues are confied to:
>
> o  Using a particular convention name (eg: "stdcall") that may not
> exist on other compilers. (The only predefined one is "C", which is
> not what a lot of Win32 uses).
> o  Assuming Ada's Address type is compatable with C pointers.
  "stdcall" is already used in Claw.  It works on Apex, Gnat, ObjectAda,
and Janus.
  Claw uses 'access', not system.address, which is not, in fact, always
the same thing as a C pointer.

  I really can't understand why, given the examples of
System.Address_To_Access_Conversions, Interfaces.C.Strings,
Interfaces.C.Pointers, and a given a demonstrated ability to move
comfortably among different abstractions, anyone would use such a low
level, implementation defined thing as System.Address.  Given the
frequency with which it's done in c.l.a. postings, I guess it seems
reasonable to more than a few people.  #.#



^ permalink raw reply	[relevance 5%]

* Re: 64bit access to an array of 8bit values
    2002-03-04  3:15  7% ` Pat Rogers
@ 2002-03-04  7:23  4% ` Jeffrey Carter
  1 sibling, 0 replies; 200+ results
From: Jeffrey Carter @ 2002-03-04  7:23 UTC (permalink / raw)


If you're willing to limit yourself to those machines that actually have
8-bit byte access (which your code would require), you can do

type Bit8 is new Interfaces.Unsigned_8;
-- This won't compile on machines that don't have 8-bit byte access.

type Bit64 is mod 2 ** 64;

type Ram_List is array (Natural range <>) of aliased Bit8;
for Ram_List'Component_Size use Bit8'Size;
pragma Pack (Ram_List);

Bytes_Per_Quad_Word : constant := 8;

subtype Quad_Word_As_Ram_List is Ram_List (1 .. Bytes_Per_Quad_Word);

function To_Quad_Word is new Ada.Unchecked_Conversion
(Source => Quad_Word_As_Ram_List, Target => Bit64);
function To_Ram_List is new Ada.Unchecked_Conversion
(Source => Bit64, Target => Quad_Word_As_Ram_List);

Ram   : Ram_List (0 .. Whatever);
Value : Bit64;
...
Value := To_Quad_Word (Ram (Ram'First .. Ram'First + Bytes_Per_Quad_Word
- 1) );

If you really need to have access values then you should look into
System.Address_To_Access_Conversions, and convert the address of the
first byte of the 64-bit value to the access-to-64-bit-value type.

To be really portable, you need to decide what byte order you want your
64-bit values to have, and do the appropriate conversion on machines
with a different endianness.

-- 
Jeff Carter
"Nobody expects the Spanish Inquisition!"
Monty Python's Flying Circus



^ permalink raw reply	[relevance 4%]

* Re: 64bit access to an array of 8bit values
  @ 2002-03-04  3:15  7% ` Pat Rogers
  2002-03-04  7:23  4% ` Jeffrey Carter
  1 sibling, 0 replies; 200+ results
From: Pat Rogers @ 2002-03-04  3:15 UTC (permalink / raw)


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

"Dave Poirier" <instinc@users.sf.net> wrote in message
news:3C823A1A.6030006@users.sf.net...
> I'm trying to modelize a small virtual machine, and I'm stuck on the
> memory model.  I'm defining the memory as an array of 8bit values, so
> that I am able to access every byte individually.  The problem comes
> when I try to access them with other data size, like 16/32/64bit.  GNAT
> simply refuses to do the pointer conversion (yeah, probably a bad habit).
>
> So, what would be a "clean" way to do it?  here's what I tried
<snip>

The predefined way to manipulate values of arbitrary types at arbitrary
locations is to use the generic package
System.Address_to_Access_Conversions:

generic
    type Object (<>) is limited private;
package System.Address_To_Access_Conversions is
    type Object_Pointer is access all Object;
    function To_Pointer( Value : Address ) return Object_Pointer;
    function To_Address( Value : Object_Pointer ) return Address;
    pragma Convention( Intrinsic, To_Pointer );
    pragma Convention( Intrinsic, To_Address );
end System.Address_To_Access_Conversions;


For example, if you wanted to swap the two bytes at an arbitrary address
(assuming that was
the reasonable thing to do), you could do it like this:


with Interfaces;
with System.Address_To_Access_Conversions;
package body Byte_Swapping is

    type Word is new Interfaces.Unsigned_16;

    package Word_Ops is new System.Address_To_Access_Conversions( Word );
    use Word_Ops;

    procedure Swap2( Location : in System.Address ) is
        X : Word renames To_Pointer(Location).all;
    begin
        X := ( Shift_Left(X,8) and 16#FF00# ) or
               ( Shift_Right(X,8) and 16#00FF# );
    end Swap2;

    �

end Byte_Swapping;

There are other ways, of course, but this illustrates the idea.

Note that there is no guarantee that the address you provide to To_Pointer is
actually a meaningful address for a value of a given type.  You have to be
concerned with issues such as padding and alignment, for example.

Having described the above, let me also say that you can do unchecked
conversions from addresses into access values if you are knowledgeable about how
access values are implemented for your given machine/vendor.  For example, there
is no reason to think that an access value is simply a single address -- it
might be an address pair, and it depends upon the type designated.

By the way, depending on exactly what you are doing, if you want to model
contiguous memory you should consider using the type
System.Storage_Elements.Storage_Array -- it is guaranteed contiguous, unlike
other array types.  That may not be an issue for your model, but if you are
doing address calculations it is worth thinking about.

Hope that helps,

---
Patrick Rogers                       Consulting and Training in:
http://www.classwide.com          Real-Time/OO Languages
progers@classwide.com               Hard Deadline Schedulability Analysis
(281)648-3165                                 Software Fault Tolerance





^ permalink raw reply	[relevance 7%]

* Device driver in Ada95
@ 2002-02-25 21:20  6% Dave Poirier
  0 siblings, 0 replies; 200+ results
From: Dave Poirier @ 2002-02-25 21:20 UTC (permalink / raw)


I'm currently trying to write a basic device driver in Ada95.  The 
device is a simple text mode videocard under a x86 PC. I got the boot 
record going as well as a small rtk of my own which allow me to run 
simple programs that return values.

My next step is to start to write device drivers in Ada95 using this 
same setup, so as to have as useable os sooner or later.  As my first 
try, I decided to create a small vga driver for text mode.  This 
requires that I write in memory from 0xB8000 to 0xB8A9F.

Here's what I tried:
--------------------
with System.Address_to_Access_Conversions;

procedure Hello is
   type Screen is array(0 .. 999) of Character;
   type Char_Ptr is access Screen;
   package CharPtrs is new System.Address_To_Access_Conversions(Char_Ptr);
   Vga : CharPtrs.Object_Pointer;
   VgaAddress : System.Address;

begin
   VgaAddress := System.Address(16#B8000#);
   Vga := CharPtrs.To_Pointer(VgaAddress);
   Vga.all(0) := '!';
end Hello;

---------

Ofcourse that doesn't compile, it doesn't like the assignment I'm trying 
to do for VgaAddress :=...

Now, could any of you indicate how I'm supposed to do that as properly 
as possible using only Ada95?

I'm compiling with GNAT to generate a .s which I then compile with my 
own wrappers, so as long as it's valid Ada95 and that it can get to 
generating my .o it should be fine.

Thanks for any help.




^ permalink raw reply	[relevance 6%]

* Re: Refactoring and Ada
  2002-02-22 14:37  5%                             ` Pat Rogers
@ 2002-02-22 21:23  0%                               ` Randy Brukardt
  0 siblings, 0 replies; 200+ results
From: Randy Brukardt @ 2002-02-22 21:23 UTC (permalink / raw)


> or, for that matter, via System.Address_To_Access_Conversions
> (for Integer in this example).

Or, pragma Import of a C object or subprogram. Or reading from a stream.
(The intended uses of the attribute).

> The OP's saying that 'Valid is useless isn't justified by the problem
with
> unchecked conversion, IMHO.

I agree with this. 'Valid is (almost) useless combined with UC, but that
is true whether or not UC is erroneous -- in most cases (other than
[very] sparse enums and float values) it is trivial to check before
applying UC. So it isn't needed in those cases. That can't be done in
the other cases - C or a file could contain anything.

> What am I missing?

Nothing that I see. The ARG discussion was narrowly focused around
'Valid and UC -- perhaps not everyone realized that.

   Randy Brukardt.






^ permalink raw reply	[relevance 0%]

* Re: Refactoring and Ada
  @ 2002-02-22 14:37  5%                             ` Pat Rogers
  2002-02-22 21:23  0%                               ` Randy Brukardt
  0 siblings, 1 reply; 200+ results
From: Pat Rogers @ 2002-02-22 14:37 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> wrote in message
news:u78hac6o7iku15@corp.supernews.com...
> >No, I was asking for the exegesis in terms of the RM for Richard's much
> more sweeping "comdemnation" of the attribute.  ("Condemnation" is too
> strong here, but you get the idea.)
>
> Reading AI-167 might help some
> (http://www.ada-auth.org/cgi-bin/cvsweb.cgi/AIs/AI-00167.TXT?rev=1.5).
> But this AI is still under construction (it is not, and never has been,
> approved, contrary to the statement of someone else here), and
> undoubtably will change.
<snip>
> The problem rule is 13.9.1(12), which makes the CALL to
> Unchecked_Conversion erroneous if the result is invalid. And this rule
> is intended (I forget why, Bob?).

Thanks (again) for the pointer to the AI in progress.  Clearly there is a
problem for unchecked conversion in this case.

However, unchecked conversion isn't the only way to get the value to which
'Valid is applied.  For example, via RM 13.9.2(11):

  P : aliased Positive;

  K : Integer;
  for K'Address use P'Address;

begin
  K := 0;
  if P'Valid then ...

or, for that matter, via System.Address_To_Access_Conversions (for Integer in
this example).

The OP's saying that 'Valid is useless isn't justified by the problem with
unchecked conversion, IMHO.

What am I missing?

Pat





^ permalink raw reply	[relevance 5%]

* Re: Ada 200X Assertions
  @ 2001-12-04  8:54  5% ` Lutz Donnerhacke
  0 siblings, 0 replies; 200+ results
From: Lutz Donnerhacke @ 2001-12-04  8:54 UTC (permalink / raw)


* Richard Riehle wrote:
>Does anyone know whether there is still serious
>consideration for pre-, post-, and invariant assertions
>in the next version of ISO Standard Ada?

I'd like to go further and request Anna.

And like to append an old article on this subject:
\f
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.
        (currently possible)
      - 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	[relevance 5%]

* Re: Using MySQL from ADA program
  @ 2001-11-29 19:00  5% ` M. A. Alves
  0 siblings, 0 replies; 200+ results
From: M. A. Alves @ 2001-11-29 19:00 UTC (permalink / raw)
  To: comp.lang.ada

On Thu, 29 Nov 2001, Preben Randhol wrote:
> Did you try GNADE? Isn't it better if there is one standard library for
> doing database stuff than several half hearted hacks?

Some years ago when I needed to bind Postgres I examined the landscape
very carefully---and decided to do it myself. Curiously enough, the
example for Postgres posted by Adrian Knoth previously on this thread uses
my solution.

Recently I needed to bind Mysql and now I just skimmed the landscape with
the previous pattern in mind.  The result was similarly dissatisfying, but
perhaps I missed something: you can surely correct my view by pointing out
one real example of an Ada program accessing a MySQL server via GNADE or
another solution (that is not my package).

I agree it is better to have one standard database library... that works.

I _will_ test the OBDC bindings out there someday.

> And please stop attaching BASE64 encoded attachments to usenet. Either
> send it by mail to the one that need it or give an URL.

I thought MIME was everywhere by now. Sorry. Here is the package spec in
plain text:

-- mysql.ads
-- (c) 2001 M�rio Amado Alves
-- Email: maa@liacc.up.pt

with System; use System;
with System.Address_To_Access_Conversions;
with Interfaces.C; use Interfaces.C;

package MySQL is

  type Connection_Type is private;
  type Action_Type is access procedure(Connection: in out Connection_Type);

  procedure Open
    (Connection : out Connection_Type  ;
     Host       : in  String  := ""    ;
     Port       : in  Natural := 0     ;
     Socket     : in  String  := ""    ;
     User       : in  String  := ""    ;
     Password   : in  String  := ""    ;
     Compress   : in  Boolean := False ;
     SSL        : in  Boolean := False ;
     ODBC       : in  Boolean := False );

  procedure Close
    (Connection : in out Connection_Type);

  procedure Execute
    (Connection : in out Connection_Type;
     Command : in String);

  procedure For_Each
    (Connection : in out Connection_Type;
     Action : in Action_Type);

  function Get
    (Connection : in Connection_Type;
     Field : in Positive)
    return String;

  function Escape(S : String) return String;

  -- PACKAGE-SPECIFIC EXCEPTIONS
  Break                   : exception;
  Null_Value              : exception;
  No_Room_For_Connection  : exception;

  -- EXCEPTIONS ASSOCIATED WITH ERROR CODES
  Unknown_Error           : exception;
  Socket_Create_Error     : exception;
  Connection_Error        : exception;
  Host_Error              : exception;
  IP_Socket_Error         : exception;
  Unknown_Host            : exception;
  Server_Gone             : exception;
  Version_Error           : exception;
  Out_Of_Memory           : exception;
  Wrong_Host_Info         : exception;
  Localhost_Connection    : exception;
  TCP_Connection          : exception;
  Server_Handshake_Error  : exception;
  Server_Lost             : exception;
  Commands_Out_Of_Sync    : exception;
  Named_Pipe_Connection   : exception;
  Named_Pipe_Wait_Error   : exception;
  Named_Pipe_Open_Error   : exception;
  Named_Pipe_State_Error  : exception;
  Cannot_Read_Charset     : exception;
  Net_Packet_Too_Large    : exception;

  -- BOTH!
  Undocumented_Error_Code : exception;

private

  type Array_Of_Lengths is array(Positive) of Unsigned_Long;
  type Array_Of_Values is array(Positive) of Address;

  package Convert_Lenghts is new
    System.Address_To_Access_Conversions(Array_Of_Lengths);

  package Convert_Values is new
    System.Address_To_Access_Conversions(Array_Of_Values);

  type Connection_Type is record
    C_Connection : Address;
    C_Result     : Address;
    Lengths      : Convert_Lenghts.Object_Pointer;
    Values       : Convert_Values.Object_Pointer;
  end record;

end MySQL;

-- USAGE GUIDE
--
-- This package provides communication with a MySQL.  Mandatory order
-- of subprogram calls:
--
--   Open --> Execute --> (For_Each --> Action --> (Get)) --> Close
--              /|\                                        |
--               |_________________________________________|
--
-- The sequence in parenthesis is associated with a row-returning Execute
-- call.  Violation of this is bound to raise Commands_Out_Of_Sync.
--
-- The Command parameter of Execute must be a valid SQL command. Violation
-- raises Undocumented_Error_Code with a message containing the code and
-- the C API message (in this order separated by a space).
--
-- Procedure For_Each iterates over all rows that have resulted from the
-- last call to Execute.  The user-defined Action procedure is invoked
-- upon each iteration.
--
-- Function Get is available for use in Action: in the course of each
-- iteration, Get returns the non-NULL value of the indexed field,
-- or else (i.e. the value is NULL) it raises Null_Value.  Note field
-- indexes start at 1.  Also, attention: there is no upper bound check
-- for field indexes!
--
-- Exception Break raised in Action exits the traversal immediately
-- (and it is not propagated).

-- REVISION HISTORY (see also body)
-- 2001-10-23: started (spec and body)
-- 2001-10-24: decided for single package and procedures Open/Close
-- 2001-10-25: fleshed Open, Close, Execute; defined exceptions
--   (defined associated named numbers and procedure Assess... in body)
-- 2001-10-29: decided for For_Each; completed and tested
-- 2001-10-31: cosmetics
-- 2001-11-06: function Escape
-- 2001-11-23: added exception No_Room_For_Connection; cosmetics

-- 
   ,
 M A R I O   data miner, LIACC, room 221   tel 351+226078830, ext 121
 A M A D O   Rua Campo Alegre, 823         fax 351+226003654
 A L V E S   P-4150-180 PORTO, Portugal    mob 351+939354002






^ permalink raw reply	[relevance 5%]

* Re: Ada Address = C pointer ?
  2001-10-30 19:53  0% ` tmoran
@ 2001-10-31 13:01  0%   ` M. A. Alves
  0 siblings, 0 replies; 200+ results
From: M. A. Alves @ 2001-10-31 13:01 UTC (permalink / raw)
  To: comp.lang.ada

On Tue, 30 Oct 2001 tmoran@acm.org wrote:
> . . .
>
> > So, either way (Interfaces.C.Pointers vs.
> > System.Address_To_Access_Conversions), _assumptions_ are made (by the
> > programmer).
>
> . . . Does the RM even suggest that a System.Address has anything to
> do with interfacing to other languages?

Hmmm... touch�.

> . . .
>
>   In the meantime, put in a comment for future maintainers that
> your code assumes a specific Gnat version on a specific platform.

Something like that, yes.

> . . .

Thanks,

-- 
   ,
 M A R I O   data miner, LIACC, room 221   tel 351+226078830, ext 121
 A M A D O   Rua Campo Alegre, 823         fax 351+226003654
 A L V E S   P-4150 PORTO, Portugal        mob 351+939354002





^ permalink raw reply	[relevance 0%]

* Re: Ada Address = C pointer ?
  @ 2001-10-30 19:53  0% ` tmoran
  2001-10-31 13:01  0%   ` M. A. Alves
  0 siblings, 1 reply; 200+ results
From: tmoran @ 2001-10-30 19:53 UTC (permalink / raw)


> Interesting. The code is incompatible with GNAT.
  Of course it is.  The particular Gnat you are using has a System.Address
that only works within a single segment, so it does not include the
segment part.  The ARM suggests System.Address should be private,
presumably to discourage coding that depends on a particular
implementation.

> Ada                C
> --------------------
> Address       * void
> Address       * char
> Null_Address    NULL
>
> GNAT seems to honor these equivalences.  Does Janus?
  (I'm not sure I'd use the word "honor" to describe a particular
implementation artifact. ;)
  I haven't used any Janus compilers on other platforms, so can't answer
for them.  On x86's Janus appears to convert (I haven't experimented with this
since I use Access types) automagically on parameter passing, but I'm sure

  type Address_List is array(1 .. 10) of System.Address;
  X : Address_List;
  procedure Cfunc(X : out Address_List);
  pragma Import(C, Cfunc);
---
  void Cfunc(char **p)

would give unpleasant results.

Do all versions of Gnat on all platforms implement those particular
equivalences?  Do even all other Ada compilers on your current platform
implement them?

> Yes, I know that null = NULL seems an obvious interpretation of
> "C-compatible", but the RM is not known for relying on the obvious.
>
> So, either way (Interfaces.C.Pointers vs.
> System.Address_To_Access_Conversions), _assumptions_ are made (by the
> programmer).
  Can you suggest any other reasonable interpretation besides null = NULL?
Does the RM even suggest that a System.Address has anything to do with
interfacing to other languages?  The RM may not be obvious, but it doesn't
*try* to mislead.

> But I agree a Pointers idiom is a viable, perhaps better, alternative to a
> System one. Perhaps I'll change my code some day.
  In the meantime, put in a comment for future maintainers that
your code assumes a specific Gnat version on a specific platform.
(Having maintained code dependent on a particular, ancient, version of
a compiler, I offer my condolences to those maintainers.)



^ permalink raw reply	[relevance 0%]

* Re: Ada Address = C pointer ?
  @ 2001-10-30 14:41  5% ` M. A. Alves
  0 siblings, 0 replies; 200+ results
From: M. A. Alves @ 2001-10-30 14:41 UTC (permalink / raw)
  To: comp.lang.ada

On Tue, 30 Oct 2001, Matthew Heaney wrote:
> "M. A. Alves" <maa@liacc.up.pt> wrote in message
> news:mailman.1004446456.21280.comp.lang.ada@ada.eu.org...
> > However, I am still not sure of the equivalence between null (a value of
> > Pointer) and NULL (C), i.e. is it garanteed that if the C function returns
> > NULL get_long_array returns null?
>
> Yes.  See RM95 B3.2 (17).

Yes, I know that null = NULL seems an obvious interpretation of
"C-compatible", but the RM is not known for relying on the obvious.

So, either way (Interfaces.C.Pointers vs.
System.Address_To_Access_Conversions), _assumptions_ are made (by the
programmer).

But I agree a Pointers idiom is a viable, perhaps better, alternative to a
System one. Perhaps I'll change my code some day.

-- 
   ,
 M A R I O   data miner, LIACC, room 221   tel 351+226078830, ext 121
 A M A D O   Rua Campo Alegre, 823         fax 351+226003654
 A L V E S   P-4150 PORTO, Portugal        mob 351+939354002





^ permalink raw reply	[relevance 5%]

* Re: A copy question....
  2001-10-17  0:18  5% ` tmoran
@ 2001-10-17  1:14  6%   ` David Botton
  0 siblings, 0 replies; 200+ results
From: David Botton @ 2001-10-17  1:14 UTC (permalink / raw)


I was showing my "favorite" method. The use of the 'Img was part of the test
driver. It is a convenience that I am surprised has not been adopted by
other vendors.

I admit that since most of my Ada programming is with GNAT, I get lazy about
portability to other compilers.

Here is a more universal version:

with Ada.Text_IO; use Ada.Text_IO;

with System.Address_To_Access_Conversions;
with System;

with Interfaces;

procedure Block is

   type My_Array is array (Integer range <>) of Interfaces.Unsigned_32;

   Stuff_In_Memory : My_Array (1 .. 200) := (others => 999);

   Address     : System.Address := Stuff_In_Memory (1)'Address;
   Data_Length : Natural := Stuff_In_Memory'Length;
   -- Assuming of Unsigned_32s

   type The_Array is new My_Array (1 .. Data_Length);
   pragma Pack (The_Array);

   package Array_Copier is
      new System.Address_To_Access_Conversions (The_Array);

   Copied_Array : The_Array := Array_Copier.To_Pointer (Address).all;
begin
   for N in Copied_Array'Range loop
      Put_Line (Interfaces.Unsigned_32'Image (Copied_Array (N)));
   end loop;
end Block;




<tmoran@acm.org> wrote in message
news:t74z7.24114$gT6.15011939@news1.rdc1.sfba.home.com...
>   Speaking of portability,
> >  function To_Pointer_To_The_Array is
> >     new Ada.Unchecked_Conversion (System.Address, Pointer_To_The_Array);
> is not portable, while
> package System.Address_To_Access_Conversions
> is specifically designed to do what you want.
> > Put_Line (Copied_Array (N)'Img);
>   The 'Img attribute is a "vendor special", 'Image would be portable.





^ permalink raw reply	[relevance 6%]

* Re: A copy question....
  @ 2001-10-17  0:18  5% ` tmoran
  2001-10-17  1:14  6%   ` David Botton
  0 siblings, 1 reply; 200+ results
From: tmoran @ 2001-10-17  0:18 UTC (permalink / raw)


> The use of
> >   for Source'Address use Address;
> is not portable.
>
> Rational would initialise Source to 0's (unless the Pragma Import is used).
  It's not a portability problem, it's an error in the code I posted. :(
Most compilers of my acquaintance only initialize things with
initializers, and don't initialize simple arrays of integers.  But that
just demonstrates the disadvantages of not using a diversity of compilers.
Yes indeed there should be a Pragma Import.
  As I read the LRM, the array Source ought to be declared aliased, also.
  Speaking of portability,
>  function To_Pointer_To_The_Array is
>     new Ada.Unchecked_Conversion (System.Address, Pointer_To_The_Array);
is not portable, while
package System.Address_To_Access_Conversions
is specifically designed to do what you want.
> Put_Line (Copied_Array (N)'Img);
  The 'Img attribute is a "vendor special", 'Image would be portable.



^ permalink raw reply	[relevance 5%]

* Re: A copy question....
  2001-10-15 11:21  5% ` Dale Stanbrough
@ 2001-10-15 11:30  0%   ` Dale Stanbrough
  0 siblings, 0 replies; 200+ results
From: Dale Stanbrough @ 2001-10-15 11:30 UTC (permalink / raw)


Dale Stanbrough wrote:

> Convert the address to an access type using an instantiation of the 
> generic
> 
>    System.Address_To_Access_Conversions.To_Pointer
> 
> and then dereference the pointer generated by the function...
> 
>    function Address_To_Int_Pointer is new
>       To_Pointer (Int_Pointer);
> 
> ...
>    for i in Array'range loop
>       Array (i) := Address_To_Int_Pointer (Address).all;
>       Address := Address + Unsigned_32'Size/8;
>       -- i think there is a constant somewhere i should use instead of 8
>    end loop;


Silly me. I didn't check the code. System.Address_To_Access_Conversion
is a generic package, not a package with a generic function.
You'll need to instantiate it as...
  
   package To_Int_Pointers is
      new System.Address_To_Access_Conversion (Int_Pointer);

and then you'll call the To_Pointer function in this package.


Dale



^ permalink raw reply	[relevance 0%]

* Re: A copy question....
  @ 2001-10-15 11:21  5% ` Dale Stanbrough
  2001-10-15 11:30  0%   ` Dale Stanbrough
  0 siblings, 1 reply; 200+ results
From: Dale Stanbrough @ 2001-10-15 11:21 UTC (permalink / raw)


In article <9qedad$i1p$1@newstoo.ericsson.se>,
 "Zebylon" <sebastian.madunic@esavionics.se> wrote:

> If you have an system.address variable, an data length variable and an array
> of Unsigned_32. How can you move the data ranging between the address and
> the address+data_length into the array?
> 
> I.G.
> 
> Address               : System.address      := 0x0200_0000;
> Data_Length       : Natural                       := 200; --bytes
> Array                   : array range (integer 0..375) of Unsigned_32;
> 
> Is there some smart way of placing the data in the array...?


Convert the address to an access type using an instantiation of the 
generic

   System.Address_To_Access_Conversions.To_Pointer

and then dereference the pointer generated by the function...

   function Address_To_Int_Pointer is new
      To_Pointer (Int_Pointer);

...
   for i in Array'range loop
      Array (i) := Address_To_Int_Pointer (Address).all;
      Address := Address + Unsigned_32'Size/8;
      -- i think there is a constant somewhere i should use instead of 8
   end loop;

note that the "+" operator is from System.Storage_Elements

Alternatively you could dive into either the OS API, which could well 
have a block move instruction (realloc?), or call any relavent assembler 
instruction.

Dale



^ permalink raw reply	[relevance 5%]

* Re: pointer in C & in  Ada
  @ 2001-08-08  3:14  5% ` DuckE
  0 siblings, 0 replies; 200+ results
From: DuckE @ 2001-08-08  3:14 UTC (permalink / raw)


In C "void *p" means that 'p' contains a pointer to an address where the
type of data at that address is unspecified.  This corresponds to an Ada
variable of type System.Address.

In C you cannot access data using the pointer unless you cast it to a
particular type.  This corresponds to using
System.Address_To_Access_Conversions in Ada.

SteveD

BTW: While my answer may not be techically correct, I believe it will lead
you to something that works.

"Lin" <lin@post.com> wrote in message
news:86772402.0108071439.1c3e1e40@posting.google.com...
> If "int *p" declares that pointer p points to integer type, then
> what's the meaning of "void *p"? How can I represent it(void *p) in
> Ada language?
>
> Many thanks,
> Lin





^ permalink raw reply	[relevance 5%]

* Re: newbie q: access types getting address
    2001-06-13 23:56  5% ` James Rogers
@ 2001-06-14  1:49  5% ` tmoran
  1 sibling, 0 replies; 200+ results
From: tmoran @ 2001-06-14  1:49 UTC (permalink / raw)


>I want to get the address of a particular object that is getting passed into
>...
>in Ada, but this is for a Windows API call binding.  Sorry if this is
  For a Windows binding you almost certainly want 'access, not 'address.
(Though System.Address_To_Access_Conversions can interconvert the two.)

>return &Obj;
>and
>return &Array[5];
 return Obj'access;
 return Array(5)'access;
If you get accessibility level errors, the compiler is telling you
that you are creating a pointer that may outlive what it's pointing to.
If you're sure what you are doing is safe, you can
  return Obj'unchecked_access;
etc.  You'll see a lot of that in Ada code accessing Windows' API.



^ permalink raw reply	[relevance 5%]

* Re: newbie q: access types getting address
  @ 2001-06-13 23:56  5% ` James Rogers
  2001-06-14  1:49  5% ` tmoran
  1 sibling, 0 replies; 200+ results
From: James Rogers @ 2001-06-13 23:56 UTC (permalink / raw)


The address of an object can be identified as a System.Address type.

Read the Ada LRM section 13.7.2 for details.

What you probably really want to do is convert to or from the
System.Address type from an Ada access type. This can be done using
the System.Address_To_Access_Conversions generic package.
Once you convert from the C++ &Array[5] to an access to an Ada
array, you can access the individual elements using normal Ada
indexing.

Jim Rogers
Colorado Springs, Colorado USA

Jesse Farmer wrote:
> 
> Please pardon my ignorance, but I have not been able to find how to do this
> on the web.
> 
> I want to get the address of a particular object that is getting passed into
> a function.  How can I do this?
> Also, how can I get the address of some arbitrary element of an array?
> 
> Essentially, I want the return value of the following c++ statements:
> 
> return &Obj;
> and
> return &Array[5];
> 
> I understand that having pointers all over the place is somewhat discouraged
> in Ada, but this is for a Windows API call binding.  Sorry if this is
> obvious and I have overlooked it.  Any informative responses would be
> greatly appreciated.  Thanks for your time + bandwidth.
> 
> -Jesse Farmer
> University of Cincinnati



^ permalink raw reply	[relevance 5%]

* Re: Locating a subprogram at user-specified address
  2001-06-12 14:36  5% ` Ted Dennison
@ 2001-06-12 15:29  0%   ` Marin David Condic
  0 siblings, 0 replies; 200+ results
From: Marin David Condic @ 2001-06-12 15:29 UTC (permalink / raw)


I seem to recall in Ada you could do some version of "for-use-at" for a
subprogram to get it to a specific address. Or even "for
Subprogram_Name'Address use ..." which I think is described in 13.3(10)
(Then you got to fight with the linker trying to tell it: "No. I *really*
meant to do that!") Details would be specified in Chapter 13 if so & then
you get to go looking for your compiler documentation to see what
Implementation Defined Restrictions are placed on it.

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/


"Ted Dennison" <dennison@telepath.com> wrote in message
news:5OpV6.5250$pb1.200601@www.newsranger.com...
> In article <tic9rgqlp8fnc1@corp.supernews.com>, jaya says...
> >My query is : How do I locate a subprogram or package at a known memory
> >address. Using "to_address" attribute works only for objects(user-defined
> >variables) and not for subprograms or packages.
>
> Do you mean that you want your subprogram to be put there, or that you
know
> there is already one there, and you want to call it?
>
> If the former, its a linker/loader issue. If its the latter, I suspect
there's
> some gymnastics you can perform with System.Address_To_Access_Conversions
and
> subprogram pointers.
>
> ---
> T.E.D.    homepage   - http://www.telepath.com/dennison/Ted/TED.html
>           home email - mailto:dennison@telepath.com





^ permalink raw reply	[relevance 0%]

* Re: Locating a subprogram at user-specified address
  @ 2001-06-12 14:36  5% ` Ted Dennison
  2001-06-12 15:29  0%   ` Marin David Condic
  0 siblings, 1 reply; 200+ results
From: Ted Dennison @ 2001-06-12 14:36 UTC (permalink / raw)


In article <tic9rgqlp8fnc1@corp.supernews.com>, jaya says...
>My query is : How do I locate a subprogram or package at a known memory 
>address. Using "to_address" attribute works only for objects(user-defined 
>variables) and not for subprograms or packages.  

Do you mean that you want your subprogram to be put there, or that you know
there is already one there, and you want to call it?

If the former, its a linker/loader issue. If its the latter, I suspect there's
some gymnastics you can perform with System.Address_To_Access_Conversions and
subprogram pointers.

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



^ permalink raw reply	[relevance 5%]

* Re: records containing variable length arrays [long]
  2001-06-08 16:42  0%   ` Jeffrey Carter
@ 2001-06-08 22:28  0%     ` Jeffrey Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey Carter @ 2001-06-08 22:28 UTC (permalink / raw)


Jeffrey Carter wrote:
> 
> Mats Karlssohn wrote:
> >
> > I ended up declaring the record in the way that was discussed earlier.
> > Then I declare an access type to the record and use an instance of
> > System.Address_To_Access_Conversions to convert the C pointer to an
> > Ada pointer. I'll probably wrap another layer around the buffer
> > manager and let that glue perform the address to access conversion.
> 
> You can probably avoid the conversion of the pointer. Given
> 
> type Message (...) is record ...;
> for Message use record ...;
> 
> and something like
> 
> void get (buffer* p, int* len);

This is probably wrong, but my C is bad, so I tend to get things wrong.
What is needed here is the equivalent of Ada's "P : out Ptr_To_Byte",
which on second look is probably

byte** p

> 
> you can define
> 
> type Message_Ptr is access all Message;
> pragma Convention (C, Message_Ptr);
> 
> procedure Get (Ptr : out Message_Ptr; Length : out Interfaces.C.Int);
> pragma Import (C, Get, "get");
> 
> and use the access value you get from Get directly.
> 
> > Given this declaration and representation:
> >
> >    type Message(Response_Length : Byte; Output_Length : Byte) is
> >       record
> >          Magic           : Word;
> >          Operation       : Word;
> >          Status          : Word;
> >          Response_Data   : Buffer(1..Response_Length);
> >          Output_Data     : Buffer(1..Output_Length);
> >          CRC             : Word;
> >       end record;
> >
> >    for Message use
> >       record
> >           Magic           at 0 range 0..15;
> >           Operation       at 2 range 0..15;
> >           Status          at 4 range 0..15;
> >           Response_Length at 6 range 0.. 7;
> >           Output_Length   at 7 range 0.. 7;
> >       end record;
> >
> >    pragma Pack(Message);
> >
> > Is there a way to explicitly put at least the CRC element into the
> > representation clause ? My experiments haven't gotten me anywhere
> > on this part.
> 
> Only if it comes before the variable-length part of the record. The
> values used in a record representation clause have to be static, which
> means known at compile time.
> 
> --
> Jeffrey Carter


-- 
Jeffrey Carter



^ permalink raw reply	[relevance 0%]

* Re: records containing variable length arrays [long]
  @ 2001-06-08 16:42  0%   ` Jeffrey Carter
  2001-06-08 22:28  0%     ` Jeffrey Carter
  0 siblings, 1 reply; 200+ results
From: Jeffrey Carter @ 2001-06-08 16:42 UTC (permalink / raw)


Mats Karlssohn wrote:
> 
> I ended up declaring the record in the way that was discussed earlier.
> Then I declare an access type to the record and use an instance of
> System.Address_To_Access_Conversions to convert the C pointer to an
> Ada pointer. I'll probably wrap another layer around the buffer
> manager and let that glue perform the address to access conversion.

You can probably avoid the conversion of the pointer. Given

type Message (...) is record ...;
for Message use record ...;

and something like

void get (buffer* p, int* len);

you can define

type Message_Ptr is access all Message;
pragma Convention (C, Message_Ptr);

procedure Get (Ptr : out Message_Ptr; Length : out Interfaces.C.Int);
pragma Import (C, Get, "get");

and use the access value you get from Get directly.

> Given this declaration and representation:
> 
>    type Message(Response_Length : Byte; Output_Length : Byte) is
>       record
>          Magic           : Word;
>          Operation       : Word;
>          Status          : Word;
>          Response_Data   : Buffer(1..Response_Length);
>          Output_Data     : Buffer(1..Output_Length);
>          CRC             : Word;
>       end record;
> 
>    for Message use
>       record
>           Magic           at 0 range 0..15;
>           Operation       at 2 range 0..15;
>           Status          at 4 range 0..15;
>           Response_Length at 6 range 0.. 7;
>           Output_Length   at 7 range 0.. 7;
>       end record;
> 
>    pragma Pack(Message);
> 
> Is there a way to explicitly put at least the CRC element into the
> representation clause ? My experiments haven't gotten me anywhere
> on this part.

Only if it comes before the variable-length part of the record. The
values used in a record representation clause have to be static, which
means known at compile time.

-- 
Jeffrey Carter



^ permalink raw reply	[relevance 0%]

Results 1-200 of ~400   | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2001-06-06 19:59     records containing variable length arrays [long] Mats Karlssohn
2001-06-08 12:32     ` Mats Karlssohn
2001-06-08 16:42  0%   ` Jeffrey Carter
2001-06-08 22:28  0%     ` Jeffrey Carter
2001-06-12 14:30     Locating a subprogram at user-specified address jaya
2001-06-12 14:36  5% ` Ted Dennison
2001-06-12 15:29  0%   ` Marin David Condic
2001-06-13 23:24     newbie q: access types getting address Jesse Farmer
2001-06-13 23:56  5% ` James Rogers
2001-06-14  1:49  5% ` tmoran
2001-08-07 22:39     pointer in C & in Ada Lin
2001-08-08  3:14  5% ` DuckE
2001-10-15 10:40     A copy question Zebylon
2001-10-15 11:21  5% ` Dale Stanbrough
2001-10-15 11:30  0%   ` Dale Stanbrough
2001-10-16 10:09     Mark Doherty
2001-10-17  0:18  5% ` tmoran
2001-10-17  1:14  6%   ` David Botton
2001-10-30 10:30     Ada Address = C pointer ? M. A. Alves
2001-10-30 19:53  0% ` tmoran
2001-10-31 13:01  0%   ` M. A. Alves
2001-10-30 14:19     Matthew Heaney
2001-10-30 14:41  5% ` M. A. Alves
2001-11-29 17:59     Using MySQL from ADA program Preben Randhol
2001-11-29 19:00  5% ` M. A. Alves
2001-12-04  3:53     Ada 200X Assertions Richard Riehle
2001-12-04  8:54  5% ` Lutz Donnerhacke
2002-02-01 15:13     Refactoring and Ada Paul Anderson
2002-02-08  9:24     ` Martin Dowie
2002-02-08 15:15       ` Ted Dennison
2002-02-10  1:30         ` Marc A. Criley
2002-02-11 15:27           ` Marin David Condic
2002-02-12 19:16             ` Simon Wright
2002-02-15 20:33               ` Matthew Heaney
2002-02-15 21:40                 ` Larry Kilgallen
2002-02-19 16:54                   ` Matthew Heaney
2002-02-19 19:39                     ` Larry Kilgallen
2002-02-20  4:23                       ` Richard Riehle
2002-02-20  9:58                         ` Pat Rogers
2002-02-20 17:14                           ` Matthew Heaney
2002-02-20 17:18                             ` Pat Rogers
2002-02-21  0:41                               ` Randy Brukardt
2002-02-22 14:37  5%                             ` Pat Rogers
2002-02-22 21:23  0%                               ` Randy Brukardt
2002-02-25 21:20  6% Device driver in Ada95 Dave Poirier
2002-03-03 14:58     64bit access to an array of 8bit values Dave Poirier
2002-03-04  3:15  7% ` Pat Rogers
2002-03-04  7:23  4% ` Jeffrey Carter
2002-04-26 16:36     Is this a GNAT bug??? Robert Quinn
2002-04-26 17:48     ` Mark Johnson
2002-04-29 15:45       ` Robert Quinn
2002-04-30  2:44         ` Robert Dewar
2002-04-30 16:41           ` Robert Quinn
2002-04-30 18:20  5%         ` tmoran
2002-04-30 21:55  4%         ` Mark Johnson
2002-04-30 13:27     ANN: GMGPL Claw Page Ted Dennison
2002-04-30 18:20  5% ` tmoran
2002-05-01 16:56  0%   ` Ted Dennison
2002-05-17  9:26  7% newbie to generic Grein, Christoph
     [not found]     <ac2hbs$ljq$1@newstoo.ericsson.se>
2002-05-17  9:35  8% ` Preben Randhol
2002-05-17 19:40  0% ` Jeffrey Carter
2002-05-23 13:50  5% Help with Copying Shared Memory to Local John Cupak
2002-05-25 16:47     slice'access? Robert Dewar
2002-05-25 18:28  4% ` slice'access? tmoran
2002-07-02 17:57     Simple Question - Direct Access to memory with ADA Fredrick Smith
2002-07-02 19:46  4% ` Pat Rogers
2002-07-22 16:56     worth the hassle? chris.danx
2002-07-22 17:56     ` chris.danx
2002-07-22 18:06       ` Stephen Leake
2002-07-22 21:06         ` chris.danx
2002-07-23 12:16  6%       ` chris.danx
2002-10-07 12:10     Pragma Import don't suppress access initialization Frédéric Ormancey
2002-10-07 17:25  5% ` Matthew Heaney
2002-10-07 19:49  0%   ` Jeffrey Carter
2002-11-11 14:54     Format of .adp files? Victor Porton
2002-11-11 15:55     ` Preben Randhol
2002-11-12 22:51       ` David C. Hoos, Sr.
2002-11-12 23:03         ` Preben Randhol
2002-11-13 14:45           ` Stephen Leake
2002-11-13 15:35             ` Preben Randhol
2002-11-13 17:30  6%           ` Stephen Leake
2002-11-14  9:43  0%             ` Preben Randhol
2002-11-14 14:57  0%               ` Timo Warns
2002-12-04 14:01  5% Size of a pointer to a tagged record Steven Murdoch
2002-12-04 15:16  0% ` Robert A Duff
2002-12-04 15:44  0%   ` Steven Murdoch
2002-12-04 17:17  0%     ` Robert A Duff
2002-12-04 17:56  4%       ` Steven Murdoch
2002-12-04 19:10  0%         ` Robert A Duff
2003-01-09 10:33  6% Generic and Access problem Sebastian Madunic
2003-01-29 10:09     AdaSDL and glTexImage2D Stefan Soos
2003-01-29 20:15  6% ` Chad R. Meiners
2003-01-30  9:52  0%   ` Stefan Soos
2003-02-10  8:26     "access constant" discriminant tmoran
2003-02-20  2:17  4% ` Matthew Heaney
2003-04-22 21:45     Q re pack & aliased Robert A Duff
2003-04-22 22:25  4% ` tmoran
2003-04-23  8:07     Vinzent Hoefler
2003-04-23 17:18  4% ` tmoran
2003-04-24 19:30  5% Allocating Memory with "new" Peter Richtmyer
2003-04-25  6:05  0% ` Vincent Smeets
2003-04-25 12:46     David C. Hoos
2003-04-25 22:19  6% ` Peter Richtmyer
2003-05-21 15:26     The old "Object.Method" syntax debate Marc A. Criley
2003-05-21 15:47     ` David C. Hoos
2003-05-22 14:32       ` Rodrigo Garcia
2003-05-22 15:39         ` David C. Hoos
2003-05-23  7:49           ` Rodrigo Garcia
2003-05-23  8:34             ` Dmitry A. Kazakov
2003-05-23 18:35               ` Alexander Kopilovitch
2003-05-25  5:38                 ` Robert I. Eachus
2003-05-25  9:13                   ` Dmitry A. Kazakov
2003-05-27  9:50                     ` John McCabe
2003-05-28  8:24                       ` Dmitry A. Kazakov
2003-05-28 12:36  5%                     ` Lutz Donnerhacke
2003-07-07 12:30     sqlite binding Ching Bon Lam
2003-07-07 14:16  5% ` Andreas Almroth
2003-07-30 11:31     Limited_Controlled types as 'out' arguments Lutz Donnerhacke
2003-07-30 12:22     ` Dmitry A. Kazakov
2003-07-30 12:32       ` Lutz Donnerhacke
2003-07-30 14:24         ` Dmitry A. Kazakov
2003-07-30 14:25           ` Lutz Donnerhacke
2003-07-30 14:48             ` Dmitry A. Kazakov
2003-07-30 15:15               ` Lutz Donnerhacke
2003-07-31 10:26                 ` Dmitry A. Kazakov
2003-07-31 10:54  6%               ` Lutz Donnerhacke
2003-07-31 11:50  0%                 ` Dmitry A. Kazakov
2003-07-30 15:52  5%         ` Lutz Donnerhacke
2003-07-30 12:31     ` Matthew Heaney
2003-07-30 12:57  6%   ` Lutz Donnerhacke
2003-10-07 14:43     C array to Ada pointer to unconstrained array without copying memory Duncan Sands
2003-10-07 18:30  4% ` tmoran
2003-10-07 19:24  0%   ` Duncan Sands
2004-01-03 18:52  6% gnat/linux:setitimer TIlman Glotzner
2004-02-08 21:26     [Q] non-limited record and "self-pointer" Georg Bauhaus
2004-02-09  0:58     ` Stephen Leake
2004-02-09  2:56       ` Georg Bauhaus
2004-02-09 12:50         ` Stephen Leake
2004-02-09 15:45  4%       ` Georg Bauhaus
2004-04-13  0:32     Access type conversions, how? Luke A. Guest
2004-04-13  1:25     ` Randy Brukardt
2004-04-13  8:08       ` Luke A. Guest
2004-04-13 15:11         ` chris
2004-04-13 16:01           ` Luke Guest
2004-04-13 17:54             ` chris
2004-04-13 19:31               ` Luke A. Guest
2004-04-13 22:51                 ` Luke A. Guest
2004-04-13 21:59                   ` Lutz Donnerhacke
2004-04-14 11:53                     ` Luke Guest
2004-04-14 12:07  5%                   ` Lutz Donnerhacke
2004-05-11 13:14     C bindings, Interfaces.C.Pointers etc Dr. Adrian Wrigley
2004-05-12  6:30  5% ` Martin Krischik
2004-05-25 21:00  4% Question on interface Ada to C James Alan Farrell
2004-05-25 21:30  0% ` Dale Stanbrough
2004-05-25 21:38  6% ` Simon Wright
2004-05-26 13:05  0%   ` James Alan Farrell
2004-05-26  7:34  0% ` Martin Krischik
2004-07-26 21:42     C array to ada record interface Ludovic Brenta
2004-07-27 21:04  5% ` tmoran
2004-07-28  2:42  0%   ` Robert I. Eachus
2004-07-29  5:56  6%     ` tmoran
2004-07-29 19:58  0%       ` Robert I. Eachus
2004-08-07  2:29     Longstanding GNAT bug, bad code, or both Jeff C,
2004-08-07 14:07     ` Longstanding GNAT bug, bad code, or both -- Answer..Bad code Jeff C,
2004-08-07 16:44       ` Stephen Leake
2004-08-08 11:26  5%     ` Simon Wright
2004-08-18 22:27     Ada access vs C/C++ pointers and references Keith H Duggar
2004-08-19  0:21  4% ` Nick Roberts
2004-10-10 19:50     Ada Pointer Size Problem skidmarks
2004-10-11  8:45     ` Martin Krischik
     [not found]       ` <1c2f5137.0410130505.57e03c@posting.google.com>
2004-10-14  3:46  5%     ` Steve
2004-11-10  2:41     Thick Ada bindings to C Win32 Brian May
2004-11-12 12:09     ` Nick Roberts
2004-11-12 23:29       ` Brian May
2004-11-13  0:51         ` Jeffrey Carter
2004-11-25 23:19           ` Brian May
2004-11-26 19:19             ` Jeffrey Carter
2004-11-27 23:56               ` Brian May
2004-11-28 23:45  4%             ` Brian May
2005-01-05 22:31  3% Converting access values Mark Lorenzen
2005-01-14 17:00     Ada equivalent for C-pointer? Duncan Sands
2005-01-14 20:05  5% ` tmoran
2005-01-29 15:58  4% POSIX.Memory_Mapping.Map_Memory Adrian Hoe
2005-07-05 17:11     GCC 4.0 Ada.Containers Cursor danger Dmitriy Anisimkov
2005-07-06  5:52     ` Martin Dowie
2005-07-06  7:53       ` Pascal Obry
2005-07-06  8:44         ` Dmitriy Anisimkov
2005-07-06  9:03           ` Pascal Obry
2005-07-06  9:34             ` Dmitriy Anisimkov
2005-07-06  9:42               ` Pascal Obry
2005-07-06  9:45                 ` Dmitriy Anisimkov
2005-07-06 10:40                   ` Georg Bauhaus
2005-07-06 16:22                     ` Dmitriy Anisimkov
2005-07-06 18:12                       ` Georg Bauhaus
2005-07-07 12:29                         ` Dmitriy Anisimkov
2005-07-07 13:54                           ` Georg Bauhaus
2005-07-07 17:56                             ` Dmitriy Anisimkov
2005-07-07 22:12                               ` Georg Bauhaus
2005-07-15 18:03                                 ` Dmitriy Anisimkov
2005-07-16  1:45                                   ` Matthew Heaney
2005-07-17  3:55  4%                                 ` Dmitriy Anisimkov
2005-07-24 18:15     ++ of C in ada nicolas.b
2005-07-25 20:15  5% ` Robert A Duff
2005-09-25  2:37     Various Language Architecture Questions frankgerlach
2005-09-25  5:07     ` jimmaureenrogers
2005-09-25  7:24  5%   ` Martin Dowie
2005-10-05 15:22     volatile vs aliased REH
2005-10-05 18:22     ` Ludovic Brenta
2005-10-05 23:38  6%   ` Randy Brukardt
2005-10-06 13:40  0%     ` REH
2005-10-06 19:08  0%     ` REH
2005-10-11 15:17     [wxAda] Problem with "limited with" in a *real* application Lucretia
2005-10-11 21:23     ` Randy Brukardt
2005-10-12 17:06       ` Lucretia
2005-10-13 14:50         ` Lucretia
2005-10-13 16:18           ` Lucretia
2005-10-14  0:36             ` Randy Brukardt
2005-10-14 15:03  3%           ` Lucretia
2005-10-14 23:47  0%             ` Randy Brukardt
2005-10-11 15:58     hashed_maps Lucretia
2005-10-11 17:45  5% ` hashed_maps Jeffrey R. Carter
2006-02-21 14:37  6% binding to C: popen Poul-Erik Andreasen
2006-09-19 13:30     A novel design of linked lists (was: Address of an object) Dmitry A. Kazakov
2006-09-19 20:09  2% ` Adam Beneschan
2006-09-20  8:35  0%   ` A novel design of linked lists Dmitry A. Kazakov
2006-09-30 19:46     To collection (GNAT bug) Dmitry A. Kazakov
2006-10-01  1:21  5% ` Jeffrey R. Carter
2006-10-01  8:00  0%   ` Dmitry A. Kazakov
2006-10-01 19:23         ` Jeffrey R. Carter
2006-10-01 22:33           ` Frank J. Lhota
2006-10-02  3:08  5%         ` Jeffrey R. Carter
2006-10-02 13:02  0%           ` Frank J. Lhota
2006-09-30 21:20  5% generic package with procedure paramter gives "not subtype conformant with declaration" cl1
2006-10-01  1:27     ` Jeffrey R. Carter
2006-10-01  6:02       ` cl1
2006-10-01 19:43         ` Jeffrey R. Carter
2006-10-01 21:26  4%       ` cl1
2006-11-12  3:45     How to use Annex G.3 Vectors and Matrices in bindings to C arrays Jerry
2006-11-12 19:39     ` Jeffrey R. Carter
2006-11-13 11:20       ` Jerry
2006-11-13 19:09  4%     ` Jeffrey R. Carter
2007-03-28 15:53  5% Fun with Tasking mhamel_98
2007-03-28 16:55  0% ` Adam Beneschan
2007-03-28 17:53  0%   ` mhamel_98
2007-04-03 12:43     Finding out minimal allocation unit Stefan Bellon
2007-04-03 13:22     ` Georg Bauhaus
2007-04-03 13:34       ` Martin Krischik
2007-04-03 23:53         ` Randy Brukardt
2007-04-05  6:12           ` Stefan Bellon
2007-04-06 12:38  4%         ` Stephen Leake
2007-07-08  0:24     Pure, Storage_Size and Unchecked_Conversion Y.Tomino
2007-07-08  9:49  5% ` Georg Bauhaus
2007-07-08 10:41  5%   ` Y.Tomino
2007-08-02 19:21     Byte streams shaunpatterson
2007-08-03  5:34  4% ` Jeffrey R. Carter
2007-09-03  8:47     urgent question - generics shoshanister
2007-09-03 16:35     ` shoshanister
2007-09-04  0:38  4%   ` anon
2007-09-03  8:59     copying data between memory locations jef.mangelschots
2007-09-03 11:09  4% ` Niklas Holsti
2007-11-30 19:32  5% Access to fixed memory location Tomas Cernaj
2008-05-19  9:38     Pointer Sébastien
2008-05-19  9:53     ` Pointer Dmitry A. Kazakov
2008-05-19 10:13       ` Pointer Sébastien
2008-05-19 10:32  5%     ` Pointer Dmitry A. Kazakov
2008-05-27 11:19  5% Access procedure to pointer Sébastien
2008-05-27 16:51  0% ` Jeffrey R. Carter
2009-03-10 21:26  2% Representing image data Kenneth Almquist
2009-05-01 21:39     GNAT on WinXP: System.OS_Lib.Spawn raises Program_Error daniel.wengelin
2009-05-02 15:59     ` Martin
2009-05-02 20:39  5%   ` anon
2009-05-03  9:42  0%     ` Martin
2009-08-01 17:53     Interpretation of extensions different from Unix/Linux? vlc
2009-08-04 11:31     ` vlc
2009-08-04 11:44       ` Jacob Sparre Andersen
2009-08-04 12:25         ` vlc
2009-08-04 19:18           ` Jeffrey R. Carter
2009-08-04 19:52             ` Dmitry A. Kazakov
2009-08-04 20:45               ` Jeffrey R. Carter
2009-08-04 21:22                 ` Dmitry A. Kazakov
2009-08-04 22:04                   ` Jeffrey R. Carter
2009-08-05  8:33                     ` Dmitry A. Kazakov
2009-08-14  4:56                       ` Randy Brukardt
2009-08-14  8:01                         ` Dmitry A. Kazakov
2009-08-14 23:54                           ` Randy Brukardt
2009-08-15  8:10                             ` Dmitry A. Kazakov
2009-08-17 22:28                               ` Randy Brukardt
2009-08-18  7:48                                 ` Dmitry A. Kazakov
2009-08-18 20:37                                   ` Randy Brukardt
2009-08-19  8:04                                     ` Dmitry A. Kazakov
2009-08-19 22:40                                       ` Randy Brukardt
2009-08-20 19:40                                         ` Dmitry A. Kazakov
2009-08-21  0:08                                           ` Randy Brukardt
2009-08-21 10:11  6%                                         ` Enumeration of network shared under Windows (was: Interpretation of extensions different from Unix/Linux?) Dmitry A. Kazakov
2009-08-18 22:26     put of access type Rob Solomon
2009-08-18 23:17  5% ` Jeffrey R. Carter
2009-08-19  3:36  0%   ` Rob Solomon
2009-09-02 20:38     Gem 39 - compiler specific? Maciej Sobczak
2009-09-02 23:20  5% ` Randy Brukardt
2009-09-03  7:26  5%   ` Dmitry A. Kazakov
2009-09-03 15:26  4%     ` Adam Beneschan
2009-09-03 16:38  0%       ` Dmitry A. Kazakov
2009-09-03 17:27  0%         ` Adam Beneschan
2009-09-03 20:26  0%           ` Dmitry A. Kazakov
2009-09-03 22:06                 ` Randy Brukardt
2009-09-04  7:29                   ` Dmitry A. Kazakov
2009-09-04 12:07  4%                 ` Maciej Sobczak
2009-09-04 22:41  0%                   ` sjw
2010-08-20  1:40  6% Access to C_float wipes out float value deadlyhead
2010-10-03 11:27     Does mmap gives a right result?! Francesco PIRANEO GIULIANO
2010-10-04  8:05  5% ` Ludovic Brenta
2011-01-22  0:04     User Defined Storage Pool : did you ever experiment with it ? Yannick Duchêne (Hibou57)
2011-01-22  9:47  4% ` User Defined Storage Pool : Example anon
2011-02-03  8:08     How do I write directly to a memory address? mockturtle
2011-02-03 18:07  5% ` Jeffrey Carter
2011-07-24 15:59     acceess problem ldries46
2011-07-24 17:27     ` Simon Wright
2011-07-25  6:57       ` ldries46
2011-07-25  8:27         ` Simon Wright
2011-07-26 15:57           ` Gautier write-only
2011-07-26 17:43  5%         ` Adam Beneschan
2011-07-27 12:06  0%           ` Gautier write-only
2011-11-07 20:09     Memory Access awdorrin
2011-11-07 22:21     ` Adam Beneschan
2011-11-07 22:42  6%   ` Adam Beneschan
2011-11-07 23:13       ` Simon Wright
2011-11-07 23:32         ` Adam Beneschan
2011-11-08 12:22           ` awdorrin
2011-11-08 16:00  5%         ` Adam Beneschan
2011-11-08 17:46  5%           ` awdorrin
2011-11-08 20:11  4%             ` Adam Beneschan
2011-11-07 22:26  4% ` Niklas Holsti
2012-04-03  7:19     Dispatching callback handed over to C Natasha Kerensikova
2012-04-03  9:37     ` Maciej Sobczak
2012-04-03 12:02       ` Natasha Kerensikova
2012-04-03 14:42         ` Maciej Sobczak
2012-04-03 20:20           ` Randy Brukardt
2012-04-04  7:26  5%         ` Georg Bauhaus
2012-06-29  9:17     GNAT (GCC) Profile Guided Compilation Keean Schupke
2012-06-29  9:34     ` Dmitry A. Kazakov
2012-06-29 10:01       ` Keean Schupke
2012-06-29 10:24  3%     ` Keean Schupke
2012-06-29 12:26  0%       ` stefan-lucks
2012-06-29 12:51  0%         ` Keean Schupke
2012-06-29 14:14     ` gautier_niouzes
2012-06-29 15:05       ` gautier_niouzes
2012-06-29 17:03         ` Keean Schupke
2012-07-01 17:45           ` Georg Bauhaus
2012-07-01 22:57             ` Keean Schupke
2012-07-02 17:15               ` Georg Bauhaus
2012-07-02 17:26                 ` Keean Schupke
2012-07-02 23:48                   ` Keean Schupke
2012-07-04 10:38                     ` Georg Bauhaus
2012-07-04 10:57                       ` Keean Schupke
2012-07-04 12:38                         ` Georg Bauhaus
2012-07-14 20:17                           ` Keean Schupke
2012-07-14 20:43                             ` Niklas Holsti
2012-07-14 22:32                               ` Keean Schupke
2012-07-14 23:40                                 ` Keean Schupke
2012-07-15  7:15                                   ` Niklas Holsti
2012-07-15  8:27                                     ` Keean Schupke
2012-07-18 10:01  6%                                   ` Georg Bauhaus
2012-07-18 17:36  0%                                     ` Keean Schupke
2012-07-15 18:40     Efficient Sequential Access to Arrays Keean Schupke
2012-07-15 19:48     ` Dmitry A. Kazakov
2012-07-15 20:03       ` Keean Schupke
2012-07-15 21:44  5%     ` Georg Bauhaus
2012-10-30 22:03     Tasking troubles, unexpected termination Shark8
2012-10-30 23:01     ` Adam Beneschan
2012-10-31  1:05       ` Anh Vo
2012-10-31  2:17  2%     ` Shark8
2013-07-28 15:27  4% System.Address to Access to function/procedure conversion Tarek Ghaleb
2013-07-28 17:19     ` Jeffrey Carter
2013-07-28 19:05       ` Tarek Ghaleb
2013-07-28 20:04  4%     ` Jeffrey Carter
2013-09-26 14:23     Gnat's Handling of Record with Address Clause Eryndlia Mavourneen
2013-09-26 14:48  5% ` Adam Beneschan
2013-09-26 15:05  0%   ` Eryndlia Mavourneen
2013-09-26 15:21  4%     ` Adam Beneschan
2014-02-14  1:07     Best representation for spares Rego, P.
2014-02-14  9:19     ` Simon Wright
2014-02-15 16:06       ` Rego, P.
2014-02-15 19:55         ` Niklas Holsti
2014-02-15 20:25           ` Rego, P.
2014-02-15 21:35             ` Rego, P.
2014-02-16 10:02               ` Niklas Holsti
2014-02-16 13:40                 ` Rego, P.
2014-02-16 16:33  6%               ` Niklas Holsti
2014-10-14  1:17     passing messages between the tasks compguy45
2014-10-14  1:49     ` Adam Beneschan
2014-10-14 19:43       ` Shark8
2014-10-14 20:42         ` Jeffrey Carter
2014-10-14 21:08           ` compguy45
2014-10-14 22:22  5%         ` Shark8
2015-05-18  8:27     Linux kernel module - memory allocation q.kontinuum
2015-05-18  8:56  3% ` Niklas Holsti
2015-05-18  9:19  0%   ` q.kontinuum
2016-02-07 22:45  5% ANN: Cortex GNAT RTS 20160207 Simon Wright
2016-03-14 17:42  5% ANN: Cortex GNAT RTS 20160314 Simon Wright
2016-05-22 14:20  4% ANN: Cortex GNAT RTS 20160522 Simon Wright
2016-06-18 22:52     Generic Embedded List Nodes Warren
2016-06-19  2:14     ` Jeremiah
2016-06-19  2:21       ` Warren
2016-06-19  2:50         ` Warren
2016-06-19  4:45           ` Simon Wright
2016-06-19 18:27             ` Warren
2016-06-19 19:04               ` Dmitry A. Kazakov
2016-06-19 20:13                 ` Warren
2016-06-19 20:35                   ` Dmitry A. Kazakov
2016-06-20  2:42                     ` Warren
2016-06-20  7:25                       ` Dmitry A. Kazakov
2016-06-20 12:26                         ` Warren
2016-06-20 19:33                           ` Niklas Holsti
2016-06-21  2:20                             ` Warren
2016-06-21  5:52  4%                           ` Niklas Holsti
2016-06-21 10:31  5%                             ` Warren
2016-06-21 21:38  0%                               ` Niklas Holsti
2016-06-22 13:01  0%                               ` G.B.
2016-06-23  2:30  0%                                 ` Warren
2016-08-31 13:01     for X'Address use - and Volatile Maciej Sobczak
2016-08-31 19:36  4% ` Randy Brukardt
2017-08-29 20:28     win32 interfacing check (SetClipboardData) Xavier Petit
2017-08-30 16:04     ` Dmitry A. Kazakov
2017-08-31  1:41       ` Randy Brukardt
2017-09-01 12:53  5%     ` Xavier Petit
2017-10-11 21:52     Convert between C "void*" pointer and an access Victor Porton
2017-10-11 22:58  7% ` Victor Porton
2017-10-11 23:12  7%   ` Victor Porton
2017-10-12  1:01  4%     ` Victor Porton
2017-11-24 11:42  4% How to access an array using two different indexing schemes Jerry
2017-11-24 17:37  0% ` A. Cervetti
2017-11-24 21:48       ` Jerry
2017-11-24 22:15         ` Robert A Duff
2017-11-24 23:38           ` Jerry
2017-11-26  1:07  5%         ` Jerry
2017-11-26  8:58  0%           ` Dmitry A. Kazakov
2017-11-26 10:31  0%             ` Jerry
2017-11-24 18:37  0% ` Per Sandberg
2018-03-07 20:11  5% Ada Alternatives to Unrestricted_Access Jere
2018-03-07 20:38     ` Dmitry A. Kazakov
2018-03-07 22:29       ` Jere
2018-03-08  8:27         ` Dmitry A. Kazakov
2018-03-09  0:43           ` Jere
2018-03-09  0:52  6%         ` Jere
2018-03-09  8:28  0%           ` Dmitry A. Kazakov
2018-03-11  0:31  0%             ` Jere
2018-03-08  3:18  4% ` gautier_niouzes
2018-03-09  0:41  0%   ` Jere
2018-06-30 10:48     Strange crash on custom iterator Lucretia
2018-06-30 11:32     ` Simon Wright
2018-06-30 12:02       ` Lucretia
2018-06-30 14:25         ` Simon Wright
2018-06-30 14:33           ` Lucretia
2018-06-30 19:25             ` Simon Wright
2018-06-30 19:36               ` Luke A. Guest
2018-07-01 18:06                 ` Jacob Sparre Andersen
2018-07-01 19:59                   ` Simon Wright
2018-07-02 17:43                     ` Luke A. Guest
2018-07-02 19:42  3%                   ` Simon Wright
2018-07-03 14:08  5%                     ` Lucretia
2018-10-14 19:15     Examining individual bytes of an integer Henrik Härkönen
2018-10-14 21:04     ` Niklas Holsti
2018-10-15  7:49  5%   ` Niklas Holsti
2020-01-17 23:30     Calling a record type's methods (functions or procedure) when record is in an array Mace Ayres
2020-01-18 18:02     ` Mace Ayres
2020-01-21 20:51       ` Shark8
2020-01-23 15:00  6%     ` joakimds
2020-01-23 20:15  0%       ` Optikos
2020-05-05 11:04     How can one record component be local and another not? hreba
2020-05-05 15:45     ` Jeffrey R. Carter
2020-05-05 17:17       ` hreba
2020-05-05 19:08         ` Niklas Holsti
2020-05-06 19:31  3%       ` hreba
2020-12-28  9:44  5% Messing with access types Marek
2020-12-28 10:14     ` Dmitry A. Kazakov
2020-12-28 11:43  6%   ` Marek
2021-01-09  9:30     Record initialisation question DrPi
2021-01-09 10:46     ` Dmitry A. Kazakov
2021-01-10 16:41       ` DrPi
2021-01-11 21:48  6%     ` Shark8
2021-01-12 11:38  0%       ` Simon Wright
2021-01-12 15:01  0%         ` Shark8
2021-01-14 21:32  0%           ` Simon Wright
2021-01-14 12:58  5%       ` DrPi
     [not found]     <609a5eaf$0$20558$e4fe514c@news.kpn.nl>
2021-05-11 12:35  6% ` Printing the address Maxim Reznik
2021-09-04 21:39     GtkAda callback and event DrPi
2021-09-04 22:29     ` Dmitry A. Kazakov
2021-09-05 13:50       ` DrPi
2021-09-05 14:48  5%     ` Dmitry A. Kazakov
2021-09-05 14:58  0%       ` DrPi
2021-09-05 15:04  0%         ` DrPi
2021-09-05 15:12  0%           ` Dmitry A. Kazakov
2021-09-05 15:20  0%             ` DrPi
2023-09-04  9:19     project euler 26 CSYH (QAQ)
2023-09-04 11:06     ` Niklas Holsti
2023-09-04 12:39       ` Dmitry A. Kazakov
2023-09-04 16:01         ` Ben Bacarisse
2023-09-04 19:20           ` Dmitry A. Kazakov
2023-09-04 20:18             ` Ben Bacarisse
2023-09-04 21:00               ` Dmitry A. Kazakov
2023-09-04 23:16                 ` Ben Bacarisse
2023-09-05  7:23                   ` Dmitry A. Kazakov
2023-09-05 15:18                     ` Ben Bacarisse
2023-09-05 17:08                       ` Dmitry A. Kazakov
2023-09-06  1:10                         ` Ben Bacarisse
2023-09-06  7:06                           ` Dmitry A. Kazakov
2023-09-06 15:16                             ` Ben Bacarisse
2023-09-06 15:54                               ` Dmitry A. Kazakov
2023-09-06 23:32                                 ` Ben Bacarisse
2023-09-07  9:02  2%                               ` Dmitry A. Kazakov
2023-09-08  1:32  0%                                 ` Ben Bacarisse

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