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: Printing the address
       [not found]     <609a5eaf$0$20558$e4fe514c@news.kpn.nl>
@ 2021-05-11 12:41  5% ` Niklas Holsti
  0 siblings, 0 replies; 200+ results
From: Niklas Holsti @ 2021-05-11 12:41 UTC (permalink / raw)


On 2021-05-11 13:38, ldries46 wrote:
> I Get an contstraint error in the line:
> /if Boxes(n).Status = manual or Boxes(n).Status = auto then/


That is either becase "n" is not in Boxes'Range, or because Boxes(n) is 
null. From the rest of your message, it seems you believe that the 
latter is the cause.

(Btw, a briefer expression is

    if Boxes(n).Status in manual | auto then ...

assuming that Box_Status is a discrete type.)


> where/:
>     Boxes     : Ar_Box;
>     type Box is record
>        Status  : Box_Status;
>        Nrs_pos : Ar_Pos;
>        x_val   : integer;
>        y_val   : integer;
>        Fill    : integer;
>     end record;
> ///   type Box_Acces is access all Box;
> /   type Ar_Box is array (1 .. Max_Num) of Box_Acces;
> 
> /To debug the program I need to finf where the constraint is
> possible a 0x0 somewhere in Box


I assume you mean that some element of Boxes is a null access. That may 
or may not be represented as 16#0#.


> How can I priint this value I tried converting it to and integer but I 
> couldn'd get that working


You don't have to print the value. All that should matter to you is 
whether the value is null or not, so:

    Put (if Boxes(n) = null then "null" else "not null");

(If you really want to print the address, do

    System.Storage_Elements.Integer_Address'Image (
       System.Storage_Elements.To_Integer (Boxes(n).all'Address))

but be sure to check for a null value of Boxes(n) first.)

^ permalink raw reply	[relevance 5%]

* [SOLVED] Re: converting pointer to value
  2021-03-04 17:35  0%   ` Dmitry A. Kazakov
  2021-03-04 19:38  4%     ` Shark8
  2021-03-05 11:02  0%     ` Björn Lundin
@ 2021-03-09 12:07  3%     ` Björn Lundin
  2 siblings, 0 replies; 200+ results
From: Björn Lundin @ 2021-03-09 12:07 UTC (permalink / raw)


Den 2021-03-04 kl. 18:35, skrev Dmitry A. Kazakov:

Dmitry, this

> 
> You need not to know that:
> 
>     declare
>        P : SQLPOINTER := ...;
>        A : System.Address;
>        pragma Import (Ada, A);
>        for A'Address use P'Address;
>        T : My_Fancy_Object;
>        pragma Import (Ada, My_Fancy_Object);
>        for T'Address use A;
>     begin
>        ... -- Use T at P
> 

combined with

 > This looks wrong because SQLINTEGER is 32-bit. Why do not you use
 > Package System.Storage_Elements.Integer_Address instead, in order to
 > place an integer there?

put me on the right track.
The actual Ada question - rather than ODBC-API question - was how I get 
the value at a certain address.

First - there has to be a pointer to a value - meaning I needed a new 
overload of SqlBindParameter that takes an integer pointer as argument, 
not the integer itself (here called value_pointer)

declare
     L            : SQLULEN := SQLULEN(Length(Tclob));
     Rc           : Sqlreturn := 0;
     Local_Length : Sqllen := Sqllen(Sql_Len_Data_At_Exec(Sqlinteger(L)));
     Length_Pointer   : aliased PTR_SQLLEN     := null;
     Value_Pointer    : aliased PTR_SQLINTEGER := null;
   begin
     Length_Pointer := new Sqllen'(Local_Length);
     Value_Pointer := new SQLINTEGER'(1);

     Rc := Gnu.Db.Sqlcli.Sqlbindparameter
        (Statementhandle  => Statement_Handle,
         Parameternumber  => 1,
         Inputoutputtype  => Sql_Param_Input,
         Valuetype        => Sql_C_Char,
         Parametertype    => Sql_Longvarchar,
         Columnsize       => L,
         Decimaldigits    => 0,
         Value            => Value_Pointer,
         Bufferlength     => 0,
         Strlen_Or_Indptr => Length_Pointer);
     Text_Io.Put_Line("bind clob rc" & Rc'Img);
   end;


then I needed to understand that in call to
Rc := SqlParamdata (Statement_Handle, pvalue'Access);
pvalue itself contains the address of the value_pointer above,
and that I can only tie that address to a variable once the value is known.

   declare
     Rc         :  Sqlreturn := Sqlexecute (Statement_Handle);
     Pvalue     : aliased Sqlpointer;
     Sent       : Integer := 0;
     Datalen    : Integer := 0;
     Buffer_Len : Natural := 0;
     Chunk_Size : Natural := 1024*10; -- 10 k chunks
     S_Ptr      : Ptr_String;
     N          : Positive := 1;
     From,To    : Positive := 1;
   begin
     Text_Io.Put_Line ("Exec: " & Rc'Img);
     -- get address of value_pointer
     Rc := Sqlparamdata (Statement_Handle,Pvalue'Access);
     declare
       Value    : aliased Sqlinteger ;
       Add : System.Address := Gnu.Db.Sqlcli.To_Address(Pvalue);
       for Value'Address use Add;
     begin
       Text_Io.Put_Line ("SQLParamData1: " & Rc'Img );
       --print it and use later on
       Text_Io.Put_Line ("SQLParamData1.2: '" & Value'Img  & "'");
     end;

So now I can putData to clob - I tried 100Mb, and that is all I need.


     -- tclob is an unbounded string containg some Mb of text
     Datalen := Length(Tclob);

     while Sent < Datalen loop
       From := N;
       if Datalen - Sent >= Chunk_Size then
         To := N+ Chunk_Size -1;
       else
         To := N+ Datalen - Sent -1;
       end if;

       Buffer_Len := To - From +1;

       S_Ptr :=  new String'(Slice(Tclob, From, To));
       N := N + Chunk_Size;

       Rc := Sqlputdata(Statementhandle => Statement_Handle,
                        Data            => To_Sqlpointer(S_Ptr),
                        Strlen_Or_Ind   => Sqllen(Buffer_Len));

       Sent := Sent + S_Ptr.all'Length ;

     end loop;
     Rc := Sqlparamdata (Statement_Handle, Pvalue'Access);
     Text_Io.Put_Line ("SQLParamData2.sist: " & Rc'Img);

   end;


I found some API error on my part.
The code above does not use pvalue, but I will need it later on.

Thanks for putting me on the right track




-- 
Björn

^ permalink raw reply	[relevance 3%]

* Re: converting pointer to value
  @ 2021-03-05 14:00  4%         ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2021-03-05 14:00 UTC (permalink / raw)


On 2021-03-05 12:57, Björn Lundin wrote:
> Den 2021-03-05 kl. 12:02, skrev Björn Lundin:
> 
>>
>> SQLParamData1.2:  4790608
>>
>>
>> I'm thinking that I may be dealing with a pointer to a pointer here?
>> hmm, needs more testing. I changed the expected value from 5 to 7. 
>> Still a bit off...
>>
> 
> The way I put the value 5 or 7 into the API is
> 
> procedure Bind_Parameter(Statement    : in out Statement_Type;
>                             Column_Index : in Positive;
>                             Value        : in CLOB;
>                             Null_Value   : in Boolean := False) is
>      A : Bind_Parameter_Type;
>      L : Sqlulen := Sqlulen(Length(Value));
>      Rc : Sqlreturn := 0;
>      Local_Length : Sqllen ;
>    begin
> 
>      Local_Length := Sqllen(Sqllen(-100) -Sqllen(L)); 
> --Sqllen'(SQL_LEN_DATA_AT_EXEC_OFFSET  - L);
> 
>      A.String_Pointer := new String'(To_String(Value) & Ascii.Nul);
> 
>      if Null_Value then
>        A.Length_Pointer := new Sqllen'(Sql_Null_Data);
>      else
>        A.Length_Pointer := new Sqllen'(Local_Length);
>      end if;
> 
>       Rc := gnu.Db.Sqlcli.Sqlbindparameter
>           (Statementhandle  => Statement.Get_Handle,
>            Parameternumber  => Sql_Parameter_Number (Column_Index),
>            Inputoutputtype  => Sql_Param_Input,
>            Valuetype        => Sql_C_Char,
>            Parametertype    => Sql_Char,
>            Columnsize       => L,
>            Decimaldigits    => 0,
>            Value            => 7,         --<-- here
>            Bufferlength     => 0,
>            Strlen_Or_Indptr => A.Length_Pointer);
> 
>    exception
>      when  Gnu.Db.Sqlcli.Table_Not_Found => raise Sql.No_Such_Object;
>    end Bind_Parameter;
> 
> 
>    where Bind_parameter_Type contains
>      Length_Pointer : aliased PTR_SQLLEN := null;
>      String_Pointer : aliased PTR_STRING := null;
> 
> 
> and PTR_types defined as
> type PTR_STRING is access all String;
> Type PTR_SQLLEN is access all SQLLEN;
> 
> and SQLLEN is a signed 64-bit integer
> 
> and SQLBindParameter looks like
> 
> 
> function SQLBindParameter (StatementHandle  : in SQLHSTMT;
>                                ParameterNumber  : in SQL_Parameter_Number;
>                                InputOutputType  : in SQL_Parameter_Type;
>                                ValueType        : in SQL_C_DATA_TYPE;
>                                ParameterType    : in SQL_DATA_TYPE;
>                                ColumnSize       : in SQLULEN;
>                                DecimalDigits    : in SQLSMALLINT;
>                                Value            : in SQLINTEGER;

This looks wrong because SQLINTEGER is 32-bit. Why do not you use 
Package System.Storage_Elements.Integer_Address instead, in order to 
place an integer there? It must be SQL_DATA_AT_EXEC which is -1, not 7. 
Alternatively you could use ptrdiff_t from Interfaces.C, because ARM is 
kind of ambiguous whether Integer_Address is signed.

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

^ permalink raw reply	[relevance 4%]

* Re: converting pointer to value
  2021-03-04 17:35  0%   ` Dmitry A. Kazakov
  2021-03-04 19:38  4%     ` Shark8
@ 2021-03-05 11:02  0%     ` Björn Lundin
    2021-03-09 12:07  3%     ` [SOLVED] " Björn Lundin
  2 siblings, 1 reply; 200+ results
From: Björn Lundin @ 2021-03-05 11:02 UTC (permalink / raw)


Den 2021-03-04 kl. 18:35, skrev Dmitry A. Kazakov:
> On 2021-03-04 17:55, Shark8 wrote:
> 
>>> type SQLPOINTER is private;
>> ....
>>> private
>>> type SQLPOINTER is new System.Storage_Elements.Integer_Address;
>>
>> And here we have SQLPOINTER, which is private, but which is something 
>> of the same representation that Integer_Address has; let's assume that 
>> the ADDRESS type is implementation-defined, and a private type.
> 
> SQLPOINTER is System.Address.
> 
>> What does this mean?
>> It means that we don't know what the size of ADDRESS (and thus 
>> SQLPOINTER) actually is, but assuming you're on a 32- or 64-bit 
>> machine it's likely 2 to 4 times as large as the 16-bit SQLSMALLINT-- 
>> which is a good indication that a simple UNCHECKED_CONVERSION is the 
>> wrong answer.
> 
> You need not to know that:
> 
>     declare
>        P : SQLPOINTER := ...;
>        A : System.Address;
>        pragma Import (Ada, A);
>        for A'Address use P'Address;
>        T : My_Fancy_Object;
>        pragma Import (Ada, My_Fancy_Object);
>        for T'Address use A;
>     begin
>        ... -- Use T at P
> 


so I tried this version:

procedure Exec (Statement_Handle : in Sqlhstmt) is
     Rc      :  Sqlreturn := Sqlexecute (Statement_Handle);
     Pvalue  : aliased Sqlpointer;
     Sent    : Integer := 0;
     Datalen : Integer := 14;
     Buffer  : String  (1..10) := (others => ' ');
     S_Ptr   : Ptr_String;

     A       :  System.Address;
     pragma Import(Ada,A);
     for A'Address use Pvalue'Address;
     I       : Sqlinteger ;
     pragma Import(Ada,I);
     for I'Address use A;

   begin
     --test for unset clob
     Rc := Sqlparamdata (Statement_Handle,Pvalue'Access);
     Text_Io.Put_Line ("SQLParamData1.2: " & I'Img );


SQLParamData1.2:  4790608


I'm thinking that I may be dealing with a pointer to a pointer here?
hmm, needs more testing. I changed the expected value from 5 to 7. Still 
a bit off...



-- 
Björn

^ permalink raw reply	[relevance 0%]

* Re: converting pointer to value
  2021-03-04 21:27  0%       ` Dmitry A. Kazakov
@ 2021-03-05  8:58  0%         ` Björn Lundin
  0 siblings, 0 replies; 200+ results
From: Björn Lundin @ 2021-03-05  8:58 UTC (permalink / raw)


Den 2021-03-04 kl. 22:27, skrev Dmitry A. Kazakov:
> On 2021-03-04 20:38, Shark8 wrote:
>> On Thursday, March 4, 2021 at 10:35:01 AM UTC-7, Dmitry A. Kazakov wrote:
>>> On 2021-03-04 17:55, Shark8 wrote:
>>>
>>>>> type SQLPOINTER is private;
>>>> ....
>>>>> private
>>>>> type SQLPOINTER is new System.Storage_Elements.Integer_Address;
>>>>
>>>> And here we have SQLPOINTER, which is private, but which is 
>>>> something of the same representation that Integer_Address has; let's 
>>>> assume that the ADDRESS type is implementation-defined, and a 
>>>> private type.
>>> SQLPOINTER is System.Address.
>>
>> Which is implementation-defined.
> 
> No, it defined this way
> 
>     typedef void * SQLPOINTER;
> 
> so for all purposes it is System.Address.
> 
>> None of that addresses the issue that he asked: "how to get the Pvalue 
>> as an SQLRETURN?"
> 
> OK, then the answer is you don't.
> 
> As the rule QDBC does not overlay different types. There are special 
> pointer values though, like 1 etc. Integer_Address can be used to encode 
> them. They are constants.
> 
> P.S. I think the OP refers to SQLParamData/SQLPutData mechanism. There 

Yes - I am. But the problem at hand was more of Ada nature than handling 
tha ODBC API (eventhough yuo've started med thinking about if I'm doing 
it the right way)

> is no overloading either. It works this way:
> 
>     prepare
>     bind to special "address" value, 1, I believe
> 
>     execute
>     if SQLParamData = need_data then
>        loop
>           SQLPutData (next chunk)
>        end loop;
>     end if;
> 
> I do not think it is worth using, unless the data are so big that they 
> are not in the memory, or read from a stream chunk by chunk etc. Clearly 
> it is a very expensive method. A normal bind would be a better choice 
> for most applications.

Yes. The use case at hand is with data fitting into RAM.
But that might change - hence the PutData way.

But I will reconsider, and contemplate if I really need that.

-- 
Björn

^ permalink raw reply	[relevance 0%]

* Re: converting pointer to value
  2021-03-04 19:38  4%     ` Shark8
@ 2021-03-04 21:27  0%       ` Dmitry A. Kazakov
  2021-03-05  8:58  0%         ` Björn Lundin
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2021-03-04 21:27 UTC (permalink / raw)


On 2021-03-04 20:38, Shark8 wrote:
> On Thursday, March 4, 2021 at 10:35:01 AM UTC-7, Dmitry A. Kazakov wrote:
>> On 2021-03-04 17:55, Shark8 wrote:
>>
>>>> type SQLPOINTER is private;
>>> ....
>>>> private
>>>> type SQLPOINTER is new System.Storage_Elements.Integer_Address;
>>>
>>> And here we have SQLPOINTER, which is private, but which is something of the same representation that Integer_Address has; let's assume that the ADDRESS type is implementation-defined, and a private type.
>> SQLPOINTER is System.Address.
> 
> Which is implementation-defined.

No, it defined this way

    typedef void * SQLPOINTER;

so for all purposes it is System.Address.

> None of that addresses the issue that he asked: "how to get the Pvalue as an SQLRETURN?"

OK, then the answer is you don't.

As the rule QDBC does not overlay different types. There are special 
pointer values though, like 1 etc. Integer_Address can be used to encode 
them. They are constants.

P.S. I think the OP refers to SQLParamData/SQLPutData mechanism. There 
is no overloading either. It works this way:

    prepare
    bind to special "address" value, 1, I believe

    execute
    if SQLParamData = need_data then
       loop
          SQLPutData (next chunk)
       end loop;
    end if;

I do not think it is worth using, unless the data are so big that they 
are not in the memory, or read from a stream chunk by chunk etc. Clearly 
it is a very expensive method. A normal bind would be a better choice 
for most applications.

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

^ permalink raw reply	[relevance 0%]

* Re: converting pointer to value
  2021-03-04 17:35  0%   ` Dmitry A. Kazakov
@ 2021-03-04 19:38  4%     ` Shark8
  2021-03-04 21:27  0%       ` Dmitry A. Kazakov
  2021-03-05 11:02  0%     ` Björn Lundin
  2021-03-09 12:07  3%     ` [SOLVED] " Björn Lundin
  2 siblings, 1 reply; 200+ results
From: Shark8 @ 2021-03-04 19:38 UTC (permalink / raw)


On Thursday, March 4, 2021 at 10:35:01 AM UTC-7, Dmitry A. Kazakov wrote:
> On 2021-03-04 17:55, Shark8 wrote: 
> 
> >> type SQLPOINTER is private; 
> > .... 
> >> private 
> >> type SQLPOINTER is new System.Storage_Elements.Integer_Address; 
> > 
> > And here we have SQLPOINTER, which is private, but which is something of the same representation that Integer_Address has; let's assume that the ADDRESS type is implementation-defined, and a private type.
> SQLPOINTER is System.Address.

Which is implementation-defined.
Even though most programmers would assert that address and integer are the same thing, this isn't a given; segmented architectures would more naturally map to records.

> > What does this mean? 
> > It means that we don't know what the size of ADDRESS (and thus SQLPOINTER) actually is, but assuming you're on a 32- or 64-bit machine it's likely 2 to 4 times as large as the 16-bit SQLSMALLINT-- which is a good indication that a simple UNCHECKED_CONVERSION is the wrong answer.
> You need not to know that: 
> 
> declare 
> P : SQLPOINTER := ...; 
> A : System.Address; 
> pragma Import (Ada, A); 
> for A'Address use P'Address; 
> T : My_Fancy_Object; 
> pragma Import (Ada, My_Fancy_Object); 
> for T'Address use A; 
> begin 
> ... -- Use T at P

None of that addresses the issue that he asked: "how to get the Pvalue as an SQLRETURN?"
One of these is 16-bits, the other is derived from System.Storage_Elements.Integer_Address.
Sure, you can overlay, and that could be valid in some cases, but I simply don't have enough information here to say if that would be a valid solution and it's much more likely that it would be completely unintended.

^ permalink raw reply	[relevance 4%]

* Re: converting pointer to value
  2021-03-04 16:55  0% ` Shark8
@ 2021-03-04 17:35  0%   ` Dmitry A. Kazakov
  2021-03-04 19:38  4%     ` Shark8
                       ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: Dmitry A. Kazakov @ 2021-03-04 17:35 UTC (permalink / raw)


On 2021-03-04 17:55, Shark8 wrote:

>> type SQLPOINTER is private;
> ....
>> private
>> type SQLPOINTER is new System.Storage_Elements.Integer_Address;
> 
> And here we have SQLPOINTER, which is private, but which is something of the same representation that Integer_Address has; let's assume that the ADDRESS type is implementation-defined, and a private type.

SQLPOINTER is System.Address.

> What does this mean?
> It means that we don't know what the size of ADDRESS (and thus SQLPOINTER) actually is, but assuming you're on a 32- or 64-bit machine it's likely 2 to 4 times as large as the 16-bit SQLSMALLINT-- which is a good indication that a simple UNCHECKED_CONVERSION is the wrong answer.

You need not to know that:

    declare
       P : SQLPOINTER := ...;
       A : System.Address;
       pragma Import (Ada, A);
       for A'Address use P'Address;
       T : My_Fancy_Object;
       pragma Import (Ada, My_Fancy_Object);
       for T'Address use A;
    begin
       ... -- Use T at P

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

^ permalink raw reply	[relevance 0%]

* Re: converting pointer to value
  2021-03-04 15:59  3% converting pointer to value Björn Lundin
@ 2021-03-04 16:55  0% ` Shark8
  2021-03-04 17:35  0%   ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Shark8 @ 2021-03-04 16:55 UTC (permalink / raw)


On Thursday, March 4, 2021 at 8:59:48 AM UTC-7, björn lundin wrote:

> this code looks like 
> 
> type SQLSMALLINT is range -(2 ** 15) .. +(2 ** 15) - 1; 
> for SQLSMALLINT'Size use 16; 
> 
> type SQLRETURN is new SQLSMALLINT; 
> 
> 
> how to get the Pvalue as an SQLRETURN? 

Ok, in Ada the creation of a new type, even if only deriving it via NEW, makes a type which is incompatible with the old type.
Thus you can say TYPE TEMPERATURE IS NEW INTEGER; and TYPE SPEED IS NEW INTEGER; and values of these types are NOT interchangeable even though both have the same internal representation and properties that INTEGER does. The way that you can use these different types together is by casting; given X : SPEED := 3; you can say Y :  TEMPERATURE := SPEED(X); -- which works because they have the same internal representation if they did not have the same representation you would have to use UNCHECKED_CONVERSION.

An example where you might need differing representations is modeling the x86 -- you could have something like:
Type Integer_Register is new Integer; -- IIRC, AX is 16-bits, divided into bytes AH and AL.
Type HL_Byte_Register is record
  High, Low : Interfaces.Unsigned_8;
end record;

AX : Integer_Register:= 16#EF10#;
...
Declare
  Function Convert is new Ada.Unchecked_Conversion(Integer_Register, HL_Byte_Register);
  Function Convert is new Ada.Unchecked_Conversion(HL_Byte_Register, Integer_Register);
  Temp : HL_Byte_Register := convert( AX );
Begin
  -- Stuff w/ bytes.
  AX:= Convert( Temp );
End;

In the code you present, SQLRETURN derives from SQLSMALLINT, so you can say SQLSMALLINT( Return_Value )... yes, I know this isn't pvalue as sqlreturn, we'll get there.

> 
> function SQLParamData (StatementHandle : SQLHSTMT; 
> pValue : access SQLPOINTER) 
> return SQLRETURN; 
> 

So this returns a number, of the same representation that the 16-bit SQLSMALLINT has.

> so I get back the column in pValue. 
> pValue is declared as 
> Pvalue : aliased Sqlpointer; 
...
> type SQLPOINTER is private;
....
> private
> type SQLPOINTER is new System.Storage_Elements.Integer_Address;

And here we have SQLPOINTER, which is private, but which is something of the same representation that Integer_Address has; let's assume that the ADDRESS type is implementation-defined, and a private type.
What does this mean?
It means that we don't know what the size of ADDRESS (and thus SQLPOINTER) actually is, but assuming you're on a 32- or 64-bit machine it's likely 2 to 4 times as large as the 16-bit SQLSMALLINT-- which is a good indication that a simple UNCHECKED_CONVERSION is the wrong answer.

Try looking at the operations which have SQLPOINTER as a parameter/result.

^ permalink raw reply	[relevance 0%]

* converting pointer to value
@ 2021-03-04 15:59  3% Björn Lundin
  2021-03-04 16:55  0% ` Shark8
  0 siblings, 1 reply; 200+ results
From: Björn Lundin @ 2021-03-04 15:59 UTC (permalink / raw)


Hi!
I am trying to implement clob handling towards a database
using the ODBC binding at <http://gnade.sourceforge.net/>

The ODBC API itself is somewhat awkward for this, but I have some Ada 
issues as well.

In one call I do the binding of data to a bind variable.

   insert into table A vales (?,?)

where the '?' are my bind variables in the sql.

Now, when data is small I call bindcol via

   Gnu.Db.Sqlcli.Sqlbindparameter

and put the wanted value into the binding.

But with CLOBs, there are too much data, so instead of setting
the actual data, one is to indicate which column to put the
data into - at a later time.

So then I call exec, it indicates by resultcode
that no all values are present.

I then get to call

     Rc := Sqlparamdata (Statement_Handle,Pvalue'Access);

with spec like this to find out what column misses value.
This is the column mentioned above

    function SQLParamData (StatementHandle : SQLHSTMT;
                           pValue          : access SQLPOINTER)
                          return SQLRETURN;

so I get back the column in pValue.
pValue is declared as
     Pvalue : aliased Sqlpointer;

I did put in a SQLINTEGER into the previous call, and want that back.

I also have the definitions
    type SQLPOINTER is private;

    type SQLINTEGER   is range -(2 ** 31) .. +(2 ** 31) - 1;
    for SQLINTEGER'Size use 32;
....
private
    type SQLPOINTER is new System.Storage_Elements.Integer_Address;

and there is a utility functions

    function To_Address (P : SQLPOINTER) return System.Address;


And here's my problem

from the call
     Rc := Sqlparamdata (Statement_Handle,Pvalue'Access);
how do get Pvalue as an integer value?

Running it in debug in GPS I hoover over the variable
and I see the correct value
(the one I feed into it earlier) but how
do I get a hold of it?

this code looks like

    type SQLSMALLINT  is range -(2 ** 15) .. +(2 ** 15) - 1;
    for SQLSMALLINT'Size use 16;

    type SQLRETURN is new SQLSMALLINT;


   procedure Exec (Statement_Handle : in Sqlhstmt) is
     RC :  SQLRETURN := SQLExecute (Statement_Handle);
     Pvalue : aliased Sqlpointer;
     Rc2 :  SQLRETURN := 0;
    begin
     Text_Io.Put_Line ("Exec: " & Rc'Img);

     Rc2 := Sqlparamdata (Statement_Handle,Pvalue'Access);
     Text_Io.Put_Line ("SQLParamData1: " & Rc2'Img );

     how to get the Pvalue as an SQLRETURN?


-- 
Björn

^ permalink raw reply	[relevance 3%]

* Re: Record initialisation question
  2021-01-14 14:27  3%                 ` Niklas Holsti
@ 2021-01-15  7:49  4%                   ` DrPi
  0 siblings, 0 replies; 200+ results
From: DrPi @ 2021-01-15  7:49 UTC (permalink / raw)


> 
> You could try Unchecked_Conversion or System.Storage_Units.To_Integer.
> 
They are not compatible with no elaboration code.
Generally, using a function call is not compatible with no elaboration code.

> But my suggestion did not involve such conversions: I assumed that you 
> would be able to compute, using static universal-integer expressions, 
> the addresses for all your flash objects, and use those directly in the 
> record aggregates. This assumes that you are able to define the lay-out 
> of all the stuff in the flash. You might then also specify the 'Address 
> of each flash object, using those same universal-integer expressions.
> 
> Something like this (not tested with a compiler):
> 
>     Flash_Start : constant := 16#500#;
> 
>     Obj_A_Addr : constant := Flash_Start;
> 
>     Obj_B_Addr : constant := Obj_A_Addr + 16#234#;
>     -- Here 16#234# is supposed to be the size of Obj_A, so that
>     -- Obj_B follows Obj_A in flash.
> 
>     Obj_A : constant Dcd_T := (
>        Next => Obj_B_Addr,
>        ...);
> 
>     for Obj_A'Address
>        use System.Storage_Elements.To_Address (Obj_A_Addr);
> 
System.Storage_Elements is not compatible with no elaboration code.

^ permalink raw reply	[relevance 4%]

* Re: Record initialisation question
  @ 2021-01-14 14:27  3%                 ` Niklas Holsti
  2021-01-15  7:49  4%                   ` DrPi
  0 siblings, 1 reply; 200+ results
From: Niklas Holsti @ 2021-01-14 14:27 UTC (permalink / raw)


On 2021-01-14 15:07, DrPi wrote:
> 
>> The problem is that "static" in Ada means "known at compile time", 
>> while addresses, although static in execution, are generally not known 
>> until link time. A case where assembly language is more powerful :-(
>>
> Or C :(
> I use the manufacturer C code generated by their tool as reference. In 
> C, initializing a structure element with an address is not a problem.


The C compiler emits a relocatable reference to the addressed object, 
and the linker replaces it with the absolute address. An Ada compiler 
should be able to do the same thing when the address of a statically 
allocated object is used to initialize another statically allocated 
object, assuming that the initialization expression is simple enough to 
require no run-time computation. Perhaps part of the reason why that 
does not happen is that System.Address is a private type, and might not 
be an integer type.

Do you (or someone) know if the C language standard guarantees that such 
initializations will be done by the linker, and not by the C start-up 
code that is analogous to Ada elaboration code?

Can you ask your Ada compiler vendor for suggestions? Assuming you have 
support from them.


>>> I have to find a workaround.
>>
>> If addresses are the only problem, and you are in control of the flash 
>> memory lay-out, you might be able to define static Ada constant 
>> expressions that compute ("predict") the addresses of every boot data 
>> structure record. But those expressions would need to use the sizes of 
>> the records, I think, and unfortunately the 'Size of a record type is 
>> not a static expression (IIRC), and that may hold also for the 
>> GNAT-specific 'Max_Size_In_Storage_Units.
> 
> I can redefine the records with UInt32 instead of System.Address. The 
> problem is : What is the expression to convert from Address to UInt32 
> without using a function ?


You could try Unchecked_Conversion or System.Storage_Units.To_Integer.

But my suggestion did not involve such conversions: I assumed that you 
would be able to compute, using static universal-integer expressions, 
the addresses for all your flash objects, and use those directly in the 
record aggregates. This assumes that you are able to define the lay-out 
of all the stuff in the flash. You might then also specify the 'Address 
of each flash object, using those same universal-integer expressions.

Something like this (not tested with a compiler):

    Flash_Start : constant := 16#500#;

    Obj_A_Addr : constant := Flash_Start;

    Obj_B_Addr : constant := Obj_A_Addr + 16#234#;
    -- Here 16#234# is supposed to be the size of Obj_A, so that
    -- Obj_B follows Obj_A in flash.

    Obj_A : constant Dcd_T := (
       Next => Obj_B_Addr,
       ...);

    for Obj_A'Address
       use System.Storage_Elements.To_Address (Obj_A_Addr);

^ permalink raw reply	[relevance 3%]

* Re: Put the access value
  2020-04-14  7:42  4% ` J-P. Rosen
  2020-04-18 15:08  0%   ` Oliver Kellogg
@ 2020-04-20 23:02  0%   ` Robert A Duff
  1 sibling, 0 replies; 200+ results
From: Robert A Duff @ 2020-04-20 23:02 UTC (permalink / raw)


"J-P. Rosen" <rosen@adalog.fr> writes:

> In Ada, a pointer is not an integer and has no 'Image attribute.

Sure it does.  ;-)

So do records and everything else.  See AI12-0020-1 (don't pay attention
to details; they're changing).  I implemented that recently, so the
latest development version of GNAT has it.

This program:

with Ada.Strings.Text_Output.Formatting; use Ada.Strings.Text_Output;
procedure Access_Image is
   type R is record
      This : Integer;
      That : String (1..10);
   end record;

   type A is access all R;

   X : A := new R'(This => 123, That => "helloworld");
begin
   Formatting.Put ("\1, \2\n", X'Image, X.all'Image);
end Access_Image;

prints:

(access 162b740),
(this =>  123,
 that => "helloworld")

> 1) Use Unchecked_Conversion to convert it to an appropriate integer type
>
> 2) use package Address_To_Access conversion to convert your pointer to
> an address, then System.Storage_Elements.To_Integer to convert the
> address to Integer_Address, which is an integer type.

Right, these are good workarounds if you don't have the latest
version.

- Bob

^ permalink raw reply	[relevance 0%]

* Re: Put the access value
  2020-04-14  7:42  4% ` J-P. Rosen
@ 2020-04-18 15:08  0%   ` Oliver Kellogg
  2020-04-20 23:02  0%   ` Robert A Duff
  1 sibling, 0 replies; 200+ results
From: Oliver Kellogg @ 2020-04-18 15:08 UTC (permalink / raw)


On Tuesday, April 14, 2020 at 9:42:56 AM UTC+2, J-P. Rosen wrote:
> Le 14/04/2020 à 09:15, ldries46 a écrit :
> > [...]
> In Ada, a pointer is not an integer and has no 'Image attribute. A
> pointer is not an address either. Of course, for debugging you can
> indulge your self to constructs that would be thrown at for long term
> maintenance. So...
> 
> 1) Use Unchecked_Conversion to convert it to an appropriate integer type
> 
> 2) use package Address_To_Access conversion to convert your pointer to
> an address, then System.Storage_Elements.To_Integer to convert the
> address to Integer_Address, which is an integer type.

There's also the sledgehammer-to-crack-a-nut solution:

https://github.com/persan/auto-io-gen

- Oliver

^ permalink raw reply	[relevance 0%]

* Re: Put the access value
  @ 2020-04-14  7:42  4% ` J-P. Rosen
  2020-04-18 15:08  0%   ` Oliver Kellogg
  2020-04-20 23:02  0%   ` Robert A Duff
  0 siblings, 2 replies; 200+ results
From: J-P. Rosen @ 2020-04-14  7:42 UTC (permalink / raw)


Le 14/04/2020 à 09:15, ldries46 a écrit :
> I just want to see if the routing of thedifferent Buffer_Pointer's is
> correct so I thought Buffer_Pointer'Image(El) would show the value of
> The Pointer El f.i. ?x000000 for null or even the simpel decimal value 0.
> 
> This construction creates a failure during compiling.
> Should I use another attribute or some other construction?
In Ada, a pointer is not an integer and has no 'Image attribute. A
pointer is not an address either. Of course, for debugging you can
indulge your self to constructs that would be thrown at for long term
maintenance. So...

1) Use Unchecked_Conversion to convert it to an appropriate integer type

2) use package Address_To_Access conversion to convert your pointer to
an address, then System.Storage_Elements.To_Integer to convert the
address to Integer_Address, which is an integer type.

-- 
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr

^ permalink raw reply	[relevance 4%]

* Re: Calling a record type's methods (functions or procedure) when record is in an array
  2020-01-23 15:00  5%     ` joakimds
  2020-01-23 15:02  5%       ` joakimds
@ 2020-01-23 20:15  0%       ` Optikos
  1 sibling, 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  5%     ` joakimds
@ 2020-01-23 15:02  5%       ` joakimds
  2020-01-23 20:15  0%       ` Optikos
  1 sibling, 0 replies; 200+ results
From: joakimds @ 2020-01-23 15:02 UTC (permalink / raw)


Obvious copy paste error:

   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;

should be:

   function Allocate_Car return Any_Car is
   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; 

Other issues?

Best regards,
Joakim

^ permalink raw reply	[relevance 5%]

* Re: Calling a record type's methods (functions or procedure) when record is in an array
  @ 2020-01-23 15:00  5%     ` joakimds
  2020-01-23 15:02  5%       ` joakimds
  2020-01-23 20:15  0%       ` Optikos
  0 siblings, 2 replies; 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 5%]

* Proper way to license a ZFP runtime
@ 2019-08-11 14:19  3% Jere
  0 siblings, 0 replies; 200+ results
From: Jere @ 2019-08-11 14:19 UTC (permalink / raw)


I'm building up a ZFP runtime targeting the GNAT compiler and
had some questions about how to handle licensing the files.  Take a
package like System.Storage_Elements.  The Ada RM leaves quite a 
few of the items as "implementation defined" (which makes sense), 
and I have to add implementations for the functions, but since I 
am targeting the GNAT compiler, I will want to use GNAT specific
language extensions to implement them.  Does this force me to
use one of the GNAT licenses?  

Additionally, defining some of the types in the package System 
are also "implementation defined" but there really is only one 
way to define them for a board of similar type (32bit arm).  
Since they have already defined in runtimes for other similar
arm boards, am I forced to use the copywrite and license of the
runtimes for those boards?

If I don't have to use the licenses mentioned above, is there
a good license statement that conveys the files are simply
based on the Ada RM and are free to use however one wants?
I feel like I have seen one before in a repo, but couldn't 
locate it, so it might have just been in my head.

Same type of questions apply to copyright as well.

If I have to, I'll put the GNAT copyright and license on all
the files, but I would prefer to only do that on files that
I include or modify from actual existing GNAT files

^ permalink raw reply	[relevance 3%]

* Re: How to make Ada popular. Get rid of ";" at end of statement.
  2019-07-27  3:11  3%           ` Randy Brukardt
@ 2019-07-27  4:06  0%             ` Keith Thompson
  0 siblings, 0 replies; 200+ results
From: Keith Thompson @ 2019-07-27  4:06 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:
> "Keith Thompson" <kst-u@mib.org> wrote in message 
> news:lnh8785kge.fsf@kst-u.example.com...
>> Lucretia <laguest9000@googlemail.com> writes:
>>> On Thursday, 25 July 2019 08:26:29 UTC+1, Maciej Sobczak  wrote:
>>>> > The one concrete reason I've ever heard for using C or C++ instead
>>>> > of Modula-2 or Ada is that C/C++ allow you to perform pointer
>>>> > arithmetic
>>>>
>>>> Really? I would never consider that reason myself.
>>>
>>> Me neither, but then you can do pointer arithmetic in Ada, you just
>>> use normal numbers and convert to an address.
>>
>> I'm fairly sure there's no guarantee that the result of any such
>> conversion (which would have to use Unchecked_Conversion or something
>> equivalent, unless I've missed something) would be meaningful.
>
> And there is in C?? ;-)

No.  Did I imply that there is?

But C pointer arithmetic (without conversion to and from an integer
type) is well defined as long as you stay within a single (array)
object.  This isn't comp.lang.c, so I won't go into the details.

> Package System.Storage_Elements includes operations for directly doing 
> address arithmetic - you would have to do the multiplies on values of 
> Storage_Offset (which is an integer type) and then add/subtract those from 
> values of System.Address.

So it does.  The standard doesn't seem to say much about
what operations are well defined beyond suggesting that they
"should reflect the target environment semantics as closely as
is reasonable".

(C *needs* to go into a lot more detail about pointer arithmetic
because so much of the language depends on it.)

[snip]

To be clear, I'm not making any arguments for or against C or Ada.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */

^ permalink raw reply	[relevance 0%]

* Re: How to make Ada popular. Get rid of ";" at end of statement.
  @ 2019-07-27  3:11  3%           ` Randy Brukardt
  2019-07-27  4:06  0%             ` Keith Thompson
  0 siblings, 1 reply; 200+ results
From: Randy Brukardt @ 2019-07-27  3:11 UTC (permalink / raw)


"Keith Thompson" <kst-u@mib.org> wrote in message 
news:lnh8785kge.fsf@kst-u.example.com...
> Lucretia <laguest9000@googlemail.com> writes:
>> On Thursday, 25 July 2019 08:26:29 UTC+1, Maciej Sobczak  wrote:
>>> > The one concrete reason I've ever heard for using C or C++ instead
>>> > of Modula-2 or Ada is that C/C++ allow you to perform pointer
>>> > arithmetic
>>>
>>> Really? I would never consider that reason myself.
>>
>> Me neither, but then you can do pointer arithmetic in Ada, you just
>> use normal numbers and convert to an address.
>
> I'm fairly sure there's no guarantee that the result of any such
> conversion (which would have to use Unchecked_Conversion or something
> equivalent, unless I've missed something) would be meaningful.

And there is in C?? ;-)

Package System.Storage_Elements includes operations for directly doing 
address arithmetic - you would have to do the multiplies on values of 
Storage_Offset (which is an integer type) and then add/subtract those from 
values of System.Address.

One could use Address_to_Access_Conversions to turn an address into an 
access value (which can then be dereferenced), as well as the reverse. 
That's better than Unchecked_Conversion as any representation differences 
can be handled properly, but admittedly there isn't much difference in the 
safety of the result.

In any case, pointer arithmetic can be done in Ada more-or-less directly. 
One wonders why it would be necessary (compiler optimizers can turn a lot of 
loops on arrays into pointer arithmetic code anyway, so there's likely to be 
little or no performance difference) - it sounds a lot like a combination of 
premature optimization and a convinient (and wrong) excuse not to consider 
Ada. (A lot of people out there are mainly looking for reasons not to use 
Ada or Rust or whatever language so that they can use whatever they have 
already decided on.)

                        Randy.


^ permalink raw reply	[relevance 3%]

* Alignment issue
@ 2019-02-16 19:40  6% Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2019-02-16 19:40 UTC (permalink / raw)


I have code like this (written while working on a StackOverflow
question), and GNAT ignores apparent alignment requests.

   with System.Storage_Pools;
   with System.Storage_Elements;
   package Alignment_Issue is

      type Data_Store is new System.Storage_Elements.Storage_Array
      with Alignment => 16;  --  Standard'Maximum_Alignment;

      type User_Pool (Size : System.Storage_Elements.Storage_Count)
         is  record
            Flag          : Boolean;
            Data          : Data_Store (1 .. Size);
         end record
      with Alignment => 16;  --  Standard'Maximum_Alignment;

   end Alignment_Issue;

(Standard'Maximum_Alignment is a GNAT special) and compiling with GNAT
CE 2018 (and other GNAT compilers) I see

   $ /opt/gnat-ce-2018/bin/gnatmake -c -u -f -gnatR alignment_issue.ads 
   gcc -c -gnatR alignment_issue.ads

   Representation information for unit Alignment_Issue (spec)
   ----------------------------------------------------------

   for Data_Store'Alignment use 16;
   for Data_Store'Component_Size use 8;

   for User_Pool'Object_Size use ??;
   for User_Pool'Value_Size use ??;
   for User_Pool'Alignment use 16;
   for User_Pool use record
      Size at 0 range  0 .. 63;
      Flag at 8 range  0 ..  7;
      Data at 9 range  0 .. ??;
   end record;

which means that GNAT has ignored the alignment specified for Data_Store
when setting up User_Pool.Data.

Is this expected? OK?

I found a workround of sorts:

   type Data_Store (Size : System.Storage_Elements.Storage_Count) is record
      Data : System.Storage_Elements.Storage_Array (1 .. Size);
   end record
   with Alignment => 16;  --  Standard'Maximum_Alignment;

   type User_Pool (Size : System.Storage_Elements.Storage_Count)
      is record
         Flag  : Boolean;
         Stack : Data_Store (Size);
      end record;

giving

   Representation information for unit Alignment_Issue (spec)
   ----------------------------------------------------------

   for Data_Store'Object_Size use ??;
   for Data_Store'Value_Size use ??;
   for Data_Store'Alignment use 16;
   for Data_Store use record
      Size at 0 range  0 .. 63;
      Data at 8 range  0 .. ??;
   end record;

   for User_Pool'Object_Size use ??;
   for User_Pool'Value_Size use ??;
   for User_Pool'Alignment use 16;
   for User_Pool use record
      Size  at  0 range  0 .. 63;
      Flag  at  8 range  0 ..  7;
      Stack at 16 range  0 .. ??;
   end record;

(but even then I see that Stack.Data is offset by 8 bytes because of the
discriminant)

^ permalink raw reply	[relevance 6%]

* Re: Examining individual bytes of an integer
  @ 2018-10-15  7:49  4%   ` 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 4%]

* Re: Ada: A beginners experience
  @ 2018-07-20 12:00  4%         ` Jere
  0 siblings, 0 replies; 200+ results
From: Jere @ 2018-07-20 12:00 UTC (permalink / raw)


On Monday, July 16, 2018 at 5:38:58 PM UTC-4, Maciej Sobczak wrote:
> > Back a few years ago, I started similarly to where you did.  I did find
> > the Inspirel book to be very good, but you had to understand the context
> > it was coming from.  It seemed to assume you were natively (not cross)
> > compiling your code.
> 
> Hi there, thank you for taking the time to check that tutorial. Still, I think there is some correction needed here - the examples in the tutorial were written with the assumption of native compilation (for example on RaspberryPi), simply because this makes the command-line the most compact and kind of neutral as well. All commands should give the same results in the cross-compilation environment. If you found any troubles with this, let me know. This can help improve the future tutorial revisions.

This was a few years ago, so this is from memory (take it with a
grain of salt).

The biggest troubles I had with it was I was coming from cross-compile
instead of native.  In bare metal, it is somewhat rare to compile from
native since you won't have an OS or shell.  Just following along blindly
came up with various errors like that it needed system.ads.  A new 
beginner is not going to immediately link this to not having and RTS. 

My first workaround was to find a system.ads and add it.  This placated
the compiler so I moved on.  Next I think I needed system.storage_elements,
so I added the spec for that to my source.  I was moving along fairly 
well until I needed something from the package body for
system.storage_elements.  When I tried to add s-stoele.adb then the compiler
said it could compile system files (or a similar error).  This was where
I had to stop with your book as I hit a road block.  I needed an actual
RTS and there was really no help there.  I spent a couple of weeks 
trying to find a simple ZFP package that I could modify that didn't come
from Adacore (I didn't want the base GPL license from GNAT GPL).  Once
I got one working, I went back to your book.

Like I said, it was good.  I just wanted the OP to understand that 
while it mentions cross-compile, just blinding following the steps
and replacing the commands with the cross compile ones doesn't work.
This isn't a deficiency of the book, it is written from a native
context, but as a beginner it can be really confusing if one doesn't
understand the implications of that.

The only other thing I found different was the section on shared
state.  I didn't have a full runtime as alluded to (I had a ZFP,
which was much more bare).  However, I was able to correctly
create:

package body Program is

   X : Integer := 123; -- This actually worked correctly for me

   procedure Run is
   -- ...

end Program;

I'm guessing it had something to do with how my linker script was
setup, but it surprised me as it contrasted what was stated in
the book.  I don't think this is an error or anything, but 
bringing this up to you just incase.

> 
> > I ran into trouble because I wanted to work on
> > a controller bare-metal (it was too small for a full Ada runtime).
> 
> The tutorial was exactly focusing on zero-foot-print, bare-metal development. There are other sources that cover the (more or less) full runtime approach, with ready runtimes and driver libraries, so the tutorial tried to fill the niche for smaller chips or those projects that chose zero-foot-print for other reasons (traceability, IP politics, etc.).

I would say the major thing here is if it really is meant to be for
bare-metal ZFP style development, it was missing some more detailed
discussion on how to get and setup a quick ZFP runtime.  For beginners
this will be a huge deal.  Developing on a Raspberry Pi really isn't
bare-metal since you are compiling native with in an OS.  Yes, you can
emulate bare-metal programming on it, but it isn't exactly the same.
Note, I am not saying have an exhaustive section on how the ZFP runtime
works or anything, but just some resource on how to setup your environment
for one of the book's targeted boards.

I really think your book is great, so please don't take any comments
as antagonistic.  I recommend it to anyone I see getting started in
micro-controller development.

^ permalink raw reply	[relevance 4%]

* Re: Memory pools
    2018-05-31 19:28  5% ` gorgelo
@ 2018-05-31 19:33  4% ` gorgelo
  1 sibling, 0 replies; 200+ results
From: gorgelo @ 2018-05-31 19:33 UTC (permalink / raw)


And to follow up on the naive benchmarks:
https://github.com/frol/completely-unscientific-benchmarks

Using the memory pool in the previous post it can be used to implement the Treap algorithm (after some minor modifications):

pragma Suppress (Tampering_Check);
-- Tampering checks are only for multi-task applications.
-- Since this application is single task we can safely
-- suppress tampering checks of the standard containers.
-- If performance is an issue, the Ada-Traits Containers may be used instead.

with System.Storage_Elements;
with System.Storage_Pools;
with Ada.Text_IO;
with Ada.Integer_Text_IO;
with Ada.Containers.Vectors;
with Ada.Unchecked_Deallocation;
with Ada.Numerics.Discrete_Random;

procedure Main is

   subtype Storage_Offset is System.Storage_Elements.Storage_Offset;
   subtype Storage_Count  is System.Storage_Elements.Storage_Count;
   subtype Storage_Array  is System.Storage_Elements.Storage_Array;

   subtype Root_Storage_Pool is System.Storage_Pools.Root_Storage_Pool;

   subtype Integer_Address is System.Storage_Elements.Integer_Address;

   subtype Count_Type is Ada.Containers.Count_Type;

   use type Count_Type;
   use type Storage_Offset;
   use type Integer_Address;

   procedure Put (Text : String) renames Ada.Text_IO.Put;

   procedure Put_Line (Text : String) renames Ada.Text_IO.Put_Line;

   procedure Put_Line (I : Integer) is
   begin
      Ada.Integer_Text_IO.Put (I, 0);
      Ada.Text_IO.New_Line;
   end Put_Line;

   procedure Put (I : Integer) is
   begin
      Ada.Integer_Text_IO.Put (I, 0);
   end Put;

   procedure Put (I : Storage_Offset) is
   begin
      Ada.Integer_Text_IO.Put (Integer (I), 0);
   end Put;

   function To_Integer (Value : System.Address) return Integer_Address
                        renames System.Storage_Elements.To_Integer;

   generic
      Slot_Size : Positive;
      -- Specifies the size of each slot in Storage Elements (bytes)
      -- Must be big enough to store any object one wishes to allocate
      -- inside the memory pool.

      MAX : Positive;
      -- Specifies the number of slots that will be allocated in an array
      -- from the heap every time more memory needs to be pre-allocated.

   package Arena_Pools is

      type Arena (<>) is new Root_Storage_Pool with private;

      function Make return Arena;

      overriding
      procedure Allocate
        (  Pool      : in out Arena;
           Address   : out System.Address;
           Size      : Storage_Count;
           Alignment : Storage_Count
          );

      overriding
      procedure Deallocate
        (  Pool      : in out Arena;
           Address   : System.Address;
           Size      : Storage_Count;
           Alignment : Storage_Count
          );

      overriding
      function Storage_Size (Pool : Arena) return Storage_Count;
      -- Approximation of how many Storage Elements (bytes)
      -- have been heap-allocated.

   private

      type Slot is record
         Elements : Storage_Array (1..Storage_Offset (Slot_Size));
      end record;

      subtype Slot_Index is Storage_Offset range 1.. Storage_Offset (MAX);

      type Slots_Array is array (Slot_Index) of Slot;

      subtype Free_Index is Integer range 1..MAX;
      -- This Integer type (32-bits) is created in order to not use the type
      -- Storage_Offset (64-bits) in the free indices vector.

      package Indices_Vector is new Ada.Containers.Vectors
        (Index_Type   => Positive,
         Element_Type => Free_Index,
         "="          => "=");

      type Slots_Envelope is record
         Items        : Slots_Array;
         Free_Indices : Indices_Vector.Vector;
      end record;

      type Slots_Envelope_Ptr is access all Slots_Envelope;

      package Envelope_Vectors is new Ada.Containers.Vectors
        (Index_Type   => Positive,
         Element_Type => Slots_Envelope_Ptr,
         "="          => "=");

      type Arena is new Root_Storage_Pool with record
         Index : Positive := 1;
         -- Indicates which array of slots to first search for a free index

         Envelopes : Envelope_Vectors.Vector;
      end record;

      overriding
      procedure Finalize (This : in out Arena);
      -- Deallocates all allocated memory from the heap

   end Arena_Pools;

   package body Arena_Pools is

      function Make return Slots_Envelope_Ptr is
         Envelope : Slots_Envelope_Ptr := new Slots_Envelope;
      begin
         Envelope.Free_Indices.Reserve_Capacity (Ada.Containers.Count_Type (MAX));
         for I in Slot_Index'Range loop
            Envelope.Free_Indices.Append (Free_Index (I));
         end loop;

         return Envelope;
      end Make;

      function Make return Arena is
         Envelope : Slots_Envelope_Ptr := Make;
      begin
         return This : Arena do
            This.Envelopes.Append (Envelope);
         end return;
      end Make;

      function Determine_Index (Pool    : Arena;
                                Address : System.Address) return Positive is
         Searched_For : Natural := 0;
         First_Address : System.Address;
         Last_Address  : System.Address;
      begin
         for I in Pool.Envelopes.First_Index..Pool.Envelopes.Last_Index loop
            First_Address := Pool.Envelopes (I).Items (1)'Address;
            Last_Address  := Pool.Envelopes (I).Items (Storage_Offset (MAX))'Address;
            if
              To_Integer (First_Address) <= To_Integer (Address) and
              To_Integer (Address)       <= To_Integer (Last_Address)
            then
               Searched_For := I;
               exit;
            end if;
         end loop;

         if Searched_For = 0 then
            raise Storage_Error;
         end if;

         return Searched_For;
      end Determine_Index;

      procedure Allocate
        (Pool      : in out Arena;
         Address   : out System.Address;
         Size      : Storage_Count;
         Alignment : Storage_Count)
      is
         Id : Slot_Index;
      begin
         if Pool.Envelopes (Pool.Index).Free_Indices.Length > 0 then
            Id := Slot_Index (Pool.Envelopes (Pool.Index).Free_Indices.Last_Element);
            Pool.Envelopes (Pool.Index).Free_Indices.Delete_Last;
         else
            declare
               Has_Found : Boolean := False;
            begin
               for I in Pool.Envelopes.First_Index .. Pool.Envelopes.Last_Index loop
                  if Pool.Envelopes (I).Free_Indices.Length > 0 then
                     Pool.Index := I;
                     Id := Slot_Index (Pool.Envelopes (Pool.Index).Free_Indices.Last_Element);
                     Pool.Envelopes (Pool.Index).Free_Indices.Delete_Last;
                     Has_Found := True;
                     exit;
                  end if;
               end loop;

               if not Has_Found then
                  declare
                     E : Slots_Envelope_Ptr := Make;
                  begin
                     Pool.Envelopes.Append (E);
                     Pool.Index := Pool.Envelopes.Last_Index;
                     Id := Slot_Index (Pool.Envelopes (Pool.Index).Free_Indices.Last_Element);
                     Pool.Envelopes (Pool.Index).Free_Indices.Delete_Last;
                  end;
               end if;
            end;
         end if;

         Address := Pool.Envelopes (Pool.Index).Items (Id).Elements'Address;
      end Allocate;

      procedure Deallocate (Pool      : in out Arena;
                            Address   : System.Address;
                            Size      : Storage_Count;
                            Alignment : Storage_Count)
      is
         I : constant Positive := Determine_Index (Pool, Address);

         First_Address : System.Address;
         Last_Address  : System.Address;

         Slot_Id : Slot_Index;

         D : Integer_Address;
      begin
         First_Address := Pool.Envelopes (I).Items (1)'Address;
         Last_Address  := Pool.Envelopes (I).Items (Storage_Offset (MAX))'Address;

         D := (To_Integer (Last_Address) - To_Integer (First_Address) + Integer_Address (Slot_Size)) / Integer_Address (MAX);

         Slot_Id := Slot_Index ((To_Integer (Address) + Integer_Address (Slot_Size) - To_Integer (First_Address))/ D);

         Pool.Envelopes (I).Free_Indices.Append (Free_Index (Slot_Id));
      end Deallocate;

      function Storage_Size (Pool : Arena) return Storage_Count is
         Result : Storage_Count := 0;
      begin
         for Envelope of Pool.Envelopes loop
            Result := Storage_Count (Slot_Size*MAX) + Storage_Count (Envelope.Free_Indices.Capacity * 4);
         end loop;

         return Result;
      end Storage_Size;

      procedure Free is new Ada.Unchecked_Deallocation (Object => Slots_Envelope,
                                                        Name   => Slots_Envelope_Ptr);

      procedure Finalize (This : in out Arena) is
      begin
         for Envelope of This.Envelopes loop
            Free (Envelope);
         end loop;
         This.Envelopes.Clear;
      end Finalize;

   end Arena_Pools;

   package Pools is new Arena_Pools (24, 200_000);

   Pool : Pools.Arena := Pools.Make;

   -- Here ends the definition of the Storage pool and here begins
   -- implementation of the algorithm.

   package Integer_Random is new Ada.Numerics.Discrete_Random (Integer);

   G : Integer_Random.Generator;

   type Node;
   type Node_Ptr is access all Node with
     Storage_Pool => Pool;

   type Node is record
      Left  : Node_Ptr;
      Right : Node_Ptr;
      X     : Integer := 0;
      Y     : Integer := Integer_Random.Random (G);
   end record with
     Size => 24*8;

   package Tree_Def is

      type Tree is tagged private;

      function Has_Value (T : in out Tree;
                          X : in     Integer) return Boolean;

      procedure Insert (T : in out Tree;
                        X : in     Integer);

      procedure Erase (T : in out Tree;
                       X : in     Integer);

   private

      function Merge (Lower   : Node_Ptr;
                      Greater : Node_Ptr) return Node_Ptr;

      function Merge (Lower   : Node_Ptr;
                      Equal   : Node_Ptr;
                      Greater : Node_Ptr) return Node_Ptr;

      procedure Split (Orig             : in     Node_Ptr;
                       Lower            : in out Node_Ptr;
                       Greater_Or_Equal : in out Node_Ptr;
                       Value            : in     Integer);

      procedure Split (Orig    : in     Node_Ptr;
                       Lower   : in out Node_Ptr;
                       Equal   : in out Node_Ptr;
                       Greater : in out Node_Ptr;
                       Value   : in     Integer);

      procedure Make_Node (Node :    out Node_Ptr;
                           X    : in     Integer);

      type Tree is tagged record
         Root: Node_Ptr := null;
      end record;

   end Tree_Def;

   package body Tree_Def is

      procedure Free is new Ada.Unchecked_Deallocation(Object => Node,
                                                       Name   => Node_Ptr);

      procedure Make_Node (Node :    out Node_Ptr;
                           X    : in     Integer) is
      begin
         Node := new Main.Node;
         Node.X := X;
         Node.Y := Integer_Random.Random (G);
      end Make_Node;

      procedure Delete_Node (Node : in out Node_Ptr) is
      begin
         if Node /= null then
            if Node.Left /= null then
               Delete_Node(Node.Left);
            end if;

            if Node.Right /= null then
               Delete_Node (Node.Right);
            end if;

            Free (Node);
         end if;
      end Delete_Node;

      function Merge (Lower   : Node_Ptr;
                      Greater : Node_Ptr) return Node_Ptr is
      begin
         if Lower = null then
            return Greater;
         end if;

         if Greater = null then
            return lower;
         end if;

         if Lower.Y < Greater.Y then
            Lower.Right := Merge (Lower.Right, Greater);
            return Lower;
         else
            Greater.Left := Merge (Lower, Greater.Left);
            return Greater;
         end if;
      end Merge;

      function Merge (Lower   : Node_Ptr;
                      Equal   : Node_Ptr;
                      Greater : Node_Ptr) return Node_Ptr is
      begin
         return Merge (Merge (Lower, Equal), Greater);
      end merge;

      procedure Split (Orig             : in     Node_Ptr;
                       Lower            : in out Node_Ptr;
                       Greater_Or_Equal : in out Node_Ptr;
                       Value            : in     Integer) is
      begin
         if Orig = null then
            Lower := null;
            Greater_Or_Equal := null;
            return;
         end if;
         if Orig.X < Value then
            Lower := Orig;
            Split (Lower.Right, Lower.Right, Greater_Or_Equal, Value);
         else
            Greater_Or_Equal := Orig;
            Split (Greater_Or_Equal.Left, Lower, Greater_Or_Equal.Left, Value);
         end if;
      end Split;

      procedure Split (Orig    : in     Node_Ptr;
                       Lower   : in out Node_Ptr;
                       Equal   : in out Node_Ptr;
                       Greater : in out Node_Ptr;
                       Value   : in     Integer)
      is
         Equal_Or_Greater: Node_Ptr;
      begin
         Split (Orig, Lower, Equal_Or_Greater, Value);
         Split (Equal_Or_Greater, Equal, Greater, Value + 1);
      end Split;

      function Has_Value (T : in out Tree;
                          X : in     Integer) return Boolean
      is
         Lower   : Node_Ptr;
         Equal   : Node_Ptr;
         Greater : Node_Ptr;

         Result : Boolean;
      begin
         Split (T.Root, Lower, Equal, Greater, X);
         Result := Equal /= null;
         T.Root := Merge (Lower, Equal, Greater);
         return Result;
      end Has_Value;

      procedure Insert (T : in out Tree;
                        X : in     Integer)
      is
         Lower   : Node_Ptr;
         Equal   : Node_Ptr;
         Greater : Node_Ptr;
      begin
         Split (T.Root, Lower, Equal, Greater, X);
         if Equal = null then
            Make_Node (Equal, X);
         end if;
         T.Root := Merge (Lower, Equal, Greater);
      end Insert;

      procedure Erase (T : in out Tree;
                       X : in     Integer) is
         Lower   : Node_Ptr;
         Equal   : Node_Ptr;
         Greater : Node_Ptr;
      begin
         Split (T.Root, Lower, Equal, Greater, X);
         T.Root := Merge (Lower, Greater);
         -- commenting out the following line
         -- doesn't seem to affect running time by much, if at all
         Delete_Node (Equal);
      end Erase;

   end Tree_Def;

   Tree    : Tree_Def.Tree;
   Current : Integer := 5;
   Result  : Integer := 0;
   Mode    : Integer;

begin
   Integer_Random.Reset (G);

   for I in 1..1_000_000 loop
      Mode := I mod 3;
      Current := (Current * 57 + 43) mod 10007;
      if Mode = 0 then
         Tree.Insert (Current);
      elsif Mode = 1 then
         Tree.Erase (Current);
      else
         Result := Result + (if Tree.Has_Value (Current) then 1 else 0);
      end if;
   end loop;
   Put_Line (Result);

end Main;

^ permalink raw reply	[relevance 4%]

* Re: Memory pools
  @ 2018-05-31 19:28  5% ` gorgelo
  2018-05-31 19:33  4% ` gorgelo
  1 sibling, 0 replies; 200+ results
From: gorgelo @ 2018-05-31 19:28 UTC (permalink / raw)


Here is an example of an unbounded storage pool that handles deallocations and is used for allocating 3 Integers inside it and then deallocating them:

with System.Storage_Elements;
with System.Storage_Pools;
with Ada.Text_IO;
with Ada.Integer_Text_IO;
with Ada.Containers.Vectors;
with Ada.Unchecked_Deallocation;

procedure Main is

   subtype Storage_Offset is System.Storage_Elements.Storage_Offset;
   subtype Storage_Count  is System.Storage_Elements.Storage_Count;
   subtype Storage_Array  is System.Storage_Elements.Storage_Array;

   subtype Root_Storage_Pool is System.Storage_Pools.Root_Storage_Pool;

   subtype Integer_Address is System.Storage_Elements.Integer_Address;

   use type Ada.Containers.Count_Type;
   use type Storage_Offset;
   use type Integer_Address;

   procedure Put (Text : String) renames Ada.Text_IO.Put;

   procedure Put_Line (Text : String) renames Ada.Text_IO.Put_Line;

   procedure Put_Line (I : Integer) is
   begin
      Ada.Integer_Text_IO.Put (I);
      Ada.Text_IO.New_Line;
   end Put_Line;

   procedure Put (I : Integer) is
   begin
      Ada.Integer_Text_IO.Put (I, 0);
   end Put;

   procedure Put (I : Storage_Offset) is
   begin
      Ada.Integer_Text_IO.Put (Integer (I), 0);
   end Put;

   function To_Integer (Value : System.Address) return Integer_Address
                        renames System.Storage_Elements.To_Integer;

   package Arena_Pools is

      type Arena (<>) is new Root_Storage_Pool with private;

      function Make return Arena;

      overriding
      procedure Allocate
        (  Pool      : in out Arena;
           Address   : out System.Address;
           Size      : Storage_Count;
           Alignment : Storage_Count
          );

      overriding
      procedure Deallocate
        (  Pool      : in out Arena;
           Address   : System.Address;
           Size      : Storage_Count;
           Alignment : Storage_Count
          );

      overriding
      function Storage_Size (Pool : Arena) return Storage_Count;
      -- Approximation of how many Storage Elements (bytes)
      -- have been heap-allocated.

   private

      Slot_Size : constant := 20;
      -- Specifies the size of each slot in Storage Elements (bytes)
      -- Must be big enough to store any object one wishes to allocate
      -- inside the memory pool.

      type Slot is record
         Elements : Storage_Array (1..Slot_Size);
      end record;

      MAX : constant := 200_000;
      -- Specifies the number of slots that will be allocated in an array
      -- from the heap every time more memory needs to be pre-allocated.

      subtype Slot_Index is Storage_Offset range 1..MAX;

      type Slots_Array is array (Slot_Index) of Slot;

      subtype Free_Index is Integer range 1..MAX;
      -- This Integer type (32-bits) is created in order to not use the type
      -- Storage_Offset (64-bits) in the free indices vector.

      package Indices_Vector is new Ada.Containers.Vectors
        (Index_Type   => Positive,
         Element_Type => Free_Index,
         "="          => "=");

      type Slots_Envelope is record
         Items        : Slots_Array;
         Free_Indices : Indices_Vector.Vector;
      end record;

      type Slots_Envelope_Ptr is access all Slots_Envelope;

      package Envelope_Vectors is new Ada.Containers.Vectors
        (Index_Type   => Positive,
         Element_Type => Slots_Envelope_Ptr,
         "="          => "=");

      type Arena is new Root_Storage_Pool with record
         Index : Positive := 1;
         -- Indicates which array of slots to first search for a free index

         Envelopes : Envelope_Vectors.Vector;
      end record;

      overriding
      procedure Finalize (This : in out Arena);
      -- Deallocates all allocated memory from the heap

   end Arena_Pools;

   package body Arena_Pools is

      function Make return Slots_Envelope_Ptr is
         Envelope : Slots_Envelope_Ptr := new Slots_Envelope;
      begin
         Envelope.Free_Indices.Reserve_Capacity (MAX);
         for I in Slot_Index'Range loop
            Envelope.Free_Indices.Append (Free_Index (I));
         end loop;

         return Envelope;
      end Make;

      function Make return Arena is
         Envelope : Slots_Envelope_Ptr := Make;
      begin
         return This : Arena do
            This.Envelopes.Append (Envelope);
         end return;
      end Make;

      function Determine_Index (Pool    : Arena;
                                Address : System.Address) return Positive is
         Searched_For : Natural := 0;
         First_Address : System.Address;
         Last_Address  : System.Address;
      begin
         for I in Pool.Envelopes.First_Index..Pool.Envelopes.Last_Index loop
            First_Address := Pool.Envelopes (I).Items (1)'Address;
            Last_Address  := Pool.Envelopes (I).Items (MAX)'Address;
            if
              To_Integer (First_Address) <= To_Integer (Address) and
              To_Integer (Address)       <= To_Integer (Last_Address)
            then
               Searched_For := I;
               exit;
            end if;
         end loop;

         if Searched_For = 0 then
            raise Storage_Error;
         end if;

         return Searched_For;
      end Determine_Index;

      procedure Allocate
        (Pool      : in out Arena;
         Address   : out System.Address;
         Size      : Storage_Count;
         Alignment : Storage_Count)
      is
         Id : Slot_Index;
      begin
         if Pool.Envelopes (Pool.Index).Free_Indices.Length > 0 then
            Id := Slot_Index (Pool.Envelopes (Pool.Index).Free_Indices.Last_Element);
            Pool.Envelopes (Pool.Index).Free_Indices.Delete_Last;
         else
            declare
               Has_Found : Boolean := False;
            begin
               for I in Pool.Envelopes.First_Index .. Pool.Envelopes.Last_Index loop
                  if Pool.Envelopes (I).Free_Indices.Length > 0 then
                     Pool.Index := I;
                     Id := Slot_Index (Pool.Envelopes (Pool.Index).Free_Indices.Last_Element);
                     Pool.Envelopes (Pool.Index).Free_Indices.Delete_Last;
                     Has_Found := True;
                     exit;
                  end if;
               end loop;

               if not Has_Found then
                  declare
                     E : Slots_Envelope_Ptr := Make;
                  begin
                     Pool.Envelopes.Append (E);
                     Pool.Index := Pool.Envelopes.Last_Index;
                     Id := Slot_Index (Pool.Envelopes (Pool.Index).Free_Indices.Last_Element);
                     Pool.Envelopes (Pool.Index).Free_Indices.Delete_Last;
                  end;
               end if;
            end;
         end if;

         Put ("Will allocate (array, slot) := (");
         Put (Pool.Index);
         Put (",");
         Put (Id);
         Put_Line (")");

         Address := Pool.Envelopes (Pool.Index).Items (Id).Elements'Address;
      end Allocate;

      procedure Deallocate (Pool      : in out Arena;
                            Address   : System.Address;
                            Size      : Storage_Count;
                            Alignment : Storage_Count)
      is
         I : constant Positive := Determine_Index (Pool, Address);

         First_Address : System.Address;
         Last_Address  : System.Address;

         Slot_Id : Slot_Index;

         D : Integer_Address;
      begin
         First_Address := Pool.Envelopes (I).Items (1)'Address;
         Last_Address  := Pool.Envelopes (I).Items (MAX)'Address;

         D := (To_Integer (Last_Address) - To_Integer (First_Address) + Slot_Size) / MAX;

         Slot_Id := Slot_Index ((To_Integer (Address) + Slot_Size - To_Integer (First_Address))/ D);

         Pool.Envelopes (I).Free_Indices.Append (Free_Index (Slot_Id));

         Put ("Deallocate (array, slot) := (");
         Put (I);
         Put (",");
         Put (Slot_Id);
         Put_Line (")");
      end Deallocate;

      function Storage_Size (Pool : Arena) return Storage_Count is
         Result : Storage_Count := 0;
      begin
         for Envelope of Pool.Envelopes loop
            Result := Slot_Size*MAX + Storage_Count (Envelope.Free_Indices.Capacity * 4);
         end loop;

         return Result;
      end Storage_Size;

      procedure Free is new Ada.Unchecked_Deallocation (Object => Slots_Envelope,
                                                        Name   => Slots_Envelope_Ptr);

      procedure Finalize (This : in out Arena) is
      begin
         for Envelope of This.Envelopes loop
            Free (Envelope);
         end loop;
         This.Envelopes.Clear;
         Put_Line ("Deallocated all heap-allocated memory");
      end Finalize;

   end Arena_Pools;

   Pool : Arena_Pools.Arena := Arena_Pools.Make;

   type Integer_Ptr is access Integer with
     Storage_Pool => Pool;

   procedure Free is new Ada.Unchecked_Deallocation (Object => Integer,
                                                     Name   => Integer_Ptr);

   X : Integer_Ptr := new Integer'(1);
   Y : Integer_Ptr := new Integer'(2);
   Z : Integer_Ptr := new Integer'(3);

begin
   Free (X);
   Free (Y);
   Free (Z);
   Put_Line ("Has allocated" & Pool.Storage_Size'Image & " bytes.");
end Main;

It has the following output:
Will allocate (array, slot) := (1,200000)
Will allocate (array, slot) := (1,199999)
Will allocate (array, slot) := (1,199998)
Deallocate (array, slot) := (1,200000)
Deallocate (array, slot) := (1,199999)
Deallocate (array, slot) := (1,199998)
Has allocated 4800000 bytes.
Deallocated all heap-allocated memory


The implementation is inspired from Rosetta stone Arena pools:
http://rosettacode.org/wiki/Arena_storage_pool#Ada

^ permalink raw reply	[relevance 5%]

* Re: some trivial questions?
  2017-11-02 13:34  0%       ` Dmitry A. Kazakov
@ 2017-11-06 22:58  4%         ` Robert A Duff
  0 siblings, 0 replies; 200+ results
From: Robert A Duff @ 2017-11-06 22:58 UTC (permalink / raw)


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

> On 02/11/2017 14:21, Simon Wright wrote:
>> AdaCore used to use the rename-package-as-abbreviation pattern a lot,

Used to?  That style is used in the run-time system,
but not so much in the compiler.

>>     package SSE renames System.Storage_Elements;
>>
>> which helped a little once you got used to the standard abbreviations.
>
> That is the most annoying thing. People do not like "use" yet are not
> ready to face the consequences of their ideological choice. So they do a
> thing which combines disadvantages of both approaches.

I agree.  Using an unhelpful name like SSE (as in SSE.Storage_Array)
does not add useful information, but does add noise.  Either
Storage_Array or System.Storage_Elements.Storage_Array is better.

And how do you make sure that every package uses the same abbreviations
for other packages?

- Bob

^ permalink raw reply	[relevance 4%]

* Re: some trivial questions?
  2017-11-02 13:21  3%     ` Simon Wright
@ 2017-11-02 13:34  0%       ` Dmitry A. Kazakov
  2017-11-06 22:58  4%         ` Robert A Duff
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2017-11-02 13:34 UTC (permalink / raw)


On 02/11/2017 14:21, Simon Wright wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:
> 
>> It is historically so and also there is a great unjustified sentiment
>> against "use" in Ada community.
> 
> Have you ever tried to work out how GNAT does something from its
> internals? (I don't mean the libraries, but the compiler itself).
> 
> AdaCore used to use the rename-package-as-abbreviation pattern a lot,
> 
>     package SSE renames System.Storage_Elements;
> 
> which helped a little once you got used to the standard abbreviations.

That is the most annoying thing. People do not like "use" yet are not 
ready to face the consequences of their ideological choice. So they do a 
thing which combines disadvantages of both approaches.

> I did in fact work out that you can write a post-facto GPR to help
> explore the compiler's internals: e.g.
> 
>     project Gcc_8 is
> 
>        for Source_Dirs use ("gcc-8-20170528-build/gcc/ada",
>                             "gcc-8-20170528/gcc/ada");
>        for Object_Dir use "gcc-8-20170528-build/gcc/ada";
>        for Languages use ("Ada", "C");
> 
>     end Gcc_8;

That is cool.

I usually declare a thing from the package which name AdaCore had 
scrambled and then use GPS' go-to-declaration to open the package.

P.S. GPS could have quick search in the project pane and have all Ada 
RTS packages there.

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


^ permalink raw reply	[relevance 0%]

* Re: some trivial questions?
  @ 2017-11-02 13:21  3%     ` Simon Wright
  2017-11-02 13:34  0%       ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Simon Wright @ 2017-11-02 13:21 UTC (permalink / raw)


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

> It is historically so and also there is a great unjustified sentiment
> against "use" in Ada community.

Have you ever tried to work out how GNAT does something from its
internals? (I don't mean the libraries, but the compiler itself).

AdaCore used to use the rename-package-as-abbreviation pattern a lot,

   package SSE renames System.Storage_Elements;

which helped a little once you got used to the standard abbreviations.

I did in fact work out that you can write a post-facto GPR to help
explore the compiler's internals: e.g.

   project Gcc_8 is

      for Source_Dirs use ("gcc-8-20170528-build/gcc/ada",
                           "gcc-8-20170528/gcc/ada");
      for Object_Dir use "gcc-8-20170528-build/gcc/ada";
      for Languages use ("Ada", "C");

   end Gcc_8;

(I'm not 100% sure this would work as-is with the latest structure,
because the compiler itself uses the RTS, and the RTS sources are now in
gcc/ada/lib{gnat,gnarl}).

^ permalink raw reply	[relevance 3%]

* Re: avoiding builtin memset
    2017-04-24 16:56  5% ` Shark8
@ 2017-05-24 15:08  5% ` Frédéric PRACA
  1 sibling, 0 replies; 200+ results
From: Frédéric PRACA @ 2017-05-24 15:08 UTC (permalink / raw)


Le lundi 24 avril 2017 18:06:11 UTC+2, Jere a écrit :
> GNAT GPL 2016
> Windows 10
> Cross compiled to arm cortex m0+
> Full Optimization
> 
> With a small runtime that I am modifying, I am not linking in the standard c
> libraries.  This means whenever I do an array initialize, gcc tries to link 
> in a non existent memset call.  I started working on an Ada version of 
> memset which I export out.  The problem comes when memset tries to 
> recursively call itself.  The compiler is too smart for me.
> 
> At the end of my memset I have a simple loop:
>       while Current_Address < End_Address loop
>          Convert_8.To_Pointer (Current_Address).all := Uint8_Value;
>          Current_Address := Current_Address + 1;
>       end loop;
> 
> It serves two purposes:
> 1.  It finishes up any leftover bytes on an unaligned array
> 2.  If the data set is small enough (<= 16), the function skips immediately
>     to this loop and just does a byte copy on the whole thing rather
>     than try and do all the extra logic for an aligned copy
> 
> However GNAT tries to convert that to another memset call, which doesn't
> work well, since I am in memset.
> 
> My immediate workaround is to make the loop more complex:
>       Count := Count * 2; --  To avod recursive memset call
>       while Count > 0 loop
>          Convert_8.To_Pointer (Current_Address).all := Uint8_Value;
>          Current_Address := Current_Address + 1;
>          Count := Count - 2;
>       end loop;
> 
> But I don't really like this as it adds unnecessary overhead.
> 
> I looked around for gcc switches to inhibit calls to memset, but the only
> one I found ( -fno-builtins ) only works on C files.  I really don't want to 
> write it in C (or  assembly for that matter).
> 
> I think I can also do ASM statements, but I would hate to have to do ASM if
> there is an Ada solution.  I also don't know if GCC would just optimize
> the ASM to a memset call anyways.
> 
> Do I have any other options that would let me do it in Ada?  I didn't see
> pragmas that jumped out at me.

In the past, I've been doing the same for a x86 toy OS called Lovelace OS.
The spec:

--  Lovelace Operating System - An Unix Like Ada'Based Operating system
--  Copyright (C) 2013-2014  Xavier GRAVE, Frederic BOYER

--  This program is free software: you can redistribute it and/or modify
--  it under the terms of the GNU General Public License as published by
--  the Free Software Foundation, either version 3 of the License, 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
--  along with this program.  If not, see <http://www.gnu.org/licenses/>.

pragma Suppress (All_Checks);
with System;
with System.Storage_Elements;

procedure Oasys.Memset (Destination : in System.Address;
                         Value : in System.Storage_Elements.Storage_Element;
                         Count : in System.Storage_Elements.Storage_Count);
pragma Pure (Memset);
pragma Export (C, Memset, "memset");


Then the body for the x86-32 part

--  Lovelace Operating System - An Unix Like Ada'Based Operating system
--  Copyright (C) 2013-2014  Xavier GRAVE, Frederic BOYER

--  This program is free software: you can redistribute it and/or modify
--  it under the terms of the GNU General Public License as published by
--  the Free Software Foundation, either version 3 of the License, 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
--  along with this program.  If not, see <http://www.gnu.org/licenses/>.

with System.Storage_Elements; use System.Storage_Elements;

with Oasys.Debug;

procedure Oasys.Memset (Destination : in System.Address;
                        Value : in Storage_Element;
                        Count : in Storage_Count) is
   pragma Suppress (All_Checks);

   --  Storage_unit zones
   Byte_Zone_Destination : Storage_Array (1 .. Count);
   for Byte_Zone_Destination'Address use Destination;

   Offset : Storage_Offset := 0;
   Number_Of_Bytes_To_Write : Storage_Count := Count;

   --  CPU width (ie 32 or 64 bits) in bytes
   Full_Width : constant := System.Word_Size / System.Storage_Unit;

begin

   --  see http://www.noxeos.com/2013/08/06/code-optimisations/
   --  Algo
   --  offset = 0
   --  while destination + offset is not aligned,
   --  set the byte to value and add 1 to offset
   --  decrease count of elements to set

   while ((Destination + Offset) mod Full_Width /= 0) loop
      --  Warning ! We use offset + 1 for indexing the array
      --  because offset starts at 0 and arrays to 1
      Byte_Zone_Destination (Offset + 1) := Value;
      Offset := Offset + 1;
      Number_Of_Bytes_To_Write := Number_Of_Bytes_To_Write - 1;
   end loop;

   declare

      --  Number of word zones
      Number_Of_Zones : constant Natural := Natural (Number_Of_Bytes_To_Write) / Full_Width;

      type Word is mod 2**System.Word_Size;

      --  word long zones
      type Long_Word_Zone_Array is array (1 .. Number_Of_Zones) of Word;

      Zone_Destination : Long_Word_Zone_Array;
      for Zone_Destination'Address use (Destination + Offset);

      Remaining_Bytes : constant Natural := Natural (Number_Of_Bytes_To_Write) rem Full_Width;

      Long_Value : Word := 0;

      Power : Natural := 0;

   begin
      --  Creating the long value
      while Power < System.Word_Size loop
         Oasys.Debug.Put_String ("Long value " & Word'Image (Long_Value));
         Oasys.Debug.New_Line;

         Oasys.Debug.Put_String ("Power = " & Natural'Image (Power));
         Oasys.Debug.New_Line;

         Oasys.Debug.Put_String ("Value  shifted = " & Word'Image (Word (Value) * 2**Power));
         Oasys.Debug.New_Line;
         Long_Value := Long_Value + Word (Value) * 2**Power;
         Power := Power + System.Storage_Unit;
      end loop;

         Oasys.Debug.Put_String ("Long value " & Word'Image (Long_Value));
         Oasys.Debug.New_Line;


      --  As we are aligned,
      --  find how many aligned word we have
      --  build an array from (destination + last_offset) to last aligned count
      --  This way, we use the full width of the CPU
      for Index in Zone_Destination'Range loop
         Zone_Destination (Index) := Long_Value;
         Offset := Offset + Full_Width;
      end loop;

      --  If there are still small bytes to change
      if (Remaining_Bytes /= 0) then
         --  For the same reason as above, we add one to Offset
         for Index in Offset - 1 .. Byte_Zone_Destination'Last loop
            Byte_Zone_Destination (Index) := Value;
         end loop;
      end if;
   end;

end Oasys.Memset;

For what it's worth ;)


^ permalink raw reply	[relevance 5%]

* Re: avoiding builtin memset
  2017-04-24 16:56  5% ` Shark8
  2017-04-25  1:21  0%   ` Anh Vo
@ 2017-04-27  0:22  0%   ` Jere
  1 sibling, 0 replies; 200+ results
From: Jere @ 2017-04-27  0:22 UTC (permalink / raw)


On Monday, April 24, 2017 at 12:56:51 PM UTC-4, Shark8 wrote:
> I suppose you could try this:
> 
>     Procedure Memset(
>        Address : System.Address;
>        Value   : System.Storage_Elements.Storage_Element;
>        Length  : Natural
>       ) is
> 	Use System.Storage_Elements;
> 	Memory : Storage_Array(1..Storage_Offset(Length))
> 	  with Import, Address => Address;
>     Begin
> 	For Element of Memory loop
> 	    Element := Value;
> 	end loop;
>     End Memset;

Thanks!  

I'll be honest, I wasn't expecting it to avoid memset (didn't see why 
it should), but it didn't recursively call it.  It did however, do a 
very interesting loop unroll:

***************************************************************
<snipped>

 208:	2a00      	cmp	r2, #0
 20a:	d02d      	beq.n	268 <memset+0xa8>
 20c:	7029      	strb	r1, [r5, #0]
 20e:	2a01      	cmp	r2, #1
 210:	d02a      	beq.n	268 <memset+0xa8>
 212:	7069      	strb	r1, [r5, #1]
 214:	2a02      	cmp	r2, #2
 216:	d027      	beq.n	268 <memset+0xa8>
 218:	70a9      	strb	r1, [r5, #2]
 21a:	2a03      	cmp	r2, #3
 21c:	d024      	beq.n	268 <memset+0xa8>
 21e:	70e9      	strb	r1, [r5, #3]
 220:	2a04      	cmp	r2, #4
 222:	d021      	beq.n	268 <memset+0xa8>
 224:	7129      	strb	r1, [r5, #4]
 226:	2a05      	cmp	r2, #5
 228:	d01e      	beq.n	268 <memset+0xa8>
 22a:	7169      	strb	r1, [r5, #5]
 22c:	2a06      	cmp	r2, #6
 22e:	d01b      	beq.n	268 <memset+0xa8>
 230:	71a9      	strb	r1, [r5, #6]
 232:	2a07      	cmp	r2, #7
 234:	d018      	beq.n	268 <memset+0xa8>
 236:	71e9      	strb	r1, [r5, #7]
 238:	2a08      	cmp	r2, #8
 23a:	d015      	beq.n	268 <memset+0xa8>
 23c:	7229      	strb	r1, [r5, #8]
 23e:	2a09      	cmp	r2, #9
 240:	d012      	beq.n	268 <memset+0xa8>
 242:	7269      	strb	r1, [r5, #9]
 244:	2a0a      	cmp	r2, #10
 246:	d00f      	beq.n	268 <memset+0xa8>
 248:	72a9      	strb	r1, [r5, #10]
 24a:	2a0b      	cmp	r2, #11
 24c:	d00c      	beq.n	268 <memset+0xa8>
 24e:	72e9      	strb	r1, [r5, #11]
 250:	2a0c      	cmp	r2, #12
 252:	d009      	beq.n	268 <memset+0xa8>
 254:	7329      	strb	r1, [r5, #12]
 256:	2a0d      	cmp	r2, #13
 258:	d006      	beq.n	268 <memset+0xa8>
 25a:	7369      	strb	r1, [r5, #13]
 25c:	2a0e      	cmp	r2, #14
 25e:	d003      	beq.n	268 <memset+0xa8>
 260:	73a9      	strb	r1, [r5, #14]
 262:	2a0f      	cmp	r2, #15
 264:	d000      	beq.n	268 <memset+0xa8>
 266:	73e9      	strb	r1, [r5, #15]
 268:	b002      	add	sp, #8
 26a:	bd70      	pop	{r4, r5, r6, pc}
***************************************************************

That was interesting.  That's with -03

^ permalink raw reply	[relevance 0%]

* Re: avoiding builtin memset
  2017-04-25  1:21  0%   ` Anh Vo
@ 2017-04-25  2:57  0%     ` Luke A. Guest
  0 siblings, 0 replies; 200+ results
From: Luke A. Guest @ 2017-04-25  2:57 UTC (permalink / raw)


Anh Vo <anhvofrcaus@gmail.com> wrote:
> On Monday, April 24, 2017 at 9:56:51 AM UTC-7, Shark8 wrote:
>> I suppose you could try this:
>> 
>> Procedure Memset(
>> Address : System.Address;
>> Value   : System.Storage_Elements.Storage_Element;
>> Length  : Natural
>> ) is
>> Use System.Storage_Elements;
>> Memory : Storage_Array(1..Storage_Offset(Length))
>> with Import, Address => Address;
>> Begin
>> For Element of Memory loop
>> Element := Value;
>> end loop;
>> End Memset;
> 
> It is very nice. Indeed, it is compact and readable piece of code.
> 
> Anh Vo
> 

You'll need to export that as the C memset function.


^ permalink raw reply	[relevance 0%]

* Re: avoiding builtin memset
  2017-04-24 16:56  5% ` Shark8
@ 2017-04-25  1:21  0%   ` Anh Vo
  2017-04-25  2:57  0%     ` Luke A. Guest
  2017-04-27  0:22  0%   ` Jere
  1 sibling, 1 reply; 200+ results
From: Anh Vo @ 2017-04-25  1:21 UTC (permalink / raw)


On Monday, April 24, 2017 at 9:56:51 AM UTC-7, Shark8 wrote:
> I suppose you could try this:
> 
>     Procedure Memset(
>        Address : System.Address;
>        Value   : System.Storage_Elements.Storage_Element;
>        Length  : Natural
>       ) is
> 	Use System.Storage_Elements;
> 	Memory : Storage_Array(1..Storage_Offset(Length))
> 	  with Import, Address => Address;
>     Begin
> 	For Element of Memory loop
> 	    Element := Value;
> 	end loop;
>     End Memset;

It is very nice. Indeed, it is compact and readable piece of code.

Anh Vo

^ permalink raw reply	[relevance 0%]

* Re: avoiding builtin memset
  @ 2017-04-24 16:56  5% ` Shark8
  2017-04-25  1:21  0%   ` Anh Vo
  2017-04-27  0:22  0%   ` Jere
  2017-05-24 15:08  5% ` Frédéric PRACA
  1 sibling, 2 replies; 200+ results
From: Shark8 @ 2017-04-24 16:56 UTC (permalink / raw)


I suppose you could try this:

    Procedure Memset(
       Address : System.Address;
       Value   : System.Storage_Elements.Storage_Element;
       Length  : Natural
      ) is
	Use System.Storage_Elements;
	Memory : Storage_Array(1..Storage_Offset(Length))
	  with Import, Address => Address;
    Begin
	For Element of Memory loop
	    Element := Value;
	end loop;
    End Memset;

^ permalink raw reply	[relevance 5%]

* Re: Dynamic type system for Ada
  @ 2017-01-24 18:07  4%     ` Jeffrey R. Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey R. Carter @ 2017-01-24 18:07 UTC (permalink / raw)


On 01/24/2017 02:58 PM, Victor Porton wrote:
>
> All I ask is just an Ada type which would be so flexible that could store
> any kind of a value (just like as a variable in a dynamic language).

You might want to look at type System.Storage_Elements.Storage_Array (ARM 
13.7.1). You can (unchecked) convert most values to and from a Storage_Array of 
the correct size. Package Ada.Storage_IO (ARM A.9) makes it easy to do so for 
definite, unlimited types.

-- 
Jeff Carter
"It is the German who is so uncourteous to his verbs."
A Scandal in Bohemia
122


^ permalink raw reply	[relevance 4%]

* s-stoele.ads:62:69: error: cannot convert to a pointer type
@ 2016-11-16 18:01  3% Lucretia
  0 siblings, 0 replies; 200+ results
From: Lucretia @ 2016-11-16 18:01 UTC (permalink / raw)


Hi,

I've been updating my bare_bones project and I've always wanted to add a simple secondary stack to it, so as a dummy interface I created the following in my RTS:

package System.Secondary_Stack is
   package SSE renames System.Storage_Elements;
   
   type Mark_Id is private;
   
   function SS_Mark return Mark_Id;
   
   procedure SS_Allocate
     (Addr         : System.Address;
      Storage_Size : SSE.Storage_Count);
   
   procedure SS_Release (M : Mark_Id);
private
   type Mark_Id is new SSE.Integer_Address;
   
   SS_Pool : Integer;
   
   SS_Size : constant SSE.Storage_Element with
     import        => True,
     Convention    => Asm,
     External_Name => "sec_stack_size";
end System.Secondary_Stack;

package body System.Secondary_Stack is
   function SS_Mark return Mark_Id is
   begin
      return Mark_Id'First;
   end SS_Mark;
   
   procedure SS_Allocate     
     (Addr         : System.Address;
      Storage_Size : SSE.Storage_Count) is
   begin
      null;
   end SS_Allocate;

   procedure SS_Release (M : Mark_Id) is
   begin
      null;
   end SS_Release;
end System.Secondary_Stack;

But when compiling this:

--  Cut out the use/with clauses
procedure Bare_Bones is
   Line : Screen_Height_Range := Screen_Height_Range'First;

   procedure T is
   begin
      Put ("T called", Screen_Width_Range'First, Line);
   end T;
   
   function Hello return String is
   begin
      return "hello";
   end Hello;
begin
   --     null;
   Clear;

   Put ("Hello, bare bones in Ada",
        Screen_Width_Range'First,
        Line);

   Line := Line + 1;

   if Magic = Magic_Value then
      Put ("Magic numbers match!", Screen_Width_Range'First, Line);
   else
      Put ("Magic numbers don't match!", Screen_Width_Range'First, Line);  --  comment

      raise Program_Error;
   end if;

   Line := Line + 1;

   T;
   
   Line := Line + 1;

   Put (Hello, Screen_Width_Range'First, Line);
end Bare_Bones;

I get the following error:

GNAT 4.9.2
Copyright 1992-2014, Free Software Foundation, Inc.
/home/laguest/src/mine/bare_bones/build/gnat/gen/rts/i586/adainclude/s-stoele.ads: In function 'Bare_Bones.Hello':
/home/laguest/src/mine/bare_bones/build/gnat/gen/rts/i586/adainclude/s-stoele.ads:62:69: error: cannot convert to a pointer type

Compiling: /home/laguest/src/mine/bare_bones/src/bare_bones.adb (source file time stamp: 2016-11-16 17:01:32)
 186 lines: No errors
End of compilation
i586-elf-gnatmake: "/home/laguest/src/mine/bare_bones/src/bare_bones.adb" compilation error
makefile:118: recipe for target '/home/laguest/src/mine/bare_bones/build/gnat/gen/pc/debug/disk/boot/bare_bones-i586.elf' failed
make: *** [/home/laguest/src/mine/bare_bones/build/gnat/gen/pc/debug/disk/boot/bare_bones-i586.elf] Error 4

My expanded source is:


pragma restrictions (no_obsolescent_features);
with vga_console;
use vga_console;
with multiboot;
use multiboot;
use type multiboot.multiboot__magic_values;
with system.system__secondary_stack;

procedure bare_bones is
   M9b : system__secondary_stack__mark_id :=
     $system__secondary_stack__ss_mark;
   procedure bare_bones___finalizer;
   freeze bare_bones___finalizer []

   procedure bare_bones___finalizer is
   begin
      $system__secondary_stack__ss_release (M9b);
      return;
   end bare_bones___finalizer;
begin
   line : vga_console__screen_height_range := 1;

   procedure bare_bones__t is
   begin
      vga_console__put__2 ("T called", 1, line, foreground =>
        vga_console__white, background => vga_console__black);
      return;
   end bare_bones__t;

   function bare_bones__hello return string is
   begin
      return "hello";
   end bare_bones__hello;

   vga_console__clear (background => vga_console__black);
   vga_console__put__2 ("Hello, bare bones in Ada", 1, 1, foreground =>
     vga_console__white, background => vga_console__black);
   line := 2;
   if magic = multiboot__magic_value then
      vga_console__put__2 ("Magic numbers match!", 1, 2, foreground =>
        vga_console__white, background => vga_console__black);
   else
      vga_console__put__2 ("Magic numbers don't match!", 1, 2,
        foreground => vga_console__white, background =>
        vga_console__black);
      [program_error "explicit raise"]
   end if;
   line := 3;
   bare_bones__t;
   R7b : constant integer := line + 1;
   [constraint_error when
     not (R7b in 1 .. 25)
     "range check failed"]
   line := R7b;
   B8b : declare
   begin
      vga_console__put__2 (bare_bones__hello, 1, line, foreground =>
        vga_console__white, background => vga_console__black);
   end B8b;
   return;
at end
   bare_bones___finalizer;
end bare_bones;

I'm lost. Anyone have any idea?

^ permalink raw reply	[relevance 3%]

* Re: Generic Embedded List Nodes
  2016-06-21 10:31  0%                             ` Warren
@ 2016-06-21 21:38  0%                               ` Niklas Holsti
  0 siblings, 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  0%                           ` Niklas Holsti
@ 2016-06-21 10:31  0%                             ` Warren
  2016-06-21 21:38  0%                               ` Niklas Holsti
  0 siblings, 1 reply; 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 0%]

* Re: Generic Embedded List Nodes
  2016-06-21  2:20  4%                         ` Warren
@ 2016-06-21  5:52  0%                           ` Niklas Holsti
  2016-06-21 10:31  0%                             ` 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 0%]

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


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 test record looks like this:

   type My_Recd is
      record
         ID:         Natural;
         Node:       aliased Emb_Node;
         Name:       Unbounded_String;  
      end record;

and the Emb_Node looks like this:

   type Emb_Node is
      record
         Next:    access Emb_Node;
         Prev:    access Emb_Node;
      end record;

The Node member is one culprit because it has two Access members (which count as members needing initialization).   Unbounded_String may be another factor.

What is particularly galling about this is that the record already exists, and does NOT need initialization at this point. All I need the compiler do is return it to me based upon its address.  Arg!

To accomplish this, I may have to resort to invoking a C function. But I don't think that will work either. Not by System.Address at least. More head scratching to follow.

Warren


^ permalink raw reply	[relevance 4%]

* Re: Generic Embedded List Nodes
  @ 2016-06-19 20:13  3%             ` Warren
    0 siblings, 1 reply; 200+ results
From: Warren @ 2016-06-19 20:13 UTC (permalink / raw)


On Sunday, 19 June 2016 15:04:05 UTC-4, Dmitry A. Kazakov  wrote:
> Maybe I don't understand the problem, but it seems you want externally 
> linked objects that themselves were of any type. 

Close, but not quite. I had been toying with the idea that each node point back to the containing object, but I've dropped that clumsy idea now.

Now I am back to the original C idea of converting a Node reference back to its containing object through pointer arithmetic (I know: Ada fans gasping). In short, given a Node, I need to get its containing Object.

> The best way to do it is IMO a custom memory pool.

The problem I have with that is performance. For example deleting a node from a list. 

procedure Delete
          (  Brand     : List_Identification_Type;
             Container : in out Web;
             Element   : in out Node
          );

To delete the node, in the worst case, requires traversing the entire list. My lists can be 30,000+ long.

In the embedded node case, I already have direct access to the affected link node. To remove the node from a list I simply say:

    R.Link_Node.Unlink;

and it removes itself out of the doubly linked list (else does nothing if not already in a list).

I have considered a memory pool and not ruled it out. 

Presently I have an generic Object_Of(Node) function working, which makes use of System.Storage_Elements."+" (gasp!) The only drawback is that I need a fake instance of the Object to determine Node'Position at startup. 

Warren

^ permalink raw reply	[relevance 3%]

* ANN: Cortex GNAT RTS 20160522
@ 2016-05-22 14:20  3% 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 3%]

* ANN: Cortex GNAT RTS 20160314
@ 2016-03-14 17:42  4% 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 4%]

* ANN: Cortex GNAT RTS 20160207
@ 2016-02-07 22:45  4% 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 4%]

* Re: Why is the destructor called multiple times after I declare an object?
  2016-01-12 21:05  4%               ` Dmitry A. Kazakov
@ 2016-01-13  0:02  0%                 ` Robert A Duff
  0 siblings, 0 replies; 200+ results
From: Robert A Duff @ 2016-01-13  0:02 UTC (permalink / raw)


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

> On 2016-01-12 21:21, Randy Brukardt wrote:
>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>> news:n72hag$bjq$1@gioia.aioe.org...
>>> On 12/01/2016 00:44, Randy Brukardt wrote:
>>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>>> news:n715oq$fae$1@gioia.aioe.org...
>>>>> On 2016-01-11 19:17, Bob Duff wrote:
>>>>>> Build-in-place is done for return of immutably-limited types,
>>>>>> whether or not the extended return syntax is used.
>>>>>
>>>>> But you can leave one return statement on an exception, catch the
>>>>> exception, and then return through another return statement, with other
>>>>> discriminants and even other type of the result (if it is class-wide).

Yes.  Or you can 'goto' or 'exit' out of an extended return.

>>>>> Therefore the result can be potentially allocated and reallocated any
>>>>> number of times. In which sense is this behavior 'in-place'?

"In place" means that the returned object created by the return
statement that actually returns is the same object as the one at the
call site.  If the return statement raises an exception, then it doesn't
actually return.

Note that this point has nothing to do with extended_return syntax.
An old fashioned "return <expression>;" can raise an exception,
and be handled, and then do a different return.  The syntax doesn't
matter; build-in-place is controlled by "immutably limited".

>>>     return Candidate_1 : T (Size => 1) do
>>>        Size := Candidate_1.Get_Required_Size;
>>>        raise Try_Again;
>>>     end return;
>>> exception
>>>     when Try_Again =>
>>>        return Candidate_2 : T (Size => Size) do
>>>            ...
>>>        end return;
>>>
>>> Since Ada lacks proper user-defined constructors one cannot claim that
>>> Candidate_1 was not fully constructed. Even its Initialize was through.
>>
>> But this is *not* a temporary object. The final object might change identity
>> in such a scenario, but Candidate_1 and Candidate_2 are the *same* object,
>> with different properties.

No, that's not right.  Candidate_1 is an object created by the first
return statement, and finalized during "raise Try_Again;".  It no
longer exists when Candidate_2 is created.  If Candidate_2 is returned
(there's no more raise/goto/whatever in there), then Candidate_2
is the same object as the one created at the call site.

> What makes two objects "same"? ...

The RM is clear on that point, and it is clear that the two candidates
are not the same object.

> Does RM specifically require the implementation to have
> Candidate_1'Address = Candidate_2'Address?

No, the RM says almost nothing about 'Address.  A garbage collector
could move objects around.  Access values are equal if and only if
they designate the same object (even in the presence of GC), but
Addresses are not (necessarily) so well behaved.

> The following program -------------------------->
> with Ada.Text_IO; use Ada.Text_IO;
> with System.Storage_Elements;  use System.Storage_Elements;
>
> procedure Test_Return is
>    package P is
>       type T is tagged limited null record;
>    end P;
>    package Q is
>       type S (L : Positive) is new P.T with record
>          X : String (1..L);
>       end record;
>    end Q;
>    function Create return P.T'Class is
>    begin
>       return Candidate_1 : P.T do
>          Put_Line (Integer_Address'Image (To_Integer
> (Candidate_1'Address)));
>          raise Constraint_Error;
>       end return;
>    exception
>       when Constraint_Error =>
>          return Candidate_2 : Q.S (1000) do
>             Put_Line (Integer_Address'Image (To_Integer
> (Candidate_2'Address)));
>          end return;
>    end Create;	
>    X : P.T'Class := Create;
> begin
>    null;
> end Test_Return;
> <----------------------------------------
> prints:
>>test_return
>  4454256
>  4454272
>
> Is GNAT at fault? Maybe "location" is not the memory address? And

The RM doesn't define "location".  And the rules about 'Address are
pretty loose.  And GNAT is correct here.

I think what Randy meant to say is that X (declared in Test_Return)
is the same object as Candidate_2.  That is what is required by the
RM, and it's what "build in place" means.  In GNAT, if you printed
X'Address it would match Candidate_2'Address, but that's not required
by the RM.  The two candidates are not the same object, as you
correctly noted.

If you had said:

    type Acc is access P.T'Class;
    X : Acc := new P.T'Class'(Create);

then Candidate_1 would get allocated on the heap, then finalized and
deallocated, then Candidate_2 would get allocated on the heap, and
X.all would end up being the same object as Candidate_2.

But keep in mind that the above example is quite unusual.  The normal
case is to have exactly one extended return.  And the size of the thing
is known at compile time, or at least known at the call site, so
the caller can allocate the result (stack, heap, whatever), and
pass the address of that to the function.

> 4. The same object allocated at two different memory addresses?
>
> Finally, I know that you don't consider RM subject to mathematical
> logic, ...

Now, now, that's just sniping.  We try to make the RM correct,
but we make mistakes.

- Bob


^ permalink raw reply	[relevance 0%]

* Re: Why is the destructor called multiple times after I declare an object?
  @ 2016-01-12 21:05  4%               ` Dmitry A. Kazakov
  2016-01-13  0:02  0%                 ` Robert A Duff
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2016-01-12 21:05 UTC (permalink / raw)


On 2016-01-12 21:21, Randy Brukardt wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
> news:n72hag$bjq$1@gioia.aioe.org...
>> On 12/01/2016 00:44, Randy Brukardt wrote:
>>> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message
>>> news:n715oq$fae$1@gioia.aioe.org...
>>>> On 2016-01-11 19:17, Bob Duff wrote:
>>>>> Brian Drummond <brian@shapes.demon.co.uk> writes:
>>>>>
>>>>>> Somehow I expected "extended return" to allocate space and "build in
>>>>>> place" during the execution of the return statement.
>>>>>
>>>>> Build-in-place is done for return of immutably-limited types,
>>>>> whether or not the extended return syntax is used.
>>>>
>>>> But you can leave one return statement on an exception, catch the
>>>> exception, and then return through another return statement, with other
>>>> discriminants and even other type of the result (if it is class-wide).
>>>>
>>>> Therefore the result can be potentially allocated and reallocated any
>>>> number of times. In which sense is this behavior 'in-place'?
>>>
>>> "Build-in-place" means simply that there is no temporary object, the
>>> object
>>> is created directly in its final resting place (that is the memory where
>>> it
>>> will live during its existence).
>>>
>>> Whatever amount of effort it takes to figure out that final resting place
>>> is
>>> not part of the equation.
>>
>> Yes, but you said 'no temporary object' which is untrue because a return
>> statement creates exactly such an object. You could even use this object
>> in order to create another one:
>>
>>     return Candidate_1 : T (Size => 1) do
>>        Size := Candidate_1.Get_Required_Size;
>>        raise Try_Again;
>>     end return;
>> exception
>>     when Try_Again =>
>>        return Candidate_2 : T (Size => Size) do
>>            ...
>>        end return;
>>
>> Since Ada lacks proper user-defined constructors one cannot claim that
>> Candidate_1 was not fully constructed. Even its Initialize was through.
>
> But this is *not* a temporary object. The final object might change identity
> in such a scenario, but Candidate_1 and Candidate_2 are the *same* object,
> with different properties.

What makes two objects "same"? Especially if:

1. none of them exists at the same time as another
2. one of them is already finalized
3. they have different specific types, discriminats, components

If T were not limited would they be same too?

> For a inherently limited type (the kind that requires build-in-place), the
> location of the object is part of its identity, argubly the most important
> part.

What is "location"?

Does RM specifically require the implementation to have 
Candidate_1'Address = Candidate_2'Address?

The following program -------------------------->
with Ada.Text_IO; use Ada.Text_IO;
with System.Storage_Elements;  use System.Storage_Elements;

procedure Test_Return is
    package P is
       type T is tagged limited null record;
    end P;
    package Q is
       type S (L : Positive) is new P.T with record
          X : String (1..L);
       end record;
    end Q;
    function Create return P.T'Class is
    begin
       return Candidate_1 : P.T do
          Put_Line (Integer_Address'Image (To_Integer 
(Candidate_1'Address)));
          raise Constraint_Error;
       end return;
    exception
       when Constraint_Error =>
          return Candidate_2 : Q.S (1000) do
             Put_Line (Integer_Address'Image (To_Integer 
(Candidate_2'Address)));
          end return;
    end Create;	
    X : P.T'Class := Create;
begin
    null;
end Test_Return;
<----------------------------------------
prints:
 >test_return
  4454256
  4454272

Is GNAT at fault? Maybe "location" is not the memory address? And

4. The same object allocated at two different memory addresses?

Finally, I know that you don't consider RM subject to mathematical 
logic, but in logic partial identity is just meaningless. E.g. you may 
say that the highest order digit is the most important part of number, 
but that does not imply two numbers same when their highest order digits 
are same.

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

^ permalink raw reply	[relevance 4%]

* Re: Q: setting an address with pure?
  2015-07-13 18:53  5%         ` Randy Brukardt
@ 2015-07-13 19:50  0%           ` Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2015-07-13 19:50 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> "Simon Wright" <simon@pushface.org> wrote in message 
> news:lyd1zylqfo.fsf@pushface.org...
>>
>>>>    128.    PIOG : PIO with Volatile, Convention => Ada;
>>>>    129.    for PIOG'Address use 16#400E1C00#;
>>>>                                 |
>>>>         >>> expected private type "System.Address"
>>>>         >>> found type universal integer
>
> Of course. It should be:
>
> for PIOG'Address use System.Storage_Elements.To_Address(16#400E1C00#);
>
> Since System.Storage_Elements is Pure, that should work fine here. You
> seemed to indicate that it did not. What's the error message for that?

non-static call not allowed in preelaborated unit

^ permalink raw reply	[relevance 0%]

* Re: setting an address with pure?
  2015-07-11  7:47  3%   ` Simon Wright
@ 2015-07-13 19:10  0%     ` Randy Brukardt
  0 siblings, 0 replies; 200+ results
From: Randy Brukardt @ 2015-07-13 19:10 UTC (permalink / raw)


"Simon Wright" <simon@pushface.org> wrote in message 
news:lypp3zkueh.fsf@pushface.org...
> "Randy Brukardt" <randy@rrsoftware.com> writes:
>
>> "Simon Wright" <simon@pushface.org> wrote in message
>> news:lyy4iokzci.fsf@pushface.org...
>>>I need to specify the address at which a hardware object appears.
>>>
>>> This works:
>>>
>>>   PIOA : PIO
>>>     with
>>>       Import,
>>>       Convention => Ada,
>>>       Address => System.Storage_Elements.To_Address (16#400E0E00#);
>>>
>>> but means that I can't declare the package Pure (or even Preelaborate).
>>
>> You can't have a variable at library level in a Pure package (there
>> shall be no state), so it makes no sense at all for such a package to
>> contain any hardware objects.
>>
>> I don't see any reason why this can't be Preelaborated
>> (System.Storage_Elements is Pure, after all); that depends on the
>> initialization of the type PIO (it needs to have
>> "preelaborable_initialization"; use the pragma if in doubt).
>
> GNAT says that the call to System.Storage_Elements.To_Address is invalid
> because "non-static call not allowed in preelaborated unit", whether
> Preelaborable_Initialization is applied or not. I take it that
> To_Address isn't static because its result type isn't scalar? (4.9(19))

To_Address is a function, not an operator. 4.9(19) does not apply (it only 
applies to predefined operators, and To_Address is neither an operator nor 
predefined [language-defined /= predefined]). There is no way to have a 
static function in Ada to date. (We've been taking about adding an aspect on 
expression functions to allow that.)

This seems like a bug in Ada to me, it's a consequence of making Address a 
private type (it's not private in Janus/Ada because we didn't want the 
incompatibility that would have resulted, so I've never seen this before). 
It certainly seems wrong that an address clause for a hardware entity can't 
be used in a preelaborated unit.

> I think this may be a failure in a GNAT extension; To_Address has pragma
> Pure_Function applied to it, and[2]
>
>   "It specifies that the function Entity is to be considered pure for
>   the purposes of code generation. This means that the compiler can
>   assume that there are no side effects, and in particular that two
>   calls with identical arguments produce the same result. It also means
>   that the function can be used in an address clause."
>
> [1] http://www.ada-auth.org/standards/12rm/html/RM-4-9.html#p19
> [2] https://gcc.gnu.org/onlinedocs/gnat_rm/Pragma-Pure_005fFunction.html

Possibly. In "pedantic" mode, the function would have to be an error because 
implementation-defined stuff shouldn't be changing basic properties (like 
staticness) of language-defined subprograms. But it certainly makes sense to 
work-around this language design flaw.

I'd encourage you to post this problem on Ada-Comment, so that it gets on 
the ARG agenda. (If we end up with a static function aspect, it would make 
sense to apply it to To_Address.)

                                    Randy.


^ permalink raw reply	[relevance 0%]

* Re: Q: setting an address with pure?
  @ 2015-07-13 18:53  5%         ` Randy Brukardt
  2015-07-13 19:50  0%           ` Simon Wright
  0 siblings, 1 reply; 200+ results
From: Randy Brukardt @ 2015-07-13 18:53 UTC (permalink / raw)



"Simon Wright" <simon@pushface.org> wrote in message 
news:lyd1zylqfo.fsf@pushface.org...
>
>>>    128.    PIOG : PIO with Volatile, Convention => Ada;
>>>    129.    for PIOG'Address use 16#400E1C00#;
>>>                                 |
>>>         >>> expected private type "System.Address"
>>>         >>> found type universal integer

Of course. It should be:

for PIOG'Address use System.Storage_Elements.To_Address(16#400E1C00#);

Since System.Storage_Elements is Pure, that should work fine here. You 
seemed to indicate that it did not. What's the error message for that?

                             Randy.


^ permalink raw reply	[relevance 5%]

* Re: Q: setting an address with pure?
  2015-07-10 11:48  4% Q: setting an address with pure? Simon Wright
  2015-07-10 12:03  0% ` G.B.
  2015-07-10 22:37  4% ` Randy Brukardt
@ 2015-07-11 10:35  0% ` Brian Drummond
    2 siblings, 1 reply; 200+ results
From: Brian Drummond @ 2015-07-11 10:35 UTC (permalink / raw)


On Fri, 10 Jul 2015 12:48:29 +0100, Simon Wright wrote:

> I need to specify the address at which a hardware object appears.
> 
> This works:
> 
>    PIOA : PIO
>      with
>        Import,
>        Convention => Ada,
>        Address => System.Storage_Elements.To_Address (16#400E0E00#);
> 
> but means that I can't declare the package Pure (or even Preelaborate).
> 
> Is anyone aware of any GNAT feature that would allow such a package to
> be Pure? There are similar things in their package Standard, for example
> Standard'Address_Size.
> 
> I tried
> 
>    PIOG : PIO with Import, Convention => Ada;
>    for PIOG use at 16#400E1800#;
> 
> but, besides warning me that 'use at' is obsolescent, GNAT still expects
> System.Address not universal integer.

Does the following work for you? It seems to work in the MSP430 Ada 
compiler (based on gcc4.7.2) ... has anything changed in gcc5.1 to make 
this illegal?

-- Brian

with Interfaces;               use Interfaces;    
--   make unsigned_n visible 

package MSP.adc10 is
 
   pragma Preelaborate;
 
 
   adc10dtc0              : unsigned_8;     --  ADC10 Data Transfer 
Control 0 
   Pragma Volatile(adc10dtc0);
   For adc10dtc0'Address use   16#48#;
...
end MSP.adc10;


^ permalink raw reply	[relevance 0%]

* Re: setting an address with pure?
  2015-07-10 22:37  4% ` Randy Brukardt
@ 2015-07-11  7:47  3%   ` Simon Wright
  2015-07-13 19:10  0%     ` Randy Brukardt
  0 siblings, 1 reply; 200+ results
From: Simon Wright @ 2015-07-11  7:47 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> "Simon Wright" <simon@pushface.org> wrote in message 
> news:lyy4iokzci.fsf@pushface.org...
>>I need to specify the address at which a hardware object appears.
>>
>> This works:
>>
>>   PIOA : PIO
>>     with
>>       Import,
>>       Convention => Ada,
>>       Address => System.Storage_Elements.To_Address (16#400E0E00#);
>>
>> but means that I can't declare the package Pure (or even Preelaborate).
>
> You can't have a variable at library level in a Pure package (there
> shall be no state), so it makes no sense at all for such a package to
> contain any hardware objects.
>
> I don't see any reason why this can't be Preelaborated
> (System.Storage_Elements is Pure, after all); that depends on the
> initialization of the type PIO (it needs to have
> "preelaborable_initialization"; use the pragma if in doubt).

GNAT says that the call to System.Storage_Elements.To_Address is invalid
because "non-static call not allowed in preelaborated unit", whether
Preelaborable_Initialization is applied or not. I take it that
To_Address isn't static because its result type isn't scalar? (4.9(19))

I think this may be a failure in a GNAT extension; To_Address has pragma
Pure_Function applied to it, and[2]

   "It specifies that the function Entity is to be considered pure for
   the purposes of code generation. This means that the compiler can
   assume that there are no side effects, and in particular that two
   calls with identical arguments produce the same result. It also means
   that the function can be used in an address clause."

[1] http://www.ada-auth.org/standards/12rm/html/RM-4-9.html#p19
[2] https://gcc.gnu.org/onlinedocs/gnat_rm/Pragma-Pure_005fFunction.html


^ permalink raw reply	[relevance 3%]

* Re: setting an address with pure?
  2015-07-10 11:48  4% Q: setting an address with pure? Simon Wright
  2015-07-10 12:03  0% ` G.B.
@ 2015-07-10 22:37  4% ` Randy Brukardt
  2015-07-11  7:47  3%   ` Simon Wright
  2015-07-11 10:35  0% ` Q: " Brian Drummond
  2 siblings, 1 reply; 200+ results
From: Randy Brukardt @ 2015-07-10 22:37 UTC (permalink / raw)


"Simon Wright" <simon@pushface.org> wrote in message 
news:lyy4iokzci.fsf@pushface.org...
>I need to specify the address at which a hardware object appears.
>
> This works:
>
>   PIOA : PIO
>     with
>       Import,
>       Convention => Ada,
>       Address => System.Storage_Elements.To_Address (16#400E0E00#);
>
> but means that I can't declare the package Pure (or even Preelaborate).

You can't have a variable at library level in a Pure package (there shall be 
no state), so it makes no sense at all for such a package to contain any 
hardware objects.

I don't see any reason why this can't be Preelaborated 
(System.Storage_Elements is Pure, after all); that depends on the 
initialization of the type PIO (it needs to have 
"preelaborable_initialization"; use the pragma if in doubt).

                            Randy.


^ permalink raw reply	[relevance 4%]

* Re: Q: setting an address with pure?
  2015-07-10 12:03  0% ` G.B.
@ 2015-07-10 14:38  0%   ` Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2015-07-10 14:38 UTC (permalink / raw)


"G.B." <bauhaus@futureapps.invalid> writes:

> On 10.07.15 13:48, Simon Wright wrote:
>> I need to specify the address at which a hardware object appears.
>>
>> This works:
>>
>>     PIOA : PIO
>>       with
>>         Import,
>>         Convention => Ada,
>>         Address => System.Storage_Elements.To_Address (16#400E0E00#);
>>
>> but means that I can't declare the package Pure (or even Preelaborate).
>>
>> Is anyone aware of any GNAT feature that would allow such a package to
>> be Pure?
>
> I know this isn't an answer, but still, do you need PIOA'Address fixed
> at compile time? Elsewhere? Could some tool that works after
> compilation take care of placement?

The way that Maciej did this was to fix PIOB in the linker
script. Personally I prefer to do it in Ada, that's all.

^ permalink raw reply	[relevance 0%]

* Re: Q: setting an address with pure?
  2015-07-10 11:48  4% Q: setting an address with pure? Simon Wright
@ 2015-07-10 12:03  0% ` G.B.
  2015-07-10 14:38  0%   ` Simon Wright
  2015-07-10 22:37  4% ` Randy Brukardt
  2015-07-11 10:35  0% ` Q: " Brian Drummond
  2 siblings, 1 reply; 200+ results
From: G.B. @ 2015-07-10 12:03 UTC (permalink / raw)


On 10.07.15 13:48, Simon Wright wrote:
> I need to specify the address at which a hardware object appears.
>
> This works:
>
>     PIOA : PIO
>       with
>         Import,
>         Convention => Ada,
>         Address => System.Storage_Elements.To_Address (16#400E0E00#);
>
> but means that I can't declare the package Pure (or even Preelaborate).
>
> Is anyone aware of any GNAT feature that would allow such a package to
> be Pure?

I know this isn't an answer, but still, do you need
PIOA'Address fixed at compile time? Elsewhere? Could
some tool that works after compilation take care of
placement?



^ permalink raw reply	[relevance 0%]

* Q: setting an address with pure?
@ 2015-07-10 11:48  4% Simon Wright
  2015-07-10 12:03  0% ` G.B.
                   ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: Simon Wright @ 2015-07-10 11:48 UTC (permalink / raw)


I need to specify the address at which a hardware object appears.

This works:

   PIOA : PIO
     with
       Import,
       Convention => Ada,
       Address => System.Storage_Elements.To_Address (16#400E0E00#);

but means that I can't declare the package Pure (or even Preelaborate).

Is anyone aware of any GNAT feature that would allow such a package to
be Pure? There are similar things in their package Standard, for example
Standard'Address_Size.

I tried

   PIOG : PIO with Import, Convention => Ada;
   for PIOG use at 16#400E1800#;

but, besides warning me that 'use at' is obsolescent, GNAT still expects
System.Address not universal integer.


^ permalink raw reply	[relevance 4%]

* Re: Arduino Due vs Mac
  @ 2015-07-07 11:08  4%     ` Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2015-07-07 11:08 UTC (permalink / raw)


Simon Wright <simon@pushface.org> writes:

> Maciej Sobczak <see.my.homepage@gmail.com> writes:
>
> What I did do is look again at https://github.com/shumatech/BOSSA.git
> and **check out the 'arduino' branch** (and compile with clang, not
> GCC!)
>
>> You should be able to upload any binary to the Arduino Due like this:
>>
>> $ bossac -e -w -v -U true -p tty.usbmodemfd131 -b program.bin
>>
>> Note: the USB device is a bit unpredictable, it might be
>> tty.usbmodemfd141 or something - I had to check the availability of
>> this special file name under /dev before every upload and use the
>> actual name that was there.
>
> If I leave out -U and -p this works (after a long pause while it scans
> through /dev/cu.Bluetooth- devices before finding /dev/cu.usbmodem1411
> (this seems stable for the Due programming port on the USB port nearer
> the front of the Macbook)).
>
> Now I have to find out why I'm getting 'Floating point exception: 8",
> but this is a huge improvement!

Turned out to be an integer division by zero if the number of Flash
pages to be written or verified was less than 10.

Now progressing to the point of having a blinking LED!!

As a matter of interest, I was able to write a simple program
initialization in Ada which, with minimal cooperation from the linker
script, lets me use gprbuild.

The linker script starts

   ENTRY(program_initialization)
   MEMORY
   {
       flash (RX)  : ORIGIN = 0x00080000, LENGTH = 512K
       sram (RWX)  : ORIGIN = 0x20070000, LENGTH = 96K
   }
   SECTIONS
   {
       .isr_vector :
       {
           . = ALIGN(4);
           LONG(_estack)
           LONG(program_initialization + 1)
           FILL(0)
           KEEP(*(.isr_vector))
       } > flash

       .text 0x00080100:

startup.ads:

   pragma Restrictions (No_Elaboration_Code);
   package Startup is
      procedure Program_Initialization
      with
        Export,
        Convention => C,
        External_Name => "program_initialization",
        No_Return;
   end Startup;

startup.adb:

   with System.Storage_Elements;
   package body Startup is

      --  Generated by gnatbind.
      procedure Main
      with
        Import,
        Convention => C,
        External_Name => "main",
        No_Return;

      procedure Program_Initialization is
         --  The following symbols are set up in the linker script:
         --
         --  _sidata: the start of read/write data in Flash, to be copied
         --           to SRAM
         --  _sdata:  where read/write data is to be copied to
         --  _edata: the first address after read/write data in SRAM
         --  _sbss:  the start of BSS (to be initialized to zero)
         --  _ebss:  the first address after BSS.

         use System.Storage_Elements;

         Sdata : Storage_Element
           with Import, Convention => C, External_Name => "_sdata";
         Edata : Storage_Element
           with Import, Convention => C, External_Name => "_edata";
         Sbss : Storage_Element
           with Import, Convention => C, External_Name => "_sbss";
         Ebss : Storage_Element
           with Import, Convention => C, External_Name => "_ebss";

         Data_Size : constant Storage_Offset := Edata'Address - Sdata'Address;

         --  Index from 1 so as to avoid subtracting 1 from the size
         Data_In_Flash : Storage_Array (1 .. Data_Size)
           with Import, Convention => C, External_Name => "_sidata";

         Data_In_Sram : Storage_Array (1 .. Data_Size)
           with Import, Convention => C, External_Name => "_sdata";

         Bss_Size : constant Storage_Offset := Ebss'Address - Sbss'Address;

         Bss : Storage_Array (1 .. Bss_Size)
           with Import, Convention => C, External_Name => "_sbss";
      begin
         Data_In_Sram := Data_In_Flash;
         Bss := (others => 0);
         Main;
      end Program_Initialization;

   end Startup;


^ permalink raw reply	[relevance 4%]

* Re: X'Alignment and System.Address without a "mod" operator?
  2015-01-05 16:47  4% ` Jeffrey Carter
@ 2015-01-05 20:07  0%   ` Jacob Sparre Andersen
  0 siblings, 0 replies; 200+ results
From: Jacob Sparre Andersen @ 2015-01-05 20:07 UTC (permalink / raw)


Jeffrey Carter wrote:

> System.Storage_Elements (ARM 13.7.1) has
>
> 8/3
>    function "mod"(Left : Address; Right : Storage_Offset)
>       return Storage_Offset
>          with Convention => Intrinsic;

Thanks!

I wonder why I didn't think of looking there.

Jacob
-- 
"There is nothing worse than having only one drunk head."


^ permalink raw reply	[relevance 0%]

* Re: X'Alignment and System.Address without a "mod" operator?
  @ 2015-01-05 16:47  4% ` Jeffrey Carter
  2015-01-05 20:07  0%   ` Jacob Sparre Andersen
  0 siblings, 1 reply; 200+ results
From: Jeffrey Carter @ 2015-01-05 16:47 UTC (permalink / raw)


On 01/05/2015 07:49 AM, Jacob Sparre Andersen wrote:
> 
>    function "mod" (Left : Address; Right : some_integer_type)
>      return some_integer_type;

System.Storage_Elements (ARM 13.7.1) has

8/3
   function "mod"(Left : Address; Right : Storage_Offset)
      return Storage_Offset
         with Convention => Intrinsic;

http://www.adaic.org/resources/add_content/standards/12rm/html/RM-13-7-1.html

-- 
Jeff Carter
"Blessed is just about anyone with a vested interest in the status quo."
Monty Python's Life of Brian
73


^ permalink raw reply	[relevance 4%]

* Re: A simple question about the "new" allocator
  @ 2014-08-12 13:38  6%   ` G.B.
  0 siblings, 0 replies; 200+ results
From: G.B. @ 2014-08-12 13:38 UTC (permalink / raw)


On 12.08.14 09:35, Dmitry A. Kazakov wrote:
> On Mon, 11 Aug 2014 23:54:50 -0700 (PDT), NiGHTS wrote:
>
>> With all default configurations using a typical Ada compiler, will the following code run indefinitely without fail or will it eventually crash?
>>
>> procedure main is
>>
>>      Test : access Positive;
>>
>> begin
>>
>>      loop
>>          Test := new Positive;
>>      end loop;
>>
>> end main;
>>
>> If this does crash, what would be another way to write this program so
>> that it does not crash?
>>
>> I would prefer not to use Ada.Unchecked_Deallocation.
>
> Write a custom memory pool that does not allocate anything. Make Test a
> pointer to that pool.
>
> P.S. It might sound silly, but such pools are actually useful. When the
> object is already allocated and you want to initialize it and get a pointer
> to, one way to do that is using a fake allocator.

One such storage pool, tailored to the problem, and therefore likely
not applicable to every problem:

with System.Storage_Pools;
with System.Storage_Elements;

generic
    type T is private;
package My_Switching_Pool is

    pragma Preelaborate (My_Switching_Pool);

    use System;

    type Alternating_Pool
      is new Storage_Pools.Root_Storage_Pool with private;
    --  Provides storage for exactly two items of formal type `T`.

    overriding
    procedure Allocate
      (Pool                     : in out Alternating_Pool;
       Storage_Address          :    out Address;
       Size_In_Storage_Elements : in     Storage_Elements.Storage_Count;
       Alignment                : in     Storage_Elements.Storage_Count);
    --  makes the other of the two items available for storage

    overriding
    procedure Deallocate
      (Pool                     : in out Alternating_Pool;
       Storage_Address          : in     Address;
       Size_In_Storage_Elements : in     Storage_Elements.Storage_Count;
       Alignment                : in     Storage_Elements.Storage_Count);

    overriding
    function Storage_Size
      (Pool : Alternating_Pool) return Storage_Elements.Storage_Count;

private
    type Names is (Fst, Snd);
    type Pair is array (Names) of T;

    type Alternating_Pool
      is new Storage_Pools.Root_Storage_Pool with
       record
          In_Use : Names := Snd;
       end record;

    The_Data : Pair;

end My_Switching_Pool;

package body My_Switching_Pool is

    overriding
    procedure Allocate
      (Pool                     : in out Alternating_Pool;
       Storage_Address          :    out Address;
       Size_In_Storage_Elements : in     Storage_Elements.Storage_Count;
       Alignment                : in     Storage_Elements.Storage_Count)
    is
    begin
       -- switch components of `The_Data`
       Pool.In_Use := (if Pool.In_Use = Fst
                       then Snd
                       else Fst);
       Storage_Address := The_Data (Pool.In_Use)'Address;
    end Allocate;

    overriding
    procedure Deallocate
      (Pool                     : in out Alternating_Pool;
       Storage_Address          : in     Address;
       Size_In_Storage_Elements : in     Storage_Elements.Storage_Count;
       Alignment                : in     Storage_Elements.Storage_Count)
    is
    begin
       null;
    end Deallocate;

    overriding
    function Storage_Size
      (Pool : Alternating_Pool)
       return Storage_Elements.Storage_Count
    is
       use type Storage_Elements.Storage_Count;
    begin
       return Pair'Size / Storage_Elements.Storage_Element'Size;
    end Storage_Size;

end My_Switching_Pool;

with My_Switching_Pool;
procedure Main is

    package Two_Numbers is new My_Switching_Pool (T => Positive);

    The_Pool : Two_Numbers.Alternating_Pool;

    type Positive_Ptr is access Positive
       with Storage_Pool => The_Pool;

    Test : Positive_Ptr;

begin

    loop
       Test := new Positive;
    end loop;

end Main;


^ permalink raw reply	[relevance 6%]

* Re: Ada's ranking of popularity at IEEE Spectrum
  @ 2014-07-11 11:56  4%                 ` G.B.
  0 siblings, 0 replies; 200+ results
From: G.B. @ 2014-07-11 11:56 UTC (permalink / raw)


On 10.07.14 20:30, Nasser M. Abbasi wrote:
> On 7/10/2014 1:18 PM, Nasser M. Abbasi wrote:
>
>>
>> One thing that can be done is concentrate on things that are unique
>> or done much better in Ada.

> int& i = *(int*)0xA100;
> ----------------------
>
> Anyone looking at the above 2 examples, can see that Ada is much
> more clear. Actually anyone who does not even know Ada can
> understand what the code does. Try that with the C++ version!

That's more of the anti-C++ fallacy. I think it won't help.

Arguably, it seems equally clear that anyone with a little background
in C++ finds the above declaration very clear, brief, and all on
one line, as should be.

The Ada example as given has incorrect syntax, because 16#A100#
alone is not of type System.Address.

Now Ada requires recent GNATs that support something which is
finally close to a single declaration, viz.

  use System.Storage_Elements;

  I : Integer with Address => To_Address (16#A100#);

(The old Ada syntax, "for I use at ..." is obsolescent,
but still present as well, and you start wondering why they
have changed this very fundamental expression three times.)

I think that typed literals would be even better...

^ permalink raw reply	[relevance 4%]

* Re: OpenSSL development (Heartbleed)
  @ 2014-04-23  8:06  5%                     ` Georg Bauhaus
  0 siblings, 0 replies; 200+ results
From: Georg Bauhaus @ 2014-04-23  8:06 UTC (permalink / raw)


On 23/04/14 09:30, Dmitry A. Kazakov wrote:

>>> Boundary checks or not, the transport layer shall have no access to the
>>> server data.
>>>
>>> A tightly coupled system is vulnerable. If compromising just one component
>>> opens all gates wide, that is a bad standard and bad design. The effects of
>>> errors and faults must be bounded per design.
>>
>> How would you design a transport layer that has no access to whatever is
>> supposed to be transported?
>>
>> "Heartbleed" didn't leak any data that ins't legitimataly needed by
>> OpenSSL (i.e. transported data and/or transport parameters (like keys))
>
> I heard it leaked user data, I didn't go into details. I hope user data are
> not transported, because otherwise that would be even an greater design
> fault.

They are not, by design, transported. I think the issue
boiled down to using some int variable `p' as an offset without
checking bounds. OpenSSL sometimes uses its own malloc,
for historical reasons. So, perhaps this approximates.

At least GNAT warns, no matter what. What do other compiler
diagnose?

with System.Storage_Elements;  use System.Storage_Elements;
with Ada.Integer_Text_IO;

procedure Leak is
    type A is array (Integer range <>) of Storage_Element;
    type A_P is access all A;

    Pool : A (1 .. 123_456);
    for Pool'Address use To_Address (16#100_000#);
    Current_Offset : Storage_Offset := 0;

    function Our_Own_Malloc (Size : Natural) return A_P is
       Result : A_P;
       for Result'Address use Pool'Address + Current_Offset;
    begin
       Current_Offset := Current_Offset + Storage_Offset (Size);
       return Result;
    end Our_Own_Malloc;

    function Something (P : Integer) return A is
       Result : A_P;
    begin
       Result := Our_Own_Malloc (P);
       return Result.all;
    end Something;

    use Ada.Integer_Text_IO;
    I : Integer;
begin
    Get(I);
    declare
       Y : A := Something (I);
    begin
       null;
    end;
end Leak;


^ permalink raw reply	[relevance 5%]

* Re: subtype of System.Address type
  @ 2014-02-27 16:06  6% ` adambeneschan
  0 siblings, 0 replies; 200+ results
From: adambeneschan @ 2014-02-27 16:06 UTC (permalink / raw)


On Wednesday, February 26, 2014 9:19:57 PM UTC-8, ashwath...@gmail.com wrote:
> Hello,
> 
> My compiler(GNAT 3.1 ) gives an error for the following statement.
> 
> 
> 
>  subtype MEMORY_RANGE_TYPE is SYSTEM.ADDRESS range 16#0000_0000#..16#7FFF_FFFF#; 
> 
> It says incorrect constraint for this type.
> 
> Kindly let me know the mistake I am doing.

Like everyone else said, System.Address is a private type.  If you really need to use integers as addresses, use System.Storage_Elements.Integer_Address:

   subtype Memory_Range_Type is System.Storage_Elements.Integer_Address range
      16#0000_0000# .. 16#7FFF_FFFF#;

Integer_Address is required to be either a signed or modular integer subtype; either way, the above will work as long as both 0 and 7FFFFFFF are in range for the implementation-defined subtype.  Then, System.Storage_Elements.To_Address(Value) will convert an Integer_Address to a System.Address.  See RM 13.7.1.  (This package has been part of the language since Ada 95.)

^ permalink raw reply	[relevance 6%]

* Re: Increasing GNAT's heap
  @ 2013-11-12 19:30  4%     ` Georg Bauhaus
  0 siblings, 0 replies; 200+ results
From: Georg Bauhaus @ 2013-11-12 19:30 UTC (permalink / raw)


On 12.11.13 15:00, Dmitry A. Kazakov wrote:
> On Tue, 12 Nov 2013 14:26:42 +0100, Georg Bauhaus wrote:
> 
>> On 12.11.13 12:09, Dmitry A. Kazakov wrote:
>>> Does anybody know a way to increase the heap size available for GNAT? It
>>> crashes with famous GNAT BUG DETECTED, Storage_Error heap exhausted.
>>
>> Do ulimit values have any effect?
> 
> $ ulimit
> unlimited


FWIW, I am finding it difficult to trigger something beyond
"Storage_Error heap exhausted" (no bug, i.e.); SE seems kind
of expected for some amounts of memory requested. The program below
tries to make the memory manager commit, by forcing random inits
of the memory at random positions. The program runs quite
a while before either me interrupting it at 2**34 storage elements
(Mac OS X 10.7.5), or some Linux VMs duly reporting STORAGE_ERROR
while processing the memory for 2**32.

Both systems are 64 bit, though, so I can't tell what 32 bit gives as
results. I'm curious. Does this trigger a bug box in your system?
(size_t and others are there for hysteric raisins of comparison.)


with System.Storage_Elements;  use System.Storage_Elements;
with Ada.Unchecked_Deallocation;
with Ada.Numerics.Discrete_Random, Ada.Numerics.Elementary_Functions;
with Ada.Text_IO;

procedure Alloc_Ada
is
   --  powers of 2, for growing allocated sizes:
   Small : constant := 16;
   Large : constant := 40;

   type Void_Ptr is access Storage_Array;
   subtype size_t is Storage_Offset;
   package Size_T_IO is new Ada.Text_IO.Integer_IO (size_t);
   use Size_T_IO, Ada.Text_IO;

   procedure Init (Object : Void_Ptr; Acc : out Storage_Element);
   --  Initialize some of Object with random data. Place something
   --  almost anywhere in the allocated area, assuming that doing so
   --  will require commits.

   procedure Free is
     new Ada.Unchecked_Deallocation (Storage_Array, Void_Ptr);

   procedure Init (Object : Void_Ptr; Acc : out Storage_Element) is
      subtype Places is Storage_Offset range 0 .. Object'Length - 1;
      package Arb is new Ada.Numerics.Discrete_Random (Storage_Element);
      package Pos is new Ada.Numerics.Discrete_Random (Places);
      package Math renames Ada.Numerics.Elementary_Functions;
      G : Arb.Generator;
      P : Pos.Generator;
      Offset, Previous_Offset : Storage_Offset := 0;
      No_Of_Inits : constant Natural :=
        2**(Natural (Math.Log (Float (Object'Length), 2.0))
              -
            (Small - 4));
   begin
      Arb.Reset (G); Pos.Reset (P);
      Acc := 0;
      for Run in 1 .. No_Of_Inits loop
         Previous_Offset := Offset;
         Offset := Pos.Random (P);
         Object (Offset) := Arb.Random (G);
         Acc := Acc / 2
           + (Object (Previous_Offset) + Object (Offset)) / 4;
      end loop;
   end Init;

   Buffer : Void_Ptr;
   Kept : Storage_Element;

begin
   for Power in size_t range Small .. Large loop
      Put ("At "); Put (Power);
      Put (" ("); Put (2**Natural (Power)); Put (")");

      Buffer := new Storage_Array (0 .. 2**Natural (Power));
      Init (Buffer, Acc => Kept);

      Put_Line (Storage_Element'Image (Kept));

      Free (Buffer);
   end loop;
end Alloc_Ada;

^ permalink raw reply	[relevance 4%]

* Re: Unchecked_Conversion vs Address-overlaying
  2013-05-26 23:34  4% Unchecked_Conversion vs Address-overlaying Shark8
@ 2013-05-27  4:37  0% ` Per Sandberg
  0 siblings, 0 replies; 200+ results
From: Per Sandberg @ 2013-05-27  4:37 UTC (permalink / raw)


On Sun, 26 May 2013 16:34:54 -0700 (PDT)
Shark8 <onewingedshark@gmail.com> wrote:

> I recently had to make a dump-function for a collection of bytes and
> was wondering if the method I chose (address-overlaying) was better
> than using Unchecked_Conversion or not.
> 
> ------------------------------
> 
>     -- The private type BLOB designates some collection of
> memory-data; -- it is actually an access to a storage-array [of
> Storage-Elements]. -- It's sized to the Cell_Size that all the other
> types are given so -- that they can be wrapped in a record and that
> pushed onto a stack. Type BLOB is Not Null Access All
> System.Storage_Elements.Storage_Array with
> 	Size => Cell_Size;
> 
> 
>     -- Returns a hex-dump of the given BLOB.
>     Function Image( Item : BLOB ) Return String is
> 	Use System, System.Storage_Elements;
> 
>         -- Our undervalued friend, the Nybble and the Byte, as well
>         -- as a type that serves as a collection of bytes.
> 	Subtype Nybble	is Interfaces.Unsigned_8 Range
> 16#0#..16#F#; Subtype Byte	is Interfaces.Unsigned_8;
> 	Type Byte_String is Array(Positive Range <>) of Byte;
> 
>         -- Return a Hex Character for any given Nybble.
> 	Function Nybble_to_Hex( Input : Nybble ) Return Character is
> 	    subtype Decimal is Nybble range 0..9;
> 	    Base : Constant Interfaces.Unsigned_8:= 
> 	      			( if Input in Decimal then
> Character'Pos('0') else Character'Pos('A') - 10 );
> 	begin
> 	    Return Character'Val( Base + Input );
> 	End Nybble_To_Hex;
> 
>         -- Return the string that is the hex-values for
>         -- the high- and low-nybbles of the given byte.
> 	Function Image( Item : Byte ) Return String is
> 	begin
> 	    Return ( 1 => Nybble_to_Hex(Item / 16),     -- High
> 	             2 => Nybble_to_Hex(Item mod 16) ); -- Low
> 	End Image;
> 
>         -- Given a Byte_String return the string containing its
> Nybbles. Function Image( Item : Byte_String ) return String is
> 	begin
> 	    Case Item'Length is
> 	    when 0	=> Return "";
> 	    when 1	=> Return Image(Item(Item'First));
> 	    when others	=>
> 		declare
> 		    Head : String Renames Image(Item(Item'First));
> 		    subtype Tail_Range is Positive Range
> 		      Positive'Succ(Item'First)..Item'Last;
> 
> 		    Tail : String Renames Image(Item(Tail_Range));
> 		begin
> 		    Return Head & Tail;
> 		end;
> 	    end case;
> 	End Image;
> 
>         -- Calculate the length of the BLOB, in bytes.
> 	Length : Constant Natural:=
> (Item'Length*Storage_Array'Component_Size) / Byte'Object_Size;
> 	Pragma Warnings(Off);
>         -- Create an overlayed, non-initializing variable of the
> proper size. Image_String : Byte_String(1..Length)
> 	  with Import, Convention => Ada, Address => Item.All'Address;
> 	Pragma Warnings(On);
>     begin
>         -- Return the image of that overlay.
> 	Return Image(Image_String);
>     end Image;


And have a look on "GNAT.Memory_Dump".
/Per

^ permalink raw reply	[relevance 0%]

* Unchecked_Conversion vs Address-overlaying
@ 2013-05-26 23:34  4% Shark8
  2013-05-27  4:37  0% ` Per Sandberg
  0 siblings, 1 reply; 200+ results
From: Shark8 @ 2013-05-26 23:34 UTC (permalink / raw)


I recently had to make a dump-function for a collection of bytes and was wondering if the method I chose (address-overlaying) was better than using Unchecked_Conversion or not.

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

    -- The private type BLOB designates some collection of memory-data;
    -- it is actually an access to a storage-array [of Storage-Elements].
    -- It's sized to the Cell_Size that all the other types are given so
    -- that they can be wrapped in a record and that pushed onto a stack.
    Type BLOB is Not Null Access All System.Storage_Elements.Storage_Array
    with
	Size => Cell_Size;


    -- Returns a hex-dump of the given BLOB.
    Function Image( Item : BLOB ) Return String is
	Use System, System.Storage_Elements;

        -- Our undervalued friend, the Nybble and the Byte, as well
        -- as a type that serves as a collection of bytes.
	Subtype Nybble	is Interfaces.Unsigned_8 Range 16#0#..16#F#;
	Subtype Byte	is Interfaces.Unsigned_8;
	Type Byte_String is Array(Positive Range <>) of Byte;

        -- Return a Hex Character for any given Nybble.
	Function Nybble_to_Hex( Input : Nybble ) Return Character is
	    subtype Decimal is Nybble range 0..9;
	    Base : Constant Interfaces.Unsigned_8:= 
	      			( if Input in Decimal then Character'Pos('0')
				  else Character'Pos('A') - 10 );
	begin
	    Return Character'Val( Base + Input );
	End Nybble_To_Hex;

        -- Return the string that is the hex-values for
        -- the high- and low-nybbles of the given byte.
	Function Image( Item : Byte ) Return String is
	begin
	    Return ( 1 => Nybble_to_Hex(Item / 16),     -- High
	             2 => Nybble_to_Hex(Item mod 16) ); -- Low
	End Image;

        -- Given a Byte_String return the string containing its Nybbles.
	Function Image( Item : Byte_String ) return String is
	begin
	    Case Item'Length is
	    when 0	=> Return "";
	    when 1	=> Return Image(Item(Item'First));
	    when others	=>
		declare
		    Head : String Renames Image(Item(Item'First));
		    subtype Tail_Range is Positive Range
		      Positive'Succ(Item'First)..Item'Last;

		    Tail : String Renames Image(Item(Tail_Range));
		begin
		    Return Head & Tail;
		end;
	    end case;
	End Image;

        -- Calculate the length of the BLOB, in bytes.
	Length : Constant Natural:= (Item'Length*Storage_Array'Component_Size)
					  / Byte'Object_Size;
	Pragma Warnings(Off);
        -- Create an overlayed, non-initializing variable of the proper size.
	Image_String : Byte_String(1..Length)
	  with Import, Convention => Ada, Address => Item.All'Address;
	Pragma Warnings(On);
    begin
        -- Return the image of that overlay.
	Return Image(Image_String);
    end Image;


^ permalink raw reply	[relevance 4%]

* Re: Efficient Sequential Access to Arrays
  @ 2013-02-25 21:18  5%                     ` Eryndlia Mavourneen
  0 siblings, 0 replies; 200+ results
From: Eryndlia Mavourneen @ 2013-02-25 21:18 UTC (permalink / raw)


On Friday, July 27, 2012 3:21:18 AM UTC-5, Keean Schupke wrote:
> 
> I am wondering if there is a way to use address arithmetic that would be just as safe as array indexing? ...


Perhaps something along the lines of:

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

package body Keean_Pkg is

   type Value_Type is limited private;
   type Index_Type is range <>;
   type Array_Type is array (Index_Type) of Value_Type;

   Element_Size : constant Storage_Offset := A'Component_Size / Storage_Unit;
   Current_A    : Address;

begin

   Current_A := Some_Element'Address; -- address of 1st element to be processed

   Processing_Loop: ... loop
      Declare_A: declare
         A : Array_Type;
         for A'Address use Current_A;
      begin
         -- Perform processing on the element of array A
         ...

         Current_A := Current_A + Element_Size;
      end Declare_A;
   end loop Processing_Loop;

end Keean_Pkg;



^ permalink raw reply	[relevance 5%]

* Re: GNAT 4.4.5 Record Bit_Order Endian issues
  2013-01-19 12:48  4%               ` AdaMagica
@ 2013-01-22  0:14  0%                 ` Randy Brukardt
  0 siblings, 0 replies; 200+ results
From: Randy Brukardt @ 2013-01-22  0:14 UTC (permalink / raw)


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

"AdaMagica" <christ-usch.grein@t-online.de> wrote in message 
news:9dc6d5fe-3382-44dd-8460-e042bd6b808e@googlegroups.com...
On Saturday, January 19, 2013 2:43:03 AM UTC+1, Stephen Leake wrote:
...
>> Then 13.5.2 talks about the Position attribute.
>> Which just retreives the mysterious "position" number, it doesn't say
>> what it _means_.

Huh? 13.5.2(2/2) says in part:
"denotes Denotes the same value as R.C'Address � R'Address". That makes it
pretty clear what it represents (for the Default_Bit_Order).

For the non-default bit order, it just is whatever you specify (and that's 
all we can say,
because it *doesn't* have a clear physical meaning - it defines the machine 
scalars to use,
which makes it a totally confusing mess if you try to work the other way).

>> > I agree that the RM is confusing in this area.
>> > It's partly my fault.  :-(
>> Ok. What paragraphs do we add? (in five years; better late than never :)

I don't think there is anything that would help. We surely tried when we 
created the non-default bit order stuff.

>The AARM helps, but this is of course not a binding standard:
>
>13.5.2(2.a/2) Ramification: {AI95-00133-01} Thus, for the default bit 
>order,
>R.C'Position is the offset of C in storage elements from the beginning of 
>the object,
>where the first storage element of an object is numbered zero. R'Address +
>R.C'Position = R.C'Address. For record extensions, the offset is not 
>measured
>from the beginning of the extension part, but from the beginning of the 
>whole object,
>as usual.
>(2.b) In �R.C'Address � R'Address�, the "�" operator is the one in
>System.Storage_Elements that takes two Addresses and returns a 
>Storage_Offset.
>
>Why isn't this in the RM itself? An oversight?

It's not necessary, it follows directly from the definition of "-", 
'Address, and 'Position as related above, for the default bit order case. In 
the non-default bit order, (2.a/2) isn't even true, so it wouldn't help to 
add such a statement in that case. ('Position defines the machine scalars to 
use in that case, and the meaning defies any simple explanation -- it's 
roughly the same as the meaning in the default-bit-order case, but not 
exactly. The RM can never lie.)

                                                   Randy.







^ permalink raw reply	[relevance 0%]

* Re: GNAT 4.4.5 Record Bit_Order Endian issues
  @ 2013-01-19 12:48  4%               ` AdaMagica
  2013-01-22  0:14  0%                 ` Randy Brukardt
  0 siblings, 1 reply; 200+ results
From: AdaMagica @ 2013-01-19 12:48 UTC (permalink / raw)


On Saturday, January 19, 2013 2:43:03 AM UTC+1, Stephen Leake wrote:
> Robert A Duff <bobduff@shell01.TheWorld.com> writes:
> > Stephen Leake <stephen_leake@stephe-leake.org> writes:
> >>      component_clause ::=
> >>          component_local_name at position range first_bit .. last_bit;
> >> But I could find no definition of "position"!
> > The very next paragraph defines the syntax:
> >     position ::= static_expression
> That doesn't say "position is the number of storage_units from the start
> of the record" (there's probably a better definition in Cohen's paper).
> For all I can tell from the ARM, "position" could be a color number, or
> the number of angels on the head of a pin!
> Then 13.5.2 talks about the Position attribute.
> Which just retreives the mysterious "position" number, it doesn't say
> what it _means_.
> > I agree that the RM is confusing in this area.
> > It's partly my fault.  :-(
> Ok. What paragraphs do we add? (in five years; better late than never :)

The AARM helps, but this is of course not a binding standard:

13.5.2(2.a/2) Ramification: {AI95-00133-01} Thus, for the default bit order, R.C'Position is the offset of C in storage elements from the beginning of the object, where the first storage element of an object is numbered zero. R'Address + R.C'Position = R.C'Address. For record extensions, the offset is not measured from the beginning of the extension part, but from the beginning of the whole object, as usual.
(2.b) In “R.C'Address – R'Address”, the "–" operator is the one in System.Storage_Elements that takes two Addresses and
returns a Storage_Offset.

Why isn't this in the RM itself? An oversight?



^ permalink raw reply	[relevance 4%]

* Re: GNAT (GCC) Profile Guided Compilation
  2012-07-18 10:01  4%                                   ` 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  4%                                   ` 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 4%]

* Re: Efficient Sequential Access to Arrays
  @ 2012-07-15 21:44  6%     ` 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 6%]

* 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  2%     ` 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  2%     ` 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 2%]

* Re: understanding runtime support
  @ 2012-05-15 14:48  3% ` Lucretia
  0 siblings, 0 replies; 200+ results
From: Lucretia @ 2012-05-15 14:48 UTC (permalink / raw)


On Friday, May 11, 2012 4:49:07 AM UTC+1, Patrick wrote:

> What is the situation with Ada? I was hoping to target various M68K related architectures, ARM and AVR.

As linked to a number of times, my tamp repo on github (above) has some code that will build for an arm board and can be run on it, doesn't do anything though :D

With Ada, you can pass a number of compilation units to the compiler and it will build them, some of these units can be what is the equivalent of a "main." What GNAT does with this is as follows, gnatbind is called to generate a new file b~<your entry procedure name>.adb, this file contains procedures for calling the elaboration code (to set up arrays and other data), then calls your entry point and on exit calls an exit procedure.

An example is best, so given the following entry point:

procedure test is
   a : string(1 .. 5) := "hello";
begin
   null;
end test;

and compiled with:

$ gnatmake -c test.adb 
gcc-4.6 -c test.adb
$ gnatmake -b test.adb 
gnatbind -x test.ali

you are left with the following b~test.ad[sb]:

pragma Ada_95;
with System;
package ada_main is
   pragma Warnings (Off);

   gnat_argc : Integer;
   gnat_argv : System.Address;
   gnat_envp : System.Address;

   pragma Import (C, gnat_argc);
   pragma Import (C, gnat_argv);
   pragma Import (C, gnat_envp);

   gnat_exit_status : Integer;
   pragma Import (C, gnat_exit_status);

   GNAT_Version : constant String :=
                    "GNAT Version: 4.6" & ASCII.NUL;
   pragma Export (C, GNAT_Version, "__gnat_version");

   Ada_Main_Program_Name : constant String := "_ada_test" & ASCII.NUL;
   pragma Export (C, Ada_Main_Program_Name, "__gnat_ada_main_program_name");

   procedure adafinal;
   pragma Export (C, adafinal, "adafinal");

   procedure adainit;
   pragma Export (C, adainit, "adainit");

   procedure Break_Start;
   pragma Import (C, Break_Start, "__gnat_break_start");

   function main
     (argc : Integer;
      argv : System.Address;
      envp : System.Address)
      return Integer;
   pragma Export (C, main, "main");

   type Version_32 is mod 2 ** 32;
   u00001 : constant Version_32 := 16#2951576a#;
   pragma Export (C, u00001, "testB");
   u00002 : constant Version_32 := 16#ba46b2cd#;
   pragma Export (C, u00002, "system__standard_libraryB");
   u00003 : constant Version_32 := 16#1e2e640d#;
   pragma Export (C, u00003, "system__standard_libraryS");
   u00004 : constant Version_32 := 16#23e1f70b#;
   pragma Export (C, u00004, "systemS");
   u00005 : constant Version_32 := 16#0936cab5#;
   pragma Export (C, u00005, "system__memoryB");
   u00006 : constant Version_32 := 16#e96a4b1e#;
   pragma Export (C, u00006, "system__memoryS");
   u00007 : constant Version_32 := 16#3ffc8e18#;
   pragma Export (C, u00007, "adaS");
   u00008 : constant Version_32 := 16#9229643d#;
   pragma Export (C, u00008, "ada__exceptionsB");
   u00009 : constant Version_32 := 16#e3df9d67#;
   pragma Export (C, u00009, "ada__exceptionsS");
   u00010 : constant Version_32 := 16#95643e9a#;
   pragma Export (C, u00010, "ada__exceptions__last_chance_handlerB");
   u00011 : constant Version_32 := 16#03cf4fc2#;
   pragma Export (C, u00011, "ada__exceptions__last_chance_handlerS");
   u00012 : constant Version_32 := 16#30ec78bc#;
   pragma Export (C, u00012, "system__soft_linksB");
   u00013 : constant Version_32 := 16#e2ebe502#;
   pragma Export (C, u00013, "system__soft_linksS");
   u00014 : constant Version_32 := 16#0d2b82ae#;
   pragma Export (C, u00014, "system__parametersB");
   u00015 : constant Version_32 := 16#bfbc74f1#;
   pragma Export (C, u00015, "system__parametersS");
   u00016 : constant Version_32 := 16#72905399#;
   pragma Export (C, u00016, "system__secondary_stackB");
   u00017 : constant Version_32 := 16#378fd0a5#;
   pragma Export (C, u00017, "system__secondary_stackS");
   u00018 : constant Version_32 := 16#ace32e1e#;
   pragma Export (C, u00018, "system__storage_elementsB");
   u00019 : constant Version_32 := 16#d92c8a93#;
   pragma Export (C, u00019, "system__storage_elementsS");
   u00020 : constant Version_32 := 16#4f750b3b#;
   pragma Export (C, u00020, "system__stack_checkingB");
   u00021 : constant Version_32 := 16#80434b27#;
   pragma Export (C, u00021, "system__stack_checkingS");
   u00022 : constant Version_32 := 16#a7343537#;
   pragma Export (C, u00022, "system__exception_tableB");
   u00023 : constant Version_32 := 16#8120f83b#;
   pragma Export (C, u00023, "system__exception_tableS");
   u00024 : constant Version_32 := 16#ff3fa16b#;
   pragma Export (C, u00024, "system__htableB");
   u00025 : constant Version_32 := 16#cc3e5bd4#;
   pragma Export (C, u00025, "system__htableS");
   u00026 : constant Version_32 := 16#8b7dad61#;
   pragma Export (C, u00026, "system__string_hashB");
   u00027 : constant Version_32 := 16#057d2f9f#;
   pragma Export (C, u00027, "system__string_hashS");
   u00028 : constant Version_32 := 16#6a8a6a74#;
   pragma Export (C, u00028, "system__exceptionsB");
   u00029 : constant Version_32 := 16#86f01d0a#;
   pragma Export (C, u00029, "system__exceptionsS");
   u00030 : constant Version_32 := 16#b012ff50#;
   pragma Export (C, u00030, "system__img_intB");
   u00031 : constant Version_32 := 16#213a17c9#;
   pragma Export (C, u00031, "system__img_intS");
   u00032 : constant Version_32 := 16#dc8e33ed#;
   pragma Export (C, u00032, "system__tracebackB");
   u00033 : constant Version_32 := 16#4266237e#;
   pragma Export (C, u00033, "system__tracebackS");
   u00034 : constant Version_32 := 16#4900ab7d#;
   pragma Export (C, u00034, "system__unsigned_typesS");
   u00035 : constant Version_32 := 16#907d882f#;
   pragma Export (C, u00035, "system__wch_conB");
   u00036 : constant Version_32 := 16#9c0ad936#;
   pragma Export (C, u00036, "system__wch_conS");
   u00037 : constant Version_32 := 16#22fed88a#;
   pragma Export (C, u00037, "system__wch_stwB");
   u00038 : constant Version_32 := 16#b11bf537#;
   pragma Export (C, u00038, "system__wch_stwS");
   u00039 : constant Version_32 := 16#5d4d477e#;
   pragma Export (C, u00039, "system__wch_cnvB");
   u00040 : constant Version_32 := 16#82f45fe0#;
   pragma Export (C, u00040, "system__wch_cnvS");
   u00041 : constant Version_32 := 16#f77d8799#;
   pragma Export (C, u00041, "interfacesS");
   u00042 : constant Version_32 := 16#75729fba#;
   pragma Export (C, u00042, "system__wch_jisB");
   u00043 : constant Version_32 := 16#d686c4f4#;
   pragma Export (C, u00043, "system__wch_jisS");
   u00044 : constant Version_32 := 16#ada34a87#;
   pragma Export (C, u00044, "system__traceback_entriesB");
   u00045 : constant Version_32 := 16#71c0194a#;
   pragma Export (C, u00045, "system__traceback_entriesS");
   u00046 : constant Version_32 := 16#13cbc5a8#;
   pragma Export (C, u00046, "system__crtlS");

   --  BEGIN ELABORATION ORDER
   --  ada%s
   --  interfaces%s
   --  system%s
   --  system.htable%s
   --  system.img_int%s
   --  system.img_int%b
   --  system.parameters%s
   --  system.parameters%b
   --  system.crtl%s
   --  system.standard_library%s
   --  system.exceptions%s
   --  system.exceptions%b
   --  system.storage_elements%s
   --  system.storage_elements%b
   --  system.stack_checking%s
   --  system.stack_checking%b
   --  system.string_hash%s
   --  system.string_hash%b
   --  system.htable%b
   --  system.traceback_entries%s
   --  system.traceback_entries%b
   --  ada.exceptions%s
   --  system.soft_links%s
   --  system.unsigned_types%s
   --  system.wch_con%s
   --  system.wch_con%b
   --  system.wch_cnv%s
   --  system.wch_jis%s
   --  system.wch_jis%b
   --  system.wch_cnv%b
   --  system.wch_stw%s
   --  system.wch_stw%b
   --  ada.exceptions.last_chance_handler%s
   --  ada.exceptions.last_chance_handler%b
   --  system.exception_table%s
   --  system.exception_table%b
   --  system.memory%s
   --  system.memory%b
   --  system.standard_library%b
   --  system.secondary_stack%s
   --  system.soft_links%b
   --  system.secondary_stack%b
   --  system.traceback%s
   --  ada.exceptions%b
   --  system.traceback%b
   --  test%b
   --  END ELABORATION ORDER

end ada_main;

pragma Ada_95;
pragma Source_File_Name (ada_main, Spec_File_Name => "b~test.ads");
pragma Source_File_Name (ada_main, Body_File_Name => "b~test.adb");

package body ada_main is
   pragma Warnings (Off);

   procedure Do_Finalize;
   pragma Import (C, Do_Finalize, "system__standard_library__adafinal");

   Local_Priority_Specific_Dispatching : constant String := "";
   Local_Interrupt_States : constant String := "";

   procedure adainit is
      E13 : Boolean; pragma Import (Ada, E13, "system__soft_links_E");
      E23 : Boolean; pragma Import (Ada, E23, "system__exception_table_E");
      E17 : Boolean; pragma Import (Ada, E17, "system__secondary_stack_E");

      Main_Priority : Integer;
      pragma Import (C, Main_Priority, "__gl_main_priority");
      Time_Slice_Value : Integer;
      pragma Import (C, Time_Slice_Value, "__gl_time_slice_val");
      WC_Encoding : Character;
      pragma Import (C, WC_Encoding, "__gl_wc_encoding");
      Locking_Policy : Character;
      pragma Import (C, Locking_Policy, "__gl_locking_policy");
      Queuing_Policy : Character;
      pragma Import (C, Queuing_Policy, "__gl_queuing_policy");
      Task_Dispatching_Policy : Character;
      pragma Import (C, Task_Dispatching_Policy, "__gl_task_dispatching_policy");
      Priority_Specific_Dispatching : System.Address;
      pragma Import (C, Priority_Specific_Dispatching, "__gl_priority_specific_dispatching");
      Num_Specific_Dispatching : Integer;
      pragma Import (C, Num_Specific_Dispatching, "__gl_num_specific_dispatching");
      Main_CPU : Integer;
      pragma Import (C, Main_CPU, "__gl_main_cpu");
      Interrupt_States : System.Address;
      pragma Import (C, Interrupt_States, "__gl_interrupt_states");
      Num_Interrupt_States : Integer;
      pragma Import (C, Num_Interrupt_States, "__gl_num_interrupt_states");
      Unreserve_All_Interrupts : Integer;
      pragma Import (C, Unreserve_All_Interrupts, "__gl_unreserve_all_interrupts");
      Zero_Cost_Exceptions : Integer;
      pragma Import (C, Zero_Cost_Exceptions, "__gl_zero_cost_exceptions");
      Detect_Blocking : Integer;
      pragma Import (C, Detect_Blocking, "__gl_detect_blocking");
      Default_Stack_Size : Integer;
      pragma Import (C, Default_Stack_Size, "__gl_default_stack_size");
      Leap_Seconds_Support : Integer;
      pragma Import (C, Leap_Seconds_Support, "__gl_leap_seconds_support");

      procedure Install_Handler;
      pragma Import (C, Install_Handler, "__gnat_install_handler");

      Handler_Installed : Integer;
      pragma Import (C, Handler_Installed, "__gnat_handler_installed");
   begin
      Main_Priority := -1;
      Time_Slice_Value := -1;
      WC_Encoding := 'b';
      Locking_Policy := ' ';
      Queuing_Policy := ' ';
      Task_Dispatching_Policy := ' ';
      Priority_Specific_Dispatching :=
        Local_Priority_Specific_Dispatching'Address;
      Num_Specific_Dispatching := 0;
      Main_CPU := -1;
      Interrupt_States := Local_Interrupt_States'Address;
      Num_Interrupt_States := 0;
      Unreserve_All_Interrupts := 0;
      Zero_Cost_Exceptions := 1;
      Detect_Blocking := 0;
      Default_Stack_Size := -1;
      Leap_Seconds_Support := 0;

      if Handler_Installed = 0 then
         Install_Handler;
      end if;

      System.Exception_Table'Elab_Body;
      E23 := True;
      System.Soft_Links'Elab_Body;
      E13 := True;
      System.Secondary_Stack'Elab_Body;
      E17 := True;
   end adainit;

   procedure adafinal is
   begin
      Do_Finalize;
   end adafinal;

   function main
     (argc : Integer;
      argv : System.Address;
      envp : System.Address)
      return Integer
   is
      procedure initialize (Addr : System.Address);
      pragma Import (C, initialize, "__gnat_initialize");

      procedure finalize;
      pragma Import (C, finalize, "__gnat_finalize");

      procedure Ada_Main_Program;
      pragma Import (Ada, Ada_Main_Program, "_ada_test");

      SEH : aliased array (1 .. 2) of Integer;

      Ensure_Reference : aliased System.Address := Ada_Main_Program_Name'Address;
      pragma Volatile (Ensure_Reference);

   begin
      gnat_argc := argc;
      gnat_argv := argv;
      gnat_envp := envp;

      Initialize (SEH'Address);
      adainit;
      Break_Start;
      Ada_Main_Program;
      Do_Finalize;
      Finalize;
      return (gnat_exit_status);
   end;

--  BEGIN Object file/option list
   --   ./test.o
   --   -L./
   --   -L/usr/lib/gcc/x86_64-linux-gnu/4.6/adalib/
   --   -shared
   --   -lgnat-4.6
--  END Object file/option list   

end ada_main;

Lots of stuff in there, but you get the idea. See the "main" procedure? That call's adainit, then the actual procedure Ada_Main_Program_Name - test.

So, for bare hardware you need to mess around with the gnatbind step like this so that it doesn't generate some stuff, my b~blink.adb main is:

   procedure main is

      procedure Ada_Main_Program;
      pragma Import (Ada, Ada_Main_Program, "_ada_blink");

      Ensure_Reference : aliased System.Address := Ada_Main_Program_Name'Address;
      pragma Volatile (Ensure_Reference);

   begin
      adainit;
      Break_Start;
      Ada_Main_Program;
   end;

I just use the default discovery startup code which calls main from some assembly after setting up the hardware.

Luke.



^ permalink raw reply	[relevance 3%]

* Re: xor
  @ 2012-03-27 20:13  4%         ` Jeffrey Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey Carter @ 2012-03-27 20:13 UTC (permalink / raw)


On 03/27/2012 01:09 PM, Michael Moeller wrote:
>
> I have to read in what in C is called an unsigned byte, which in fact is
> a stream of bytes without any interpretation as a symbol. Just a number
> from 0 to 255.

There are several things in Ada that correspond to an unsigned byte on a 
byte-oriented machine: Interfaces.Unsigned_8 (ARM B.2), 
System.Storage_Elements.Storage_Element (13.7.1), and Ada.Streams.Stream_Element 
(13.13.1). And, of course, any user-defined type that is "mod 2 ** 8".

Usually you want to read a bunch of these at once. For the most general case of 
that, you read into an Ada.Streams.Stream_Element_Array, using the Read 
operation in Ada.Streams.

-- 
Jeff Carter
"My mind is a raging torrent, flooded with rivulets of
thought, cascading into a waterfall of creative alternatives."
Blazing Saddles
89



^ permalink raw reply	[relevance 4%]

* Re: Address and bit mask
  2011-08-30 15:14  2%       ` Adam Beneschan
@ 2011-08-30 15:59  4%         ` Adam Beneschan
  0 siblings, 0 replies; 200+ results
From: Adam Beneschan @ 2011-08-30 15:59 UTC (permalink / raw)


On Aug 30, 8:14 am, Adam Beneschan <a...@irvine.com> wrote:

>    type Pool_Type is array (Natural range <>) of
>        System.Storage_Elements.Storage_Element;
>    for Pool_Type'Alignment use 2048;

OK, I'm still not used to Ada 2012 aspect clauses, so it would be
better to say

   type Pool_Type is array (Natural range <>) of
      System.Storage_Elements.Storage_Element
      with Alignment => 2048;

if your compiler supports this Ada 2012 feature.

               -- Adam



^ permalink raw reply	[relevance 4%]

* Re: Address and bit mask
  2011-08-30  9:14  4%     ` milouz
                         ` (2 preceding siblings ...)
  2011-08-30 12:35  3%       ` Georg Bauhaus
@ 2011-08-30 15:14  2%       ` Adam Beneschan
  2011-08-30 15:59  4%         ` Adam Beneschan
  3 siblings, 1 reply; 200+ results
From: Adam Beneschan @ 2011-08-30 15:14 UTC (permalink / raw)


On Aug 30, 2:14 am, milouz <a.micheli...@gmail.com> wrote:
> Ok, thank you very much for all your answers, but I'm not really more
> advanced. Let me summarize :
>
> - my question was about address arithmetic (howto ?)
> - Some fellows gave me cues about the use of the
> System.Storage_Elements, but without gaving any concrete example.
> - Some others just wandered about the need of doing address
> arithmetic.
>
> Hum... well... I still do not know how to do some simple arithmetic
> with address. So, let me give you an example in C :
>
>   p = (char*) (((unsigned long)p + ALIGN_MASK) & ~ALIGN_MASK);
>
> How do you write that in Ada ?

It looks like you have a char* and you want to find the address equal
to or greater than p that is a multiple of some alignment.  I can
think of only one application where you would want to do something
like that, so I'll give you some ideas about how to accomplish it.

But first I want to echo what everyone else is saying: asking "How do
I write this C code in Ada" is the WRONG approach.  I can't emphasize
this strongly enough.  The right approach is to ask "What do I want to
accomplish?" or "What is this C code accomplishing?", and then "How do
I accomplish that in Ada?"  Trying to translate C code just does not
work.  I have seen a lot of absolutely horrendous code in Ada written
by programmers who figured out how they would solve their problem in
C, and then tried to do a more-or-less literal translation.  Please,
don't go that way.

Anyway, the case I can think of where you'd want to align a pointer
upward has to do with memory allocation; you have a pool of memory and
want to allocate a chunk of it, but sometimes the chunks have to be
aligned on a certain boundary.  In other words, writing your own
version of malloc().  This is a useful thing to do in Ada, because
once you write your own routines for maintaining the memory pool, you
can use the "storage pools" feature to hook up Ada's access types and
allocator operation to them.  But you still have to write the pool
maintenance routines.

The way I've seen this done is to set up an array of bytes (storage
elements):

   type Pool_Type is array (Natural range <>) of
System.Storage_Elements.Storage_Element;
   for Pool_Type'Alignment use 2048;  -- or whatever the maximum
possible alignment you
                                      -- might need is

   Pool_Size : constant := 100_000;
   Pool : Pool_Type (0 .. Pool_Size - 1);
   subtype Pool_Index is Natural range 0 .. Pool_Size - 1;

Now, instead of doing arithmetic on addresses, you keep variables of
type Pool_Index to refer to the next available location, keep free
lists, etc., and do your alignment arithmetic on those indexes.  When
you need the address of the pool element at a given index, then use
Pool(Index)'Address.  But don't do the arithmetic on the addresses.

This is a very rough outline.  There should be some publicly available
code out there that already does storage pool handling, and I think
some of the other posters on this thread can point you to that.  So if
that's the job you're trying to accomplish, I'd suggest you take a
look at the existing code for this.

If the reason you want to do address arithmetic is something else,
though, you're welcome to ask about it, but rather than giving us C
code with no context and asking us how to translate it, please give us
a bigger-picture description of what you're trying to accomplish and
let us give you ideas about that (like I tried to do with the storage
pool example).

                                 -- Adam







^ permalink raw reply	[relevance 2%]

* Re: Address and bit mask
  2011-08-30 10:34  6%       ` Ludovic Brenta
@ 2011-08-30 14:52  4%         ` Adam Beneschan
  0 siblings, 0 replies; 200+ results
From: Adam Beneschan @ 2011-08-30 14:52 UTC (permalink / raw)


On Aug 30, 3:34 am, Ludovic Brenta <ludo...@ludovic-brenta.org> wrote:

> If the extremely rare case where you really, really must do address
> arithmetic, you still don't need bitwise operations on addresses.  You
> simply use System.Storage_Elements like so:
>
> function Succ (A : in System.Address) return System.Address is
>    Alignment : constant Storage_Offset := 2**3;
>    use System.Storage_Elements;
> begin
>    return (A + Alignment) mod Alignment;
>    -- note: "+" and "mod" are in System.Storage_Elements
> end Increment;

"mod" won't return a System.Address.  (Not to mention that you can't
end a function Succ with "end Increment", but now I'm just being
picky.)

Here's a function that rounds A up to the next multiple of Alignment
(the result could equal A):

 function Align_Up (A : in System.Address) return System.Address is
    Alignment : constant Storage_Offset := 2**3;
    B : System.Address;
    use System.Storage_Elements;
 begin
    B := A + (Alignment - 1);
    return B - (B mod Alignment);
      -- the latter has the effect of zeroing out the low bits of B,
like B & ~ALIGN_MASK
 end Align_Up;

                         -- Adam





^ permalink raw reply	[relevance 4%]

* Re: Address and bit mask
  2011-08-30  9:14  4%     ` milouz
  2011-08-30 10:34  6%       ` Ludovic Brenta
  2011-08-30 10:40  6%       ` Simon Wright
@ 2011-08-30 12:35  3%       ` Georg Bauhaus
  2011-08-30 15:14  2%       ` Adam Beneschan
  3 siblings, 0 replies; 200+ results
From: Georg Bauhaus @ 2011-08-30 12:35 UTC (permalink / raw)


On 30.08.11 11:14, milouz wrote:

> Hum... well... I still do not know how to do some simple arithmetic
> with address.

As has been said, addresses are addresses of something.
The "something" which your pointers will refer to can
be addressed, aligned, and laid out very specifically
using the attribute functions and packages mentioned. OTOH...

> So, let me give you an example in C :
>
>   p = (char*) (((unsigned long)p + ALIGN_MASK) & ~ALIGN_MASK);

The only address arithmetic in there is ... I'm not sure,
have you got the parentheses right?

Assuming this from the Linux kernel source:

/*
 * Round up the ptr to an 8-byte boundary.
 */
#define ALIGN_MASK 7
static inline void *align_ptr(void *ptr)
{
        return (void *) (((size_t) (ptr + ALIGN_MASK)) & ~ALIGN_MASK);
}

(Which, incidentally, gives
test.c:8:34: warning: pointer of type �void *� used in arithmetic)

Assuming your program cannot control alignment using 'Alignment,
layout specifications, and offsets etc, as Ludovic has shown.
Cannot perform arithmetic on addresses using this function
from System.Storage_Elements:

        function "+"(Left : Address; Right : Storage_Offset)
          return Address;

Also assuming that you want exactly C's pointer arithmetic,
copying C's rules, relying on void* casts, and not use Ada
facilities for a reason. (Side note: C's pointer arithmetic
and alignment are not defining what's in the hardware, storage
elements are not defined in C WRT size etc; C refers to hardware
and compiler for further reading.  That's somewhat less so in
Ada.)

Then Interfaces.C.Pointers is your friend, for helping with writing
C in Ada, including the necessary C pointer arithmetic functions,
such as

	function "+" (Left : in Pointer;  Right : in ptrdiff_t)
	  return Pointer;

It is also worthwhile searching the compiler docs that state which
type corresponds with C's void* on your platform.  (System.Address
in case of many GNATs.)

If the platform allows direct interpretation of the bits of
a pointer as an Unsigned_N (no composite pointers, for example),
then after Unchecked_Conversion, the bit operations used in
align_ptr above would be those of Unsigned_N (with suitable N),
named "and" and "not".



^ permalink raw reply	[relevance 3%]

* Re: Address and bit mask
  2011-08-30  9:14  4%     ` milouz
  2011-08-30 10:34  6%       ` Ludovic Brenta
@ 2011-08-30 10:40  6%       ` Simon Wright
  2011-08-30 12:35  3%       ` Georg Bauhaus
  2011-08-30 15:14  2%       ` Adam Beneschan
  3 siblings, 0 replies; 200+ results
From: Simon Wright @ 2011-08-30 10:40 UTC (permalink / raw)


milouz <a.michelizza@gmail.com> writes:

> Hum... well... I still do not know how to do some simple arithmetic
> with address. So, let me give you an example in C :
>
>   p = (char*) (((unsigned long)p + ALIGN_MASK) & ~ALIGN_MASK);
>
> How do you write that in Ada ?

Perhaps you could achieve that by using the Alignment attribute?

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

with Ada.Text_IO;
With System.Storage_Elements;
procedure Alignment is

   type Aligned_Char is new Character;
   for Aligned_Char'Alignment use 16#1000#;
   type Character_P is access Character;
   type Aligned_Char_P is access Aligned_Char;
   C : constant Character_P := new Character'('c');
   A : constant Aligned_Char_P := new Aligned_Char'('a');

   package Address_IO
   is new Ada.Text_IO.Modular_IO (System.Storage_Elements.Integer_Address);

begin

   Ada.Text_IO.Put ("Address of allocated Character:");
   Address_IO.Put (System.Storage_Elements.To_Integer (C.all'Address),
                   Base => 16);
   Ada.Text_IO.New_Line;

   Ada.Text_IO.Put ("Address of allocated Character:");
   Address_IO.Put (System.Storage_Elements.To_Integer (A.all'Address),
                   Base => 16);
   Ada.Text_IO.New_Line;

end Alignment;

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

gnatmake -gnatwa alignment.adb
gcc -c -gnatwa alignment.adb
alignment.adb:6:35: warning: suspiciously large alignment specified for "Aligned_Char"
gnatbind -x alignment.ali
gnatlink alignment.ali

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

$ ~/tmp/alignment 
Address of allocated Character:           16#1092008F0#
Address of allocated Aligned_Char:     16#7F9164001000#
$



^ permalink raw reply	[relevance 6%]

* Re: Address and bit mask
  2011-08-30  9:14  4%     ` milouz
@ 2011-08-30 10:34  6%       ` Ludovic Brenta
  2011-08-30 14:52  4%         ` Adam Beneschan
  2011-08-30 10:40  6%       ` Simon Wright
                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 200+ results
From: Ludovic Brenta @ 2011-08-30 10:34 UTC (permalink / raw)


milouz wrote on comp.lang.ada:
> Ok, thank you very much for all your answers, but I'm not really more
> advanced. Let me summarize :
>
> - my question was about address arithmetic (howto ?)
> - Some fellows gave me cues about the use of the
> System.Storage_Elements, but without gaving any concrete example.
> - Some others just wandered about the need of doing address
> arithmetic.
>
> Hum... well... I still do not know how to do some simple arithmetic
> with address. So, let me give you an example in C :
>
>   p = (char*) (((unsigned long)p + ALIGN_MASK) & ~ALIGN_MASK);
>
> How do you write that in Ada ?

You don't.  You declare an array of characters, specify that each
character takes up ALIGN_MASK*Storage_Unit bits and that the array is
aligned on an ALIGN_MASK boundary.  No need for address arithmetic or
bitwise operations.

declare
  Alignment : constant := 2**3; -- bytes
  type P_T is array (Positive range <>) of Character;
  for P_T'Alignment use Alignment; -- storage_elements
  for P_T'Component_Size use Alignment * System.Storage_Unit; -- bits

  P : P_T (1 .. Number_Of_Elements_In_The_Array);
  -- if P starts at a specific address, you say so:
  for P'Address use The_Starting_Address_Of_P;
begin
  for Index in P'Range loop
     P (Index) := Foo;
  end loop;
end;

The above is not strictly equivalent to your C example; it is much
better:
- it says what it does (as opposed to how it does it);
- it has bounds checking on the array such that you cannot read or
write outside the array;
- it allows you to pass the array as a parameter to subprograms, as
opposed to a pointer to the array (worry not, the compiler will pass
by address behind the scenes)

If the extremely rare case where you really, really must do address
arithmetic, you still don't need bitwise operations on addresses.  You
simply use System.Storage_Elements like so:

function Succ (A : in System.Address) return System.Address is
   Alignment : constant Storage_Offset := 2**3;
   use System.Storage_Elements;
begin
   return (A + Alignment) mod Alignment;
   -- note: "+" and "mod" are in System.Storage_Elements
end Increment;

--
Ludovic Brenta.
Our unique strategic thinking inspires the team players.



^ permalink raw reply	[relevance 6%]

* Re: Address and bit mask
  2011-08-29 19:54  4%   ` Adam Beneschan
@ 2011-08-30  9:14  4%     ` milouz
  2011-08-30 10:34  6%       ` Ludovic Brenta
                         ` (3 more replies)
  0 siblings, 4 replies; 200+ results
From: milouz @ 2011-08-30  9:14 UTC (permalink / raw)


Ok, thank you very much for all your answers, but I'm not really more
advanced. Let me summarize :

- my question was about address arithmetic (howto ?)
- Some fellows gave me cues about the use of the
System.Storage_Elements, but without gaving any concrete example.
- Some others just wandered about the need of doing address
arithmetic.

Hum... well... I still do not know how to do some simple arithmetic
with address. So, let me give you an example in C :

  p = (char*) (((unsigned long)p + ALIGN_MASK) & ~ALIGN_MASK);

How do you write that in Ada ?




^ permalink raw reply	[relevance 4%]

* Re: Address and bit mask
  @ 2011-08-29 19:54  4%   ` Adam Beneschan
  2011-08-30  9:14  4%     ` milouz
  0 siblings, 1 reply; 200+ results
From: Adam Beneschan @ 2011-08-29 19:54 UTC (permalink / raw)


On Aug 29, 12:41 pm, Ludovic Brenta <ludo...@ludovic-brenta.org>
wrote:
> milouz writes:
> > How do you make a binary operation (and, or, etc.) in Ada on an
> > Address type in a rather portable way ?
>
> You don't.  Addresses are not portable at all, not even "rather".
>
> I'm curious.  Why do you need bitwise operations on addresses?

The only case that makes to me is checking the low-order N bits (N=2
or 3 or something small like that) to make sure an address meets
certain alignment requirements.  But System.Storage_Elements already
has a "mod" operation that works quite nicely for that.  Perhaps
that's what the OP is looking for...?

                       -- Adam



^ permalink raw reply	[relevance 4%]

* Re: Some idea could be:
  2011-08-29 17:14  6% Some idea could be: Per Sandberg
@ 2011-08-29 19:17  0% ` Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2011-08-29 19:17 UTC (permalink / raw)


On Mon, 29 Aug 2011 19:14:43 +0200, Per Sandberg wrote:

> The whole idea is copied from "System.Storage_Elements".

Integer_Address is not necessarily modular. See 13.7.1(13). Therefore it is
not guaranteed to work. Masking etc should be performed on relative offsets
rather than on absolute addresses or, for that matter, on their integer
equivalents. It is not even required 0 = To_Address (Null_Address).

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



^ permalink raw reply	[relevance 0%]

* Re: Address and bit mask
  2011-08-29 16:33  0%   ` milouz
  2011-08-29 17:47  4%     ` Dmitry A. Kazakov
  2011-08-29 17:54  0%     ` Martin
@ 2011-08-29 18:46  4%     ` tmoran
  2 siblings, 0 replies; 200+ results
From: tmoran @ 2011-08-29 18:46 UTC (permalink / raw)


> As far as I understand, your solution is to convert the address in
> address_integer, manipulating it, and then converting it in address.
> And all that stuff is because Address type is defined as private.
> Am I right ?
>
> > Size/range of addresses are rather target dependent, so I'm curious as
> > to what you wish to make 'portable'?...
>
> I mean a solution that works with the Address type without the need to
> redefine everything.

  "New_Paint_Color := Old_Paint_Color + 3;" makes no sense in general,
though in certain circumstances adding 3 to the numeric representation of
a color may make a great deal of sense.  Similarly, ANDing two addresses
does not in general make any sense, but sometimes ANDing their bitwise
representation may be just the thing.  Ada tries to operate at the level
of abstraction where a color is a color, not a number, and an address is
an address, not a number.  The compiler will catch abstraction level
mismatches.  If you want to do something at a lower abstraction level, you
have to tell the compiler you are changing levels.  That's what
System.Storage_Elements is for.



^ permalink raw reply	[relevance 4%]

* Re: Address and bit mask
  2011-08-29 16:33  0%   ` milouz
  2011-08-29 17:47  4%     ` Dmitry A. Kazakov
@ 2011-08-29 17:54  0%     ` Martin
  2011-08-29 18:46  4%     ` tmoran
  2 siblings, 0 replies; 200+ results
From: Martin @ 2011-08-29 17:54 UTC (permalink / raw)


On Aug 29, 5:33 pm, milouz <a.micheli...@gmail.com> wrote:
> > To start with, check out package System.Storage_Elements. It at least
> > has To_Address/To_Integer subprograms.
>
> As far as I understand, your solution is to convert the address in
> address_integer, manipulating it, and then converting it in address.
> And all that stuff is because Address type is defined as private.
> Am I right ?
>
> > Size/range of addresses are rather target dependent, so I'm curious as
> > to what you wish to make 'portable'?...
>
> I mean a solution that works with the Address type without the need to
> redefine everything.

Maybe, without know what you actually want to do, it's hard to say.

I'd definitely be littering the code that did the manipulation with
all sorts of "pragma Assert"s. Things under System.* are, well, system
specific - the language makes no guarantee about the format of the
integer address (signed or modular?).

Perhaps you 'know' that 32-bit addresses are all you are ever going to
use - so you could Assert that knowledge. It'll come in handy the day
someone else decides to port it to a 64-bit cpu.

-- Martin



^ permalink raw reply	[relevance 0%]

* Re: Address and bit mask
  2011-08-29 16:33  0%   ` milouz
@ 2011-08-29 17:47  4%     ` Dmitry A. Kazakov
  2011-08-29 17:54  0%     ` Martin
  2011-08-29 18:46  4%     ` tmoran
  2 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2011-08-29 17:47 UTC (permalink / raw)


On Mon, 29 Aug 2011 09:33:29 -0700 (PDT), milouz wrote:

>> To start with, check out package System.Storage_Elements. It at least
>> has To_Address/To_Integer subprograms.
> 
> As far as I understand, your solution is to convert the address in
> address_integer, manipulating it, and then converting it in address.
> And all that stuff is because Address type is defined as private.
> Am I right ?

There is Storage_Offset type in System.Storage_Elements. Address arithmetic
is most likely to be done on the offsets to some definite address, for
example, alignment computations. Bit-wise operations are either meaningless
or machine-specific.

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



^ permalink raw reply	[relevance 4%]

* Some idea could be:
@ 2011-08-29 17:14  6% Per Sandberg
  2011-08-29 19:17  0% ` Dmitry A. Kazakov
  0 siblings, 1 reply; 200+ results
From: Per Sandberg @ 2011-08-29 17:14 UTC (permalink / raw)


The whole idea is copied from "System.Storage_Elements".
/P

---------------------------------------------------------
with System; use System;
with System.Storage_Elements; use System.Storage_Elements;
package ops is
    function "and" (Left  : Address;
                    Right : Address) return Address;
    pragma Convention (Intrinsic, "and");
    pragma Inline_Always ("and");
    pragma Pure_Function ("and");

    function "or" (Left  : Address;
                   Right : Address) return Address;
    pragma Convention (Intrinsic, "or");
    pragma Inline_Always ("or");
    pragma Pure_Function ("or");


    function "xor" (Left  : Address;
                    Right : Address) return Address;
    pragma Convention (Intrinsic, "xor");
    pragma Inline_Always ("xor");
    pragma Pure_Function ("xor");

    function "xor"
      (Left  : Address;
       Right : Integer_Address) return Address;
    pragma Convention (Intrinsic, "xor");
    pragma Inline_Always ("xor");
    pragma Pure_Function ("xor");

    function "xor"
      (Left  : Integer_Address;
       Right : Address) return Address;

    pragma Convention (Intrinsic, "xor");
    pragma Inline_Always ("xor");
    pragma Pure_Function ("xor");

end ops;

-----------------------------------------------------
package body ops is

    function "and"
      (Left  : Address;
       Right : Address)
       return Address
    is
    begin
       return To_Address (To_Integer (Left) and To_Integer (Right));
    end "and";


    function "or"
      (Left  : Address;
       Right : Address)
       return Address
    is
    begin
       return To_Address (To_Integer (Left) or To_Integer (Right));
    end "or";


    function "xor"
      (Left  : Address;
       Right : Address)
       return Address
    is
    begin
       return To_Address (To_Integer (Left) xor To_Integer (Right));
    end "xor";

    function "xor"
      (Left  : Address;
       Right : Integer_Address) return Address is
    begin
       return To_Address (To_Integer (Left) xor Right);
    end "xor";

    function "xor"
      (Left  : Integer_Address;
       Right : Address) return Address is
    begin
       return To_Address (Left xor To_Integer (Right));
    end "xor";
end ops;
------------------------------------------------------------
with ops; use ops;
with System.Storage_Elements; use System.Storage_Elements;
procedure My_Address_Ops_Demo is
    a1 : System.Address;
    a2 : System.Address;
    a3 : System.Address;
    pragma Unreferenced (a3);
begin
    a1 := a2'Address;
    a2 := a1'Address;
    a3 := 2#0000_0000_1111_1111# xor a2;
end My_Address_Ops_Demo;
-----------------------------------------------------------



^ permalink raw reply	[relevance 6%]

* Re: Address and bit mask
  2011-08-29 16:06  4% ` Martin
@ 2011-08-29 16:33  0%   ` milouz
  2011-08-29 17:47  4%     ` Dmitry A. Kazakov
                       ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: milouz @ 2011-08-29 16:33 UTC (permalink / raw)



> To start with, check out package System.Storage_Elements. It at least
> has To_Address/To_Integer subprograms.

As far as I understand, your solution is to convert the address in
address_integer, manipulating it, and then converting it in address.
And all that stuff is because Address type is defined as private.
Am I right ?

> Size/range of addresses are rather target dependent, so I'm curious as
> to what you wish to make 'portable'?...

I mean a solution that works with the Address type without the need to
redefine everything.



^ permalink raw reply	[relevance 0%]

* Re: Address and bit mask
  @ 2011-08-29 16:06  4% ` Martin
  2011-08-29 16:33  0%   ` milouz
    1 sibling, 1 reply; 200+ results
From: Martin @ 2011-08-29 16:06 UTC (permalink / raw)


On Aug 29, 4:46 pm, milouz <a.micheli...@gmail.com> wrote:
> How do you make a binary operation (and, or, etc.) in Ada on an
> Address type in a rather portable way ?

To start with, check out package System.Storage_Elements. It at least
has To_Address/To_Integer subprograms.

Size/range of addresses are rather target dependent, so I'm curious as
to what you wish to make 'portable'?...

-- Martin



^ permalink raw reply	[relevance 4%]

* Re: using `use' : what is the best practice ?
  2011-06-07 15:32  6% using `use' : what is the best practice ? milouz
                   ` (2 preceding siblings ...)
  2011-06-08  6:06  4% ` stefan-lucks
@ 2011-06-15  2:25  5% ` Adrian Hoe
  3 siblings, 0 replies; 200+ results
From: Adrian Hoe @ 2011-06-15  2:25 UTC (permalink / raw)


On Jun 7, 11:32 pm, milouz <a.micheli...@gmail.com> wrote:
> Hi guys,
> Sorry with my annoying questions, but it's not easy to program in Ada
> after 20 years programming in asm / C ;-)
>
> Maybe a not so anecdotic question : when using the 'use' clause ?
>
> My first thought is that using 'use' is not good because it masks the
> package tree.
> For example, if I have 2 packages with procedures sharing the same
> name, example `P1.Foo' and `P2.Foo', my code won't be very readable if
> I only write the short name (`Foo') :
>
>    with P1; use P1;
>    with P2; use P2;
>
>    procedure Main is
>       My_Val : Integer;
>    begin
>       Foo(My_Val);  -- P1 or P2 ?
>    ...

I "use" packages when I need to "use" its type and many calls to
subprograms in it to avoid lengthy code.

You can always explicitly write:

         P1.Foo ( My_Val );
         P2.F00 ( My_Val );

The beauty of Ada is that it is not only an implementation language,
it is also a documentation language.


> But always avoiding 'use' give some rather obfuscated code, especially
> when using some specific arithmetic operator. For example, playing
> with Address arithmetic without 'use' :
>
>    with System;
>    with System.Storage_Elements;
>
>    procedure Main is
>       A : System.Address;
>       N : Integer;
>    begin
>       A := System.Storage_Elements.To_Address(16#10000#);
>       N := 4;
>
> System.Storage_Elements."+"(System.Storage_Elements.Storage_Offset(N),
> A);
>    end Main;
>
> The same code with 'use' is more readable :
>
>    with System; use System;
>    with System.Storage_Elements; use System.Storage_Elements;
>
>    procedure Main is
>       A : Address;
>       N : Integer;
>    begin
>       A := To_Address(16#10000#);
>       N := 4;
>       A := A + Storage_Offset(N);
>    end Main;


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

procedure Main is
   A : System.Address;
   ...

This will be more readable though, IMO.


--
Adrian Hoe
http://adrianhoe.com/adrianhoe



^ permalink raw reply	[relevance 5%]

* Re: using `use' : what is the best practice ?
  2011-06-07 15:32  6% using `use' : what is the best practice ? milouz
  2011-06-07 15:59  3% ` Simon Wright
  2011-06-07 19:32  0% ` Anders Wirzenius
@ 2011-06-08  6:06  4% ` stefan-lucks
  2011-06-15  2:25  5% ` Adrian Hoe
  3 siblings, 0 replies; 200+ results
From: stefan-lucks @ 2011-06-08  6:06 UTC (permalink / raw)


On Tue, 7 Jun 2011, milouz wrote:

> Maybe a not so anecdotic question : when using the 'use' clause ?

I am sure you will get a lot of different answers about this. 

Note that your example below is using "use" in the "context clause" (i.e., 
where the "with" is). 

>    with P1; use P1;
>    with P2; use P2;
> 
>    procedure Main is
>       My_Val : Integer;
>    begin
>       Foo(My_Val);  -- P1 or P2 ?
>    ...

Try out what your program does! If P1 defines 
  procedure Foo(I: Integer); 
and P2 defines only, say, 
  Procedure Foo(S: String);
then the Ada compiler will know that you are calling P1.Foo. You are 
allowed to write P1.Foo(My_Val) to improve the readability of your code. 

On the other hand, if P2 also defines 
  procedure Foo(I: Integer);
you *must* either write P1.Foo(My_Val) or P2.Foo(My_Val). The compiler 
will not try to "guess" which Foo you wanted to call, it will just give 
you the syntax error you deserve. 

> But always avoiding 'use' give some rather obfuscated code, especially
> when using some specific arithmetic operator. For example, playing
> with Address arithmetic without 'use' :

There are alternatives to the use in the syntax clause:
  -> use type;
  -> a renames clause 
  -> a local use 

>    with System;
>    with System.Storage_Elements;
> 
>    procedure Main is
>       A : System.Address;
>       N : Integer;

        use System.Storage_Elements;
        -- locally in any scope -- not very local if in the main procedure
 
        use type System.Address;
        -- alternative: use type

        package SSE renames System.Storage_Elements;
        -- alternative: renames

>    begin
>       A := System.Storage_Elements.To_Address(16#10000#);

        -- A := To_Address(...); -- for local use (or in context clause)
                                 -- but not for use type!

        -- A := SSE.To_Address(...); -- for renames

>       N := 4;
>  
> A := System.Storage_Elements."+"(System.Storage_Elements.Storage_Offset(N), A);

  -- A := SSE."+"(SSE.Storage_Offset(N), A); -- for renames

  -- A := Storage_Offset(N)+ A; -- for local use, context-clause use 
                                -- and use type

>    end Main;
> 
> As I'm very new, I'd like to have your opinion about the way to use
> 'use'.

Always consider the alternatives to the context-clause use!


-- 
------ Stefan Lucks   --  Bauhaus-University Weimar  --   Germany  ------
               Stefan dot Lucks at uni minus weimar dot de
------  I  love  the  taste  of  Cryptanalysis  in  the  morning!  ------



^ permalink raw reply	[relevance 4%]

* Re: using `use' : what is the best practice ?
  2011-06-07 15:32  6% using `use' : what is the best practice ? milouz
  2011-06-07 15:59  3% ` Simon Wright
@ 2011-06-07 19:32  0% ` Anders Wirzenius
  2011-06-08  6:06  4% ` stefan-lucks
  2011-06-15  2:25  5% ` Adrian Hoe
  3 siblings, 0 replies; 200+ results
From: Anders Wirzenius @ 2011-06-07 19:32 UTC (permalink / raw)


milouz <a.michelizza@gmail.com> writes:

> Hi guys,
> Sorry with my annoying questions, but it's not easy to program in Ada
> after 20 years programming in asm / C ;-)
>
> Maybe a not so anecdotic question : when using the 'use' clause ?
>
> My first thought is that using 'use' is not good because it masks the
> package tree.
> For example, if I have 2 packages with procedures sharing the same
> name, example `P1.Foo' and `P2.Foo', my code won't be very readable if
> I only write the short name (`Foo') :
>
>    with P1; use P1;
>    with P2; use P2;
>
>    procedure Main is
>       My_Val : Integer;
>    begin
>       Foo(My_Val);  -- P1 or P2 ?
>    ...
>
> But always avoiding 'use' give some rather obfuscated code, especially
> when using some specific arithmetic operator. For example, playing
> with Address arithmetic without 'use' :
>
>    with System;
>    with System.Storage_Elements;
>
>    procedure Main is
>       A : System.Address;
>       N : Integer;
>    begin
>       A := System.Storage_Elements.To_Address(16#10000#);
>       N := 4;
>  
> System.Storage_Elements."+"(System.Storage_Elements.Storage_Offset(N),
> A);
>    end Main;
>
> The same code with 'use' is more readable :
>
>    with System; use System;
>    with System.Storage_Elements; use System.Storage_Elements;
>
>    procedure Main is
>       A : Address;
>       N : Integer;
>    begin
>       A := To_Address(16#10000#);
>       N := 4;
>       A := A + Storage_Offset(N);
>    end Main;
>
> As I'm very new, I'd like to have your opinion about the way to use
> 'use'.
>
>
>

You may restrict the context of a 'use':

with Text_IO;
procedure Bl is
   A : String := "aaa";
begin
   Text_IO.Put_Line (A);
   declare
      use Text_IO;
      A : character := 'b';
   begin
      Put (A);
   end;
   Put_Line (A);
end;

Try to compile the code. The error message (Gnat) will be:

gnatmake bl.adb 
gcc-4.4 -c bl.adb
bl.adb:12:04: "Put_Line" is not visible
bl.adb:12:04: non-visible declaration at a-textio.ads:263
bl.adb:12:04: non-visible declaration at a-textio.ads:259
gnatmake: "bl.adb" compilation error

-- 
Anders



^ permalink raw reply	[relevance 0%]

* Re: using `use' : what is the best practice ?
  2011-06-07 15:32  6% using `use' : what is the best practice ? milouz
@ 2011-06-07 15:59  3% ` Simon Wright
  2011-06-07 19:32  0% ` Anders Wirzenius
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 200+ results
From: Simon Wright @ 2011-06-07 15:59 UTC (permalink / raw)


milouz <a.michelizza@gmail.com> writes:

> Hi guys,

> Maybe a not so anecdotic question : when using the 'use' clause ?
>
> My first thought is that using 'use' is not good because it masks the
> package tree.

100% agree.

Well, actually more like 90%! I have no problem writing

   with Ada.Text_IO; use Ada.Text_IO;

(but, I'd most often be using Text_IO for debug trace output, not in
operational code).

And some packages (Ada.Strings.Unbounded) are designed to be "use"d.

AdaCore tend to use package renaming, eg

   package SSE renames System.Storage_Elements;

> For example, if I have 2 packages with procedures sharing the same
> name, example `P1.Foo' and `P2.Foo', my code won't be very readable if
> I only write the short name (`Foo') :
>
>    with P1; use P1;
>    with P2; use P2;
>
>    procedure Main is
>       My_Val : Integer;
>    begin
>       Foo(My_Val);  -- P1 or P2 ?

And would not even compile, if both packages contained a procedure Foo.

> But always avoiding 'use' give some rather obfuscated code, especially
> when using some specific arithmetic operator. For example, playing
> with Address arithmetic without 'use' :
> System.Storage_Elements."+"(System.Storage_Elements.Storage_Offset(N),
> A);

See "use type", designed for exactly this purpose.

http://www.adaic.org/resources/add_content/standards/05rm/html/RM-8-4.html#I3407

Although you can "use type" in the context clauses (the "with"s) I much
prefer to put them as close as possible to the actual use: eg, in the
declarative region of a subprogram.

Of course, if all the subprograms in a package need to "use type", move
the "use type" to package scope.



^ permalink raw reply	[relevance 3%]

* using `use' : what is the best practice ?
@ 2011-06-07 15:32  6% milouz
  2011-06-07 15:59  3% ` Simon Wright
                   ` (3 more replies)
  0 siblings, 4 replies; 200+ results
From: milouz @ 2011-06-07 15:32 UTC (permalink / raw)


Hi guys,
Sorry with my annoying questions, but it's not easy to program in Ada
after 20 years programming in asm / C ;-)

Maybe a not so anecdotic question : when using the 'use' clause ?

My first thought is that using 'use' is not good because it masks the
package tree.
For example, if I have 2 packages with procedures sharing the same
name, example `P1.Foo' and `P2.Foo', my code won't be very readable if
I only write the short name (`Foo') :

   with P1; use P1;
   with P2; use P2;

   procedure Main is
      My_Val : Integer;
   begin
      Foo(My_Val);  -- P1 or P2 ?
   ...

But always avoiding 'use' give some rather obfuscated code, especially
when using some specific arithmetic operator. For example, playing
with Address arithmetic without 'use' :

   with System;
   with System.Storage_Elements;

   procedure Main is
      A : System.Address;
      N : Integer;
   begin
      A := System.Storage_Elements.To_Address(16#10000#);
      N := 4;
 
System.Storage_Elements."+"(System.Storage_Elements.Storage_Offset(N),
A);
   end Main;

The same code with 'use' is more readable :

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

   procedure Main is
      A : Address;
      N : Integer;
   begin
      A := To_Address(16#10000#);
      N := 4;
      A := A + Storage_Offset(N);
   end Main;

As I'm very new, I'd like to have your opinion about the way to use
'use'.






^ permalink raw reply	[relevance 6%]

* Re: How do I write directly to a memory address?
  @ 2011-02-12  8:02  6%   ` Niklas Holsti
  0 siblings, 0 replies; 200+ results
From: Niklas Holsti @ 2011-02-12  8:02 UTC (permalink / raw)


Edward Fish wrote:
> On Feb 2, 10:52 pm, Syntax Issues <syntax.iss...@gmail.com> wrote:
>> I am planning to start learning lower-level programming with ada,
>> however, I was unable to find a solid tutorial on writing directly to
>> a memory address or interfacing with assembly. Does anyone know where
>> I can find a reference to some tutorials/information? Below is an
>> example of code I would like to be able to implement.
>>
> 
> As others have replied using the 'Address attribute on a constrained
> array of your video's cell-type {attribute-character pair}is the
> way to go.
> 
> But if you're using GNAT you may have noticed that it doesn't allow
> a straight "For Data'Address Use 16#000B_8000#;" because GNAT
> uses a private type and not a derivative of Universal_Integer.

That is correct, and it need not work on any compiler, because 
System.Address is an implementation-defined type. You should in effect 
consider it a private type.

> They recommend an implementation-dependent "to_Address" function,
> but that would make things non-portable.

As others have said earlier in this thread (before the language war) 
there is a standard conversion function in the package 
System.Storage_Elements: the function System.Storage_Elements.To_Address 
converts from the integer type System.Storage_Elements.Integer_Address 
to System.Address.

Perhaps this is the function that AdaCore meant? The function and its 
usage are standard. (The implementation of the function is of course 
implementation-dependent, as it should be.)

> After some thought and some fiddling here's a portable,
> insofar as I know, method to convert an integer literal
> or constant (or even variable) to an address containing
> that value.

Your method may work on some systems, but it is not portable, because it 
assumes that System.Address has the same size and the same internal 
representation as your integer type Address_Overlay.Address_Integer, 
which does not follow from the language standard.

The functions System.Storage_Elements.To_Address/To_Integer translate 
between the internal representations if they are different.

In your method, the overlay of an Address_Integer with a System.Address 
is the same as an Unchecked_Conversion (which would be a simpler way to 
implement the same, wrong, method).

By your method (or by Unchecked_Conversion) you can indeed make a 
System.Address that "contains" the given integer value, in the sense of 
containing the same bit pattern, but this bit pattern may not be the 
Address that you want.

> -- Address_Overlay.ads; Pragma pure may be added.
> With System;
> Package Address_Overlay is
> 
>    Type Address_Integer is Range 0..System.Memory_Size;
> 
> Private
> End Address_Overlay;
> 
> -----  Address_Overlay.This.ads; an instantiation of
> -----                             this provides the proper overlay
> Generic
>    Value : Address_Integer;
> Package Address_Overlay.This is
> 
>    Address : Constant System.Address;		-- Overlay Address with Value.
> 
> Private
>   Pragma Warnings (Off, "*overlay*");		-- Here we turn off the warning
>    For Address'Address Use Value'Address;	-- about a constant
> overlaying
>    Pragma Import( Ada, Address );		-- a variable; as that is our
>   Pragma Warnings (On, "*overlay*");		-- intention.
> End Address_Overlay.This;
> 
> -----------
> -- USAGE --
> -----------
>    Declare
>       Package An_Address( 16#000C_8000#  );
> 
>       Data : Integer;
>       For Data'Address Use An_Address.Address;
>    Begin
> 	Data:= 4;
>    End;

Here is an example of the use of System.Storage_Elements and its 
Integer_Address type and functions:

-- begin example

with System.Storage_Elements;
with Ada.Text_IO;

procedure ItoA is

    use Ada.Text_IO;
    use System;

    Value : aliased Float := 1.2345;
    -- A variable that we will modify through an overlay,
    -- just to show that we can do it.

    Value_Int_Address : constant Storage_Elements.Integer_Address :=
       Storage_Elements.To_Integer (Value'Address);
    -- The address of Value, as an integer.

    Value_Address : constant Address :=
       Storage_Elements.To_Address (Value_Int_Address);
    -- The address of Value, converted back from its integer form.

    Other_Value : Float;
    for Other_Value'Address use Value_Address;
    -- Other_Value now overlays Value.

begin

    Put_Line ("Value'Address as integer ="
       & Storage_Elements.Integer_Address'Image (Value_Int_Address));

    Put_Line ("Value originally =" & Float'Image (Value));

    Other_Value := 9.8765;

    Put_Line ("Value changed via Other_Value =" & Float'Image (Value));

end ItoA;

-- end example


So the OP should use System.Storage_Elements.To_Address (16#000B_8000#) 
to compute the address (if that number is indeed the right one to use).

It is conceivable that the implementations of System.Storage_Elements in 
two different Ada compilers for the same target system could have 
different interpretations of the Integer_Address type and thus different 
mappings from Integer_Address to System.Address. For example, if the 
target system is only addressable in units of 16-bit words, one compiler 
could choose to use "16-bit word" as the unit of Integer_Address and 
another compiler could choose to use "8-bit octet". For the latter 
compiler, only even values of Integer_Address would be valid. (There are 
some 16-bit processors where different C compilers differ in this way, 
in the addresses that they display in listings and symbol tables.)

For octet-addressable processors Integer_Address in any Ada compiler is 
almost sure to use octet units, so values of Integer_Address should be 
portable across compilers.

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



^ permalink raw reply	[relevance 6%]

* Re: How do I write directly to a memory address?
  @ 2011-02-03 18:07  4% ` 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 4%]

* 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: Beginners question: Compound types, how-to?
  2010-11-03 17:42  0%                 ` Vinzent Hoefler
@ 2010-11-04  5:23  0%                   ` Stephen Leake
  0 siblings, 0 replies; 200+ results
From: Stephen Leake @ 2010-11-04  5:23 UTC (permalink / raw)


"Vinzent Hoefler" <nntp-2010-10@t-domaingrabbing.de> writes:

> On Wed, 03 Nov 2010 18:01:55 +0100, Georg Bauhaus <rm.dash-bauhaus@futureapps.de> wrote:
>
>> On 03.11.10 17:56, Warren wrote:
>>
>>> There is a good practical case for _Type, IMO. If Buffer_Type is defined
>>> simply as Buffer, then we develop an inconvenient name clash:
>>>
>>>>     subtype Buffer is
>>>>        System.Storage_Elements.Storage_Array (1..Buffer_Size);
>>>
>>> In use now:
>>>
>>> declare
>>>    Buffer : Buffer;   -- hmmmm
>>> begin
>>
>> What role does the object named Buffer play?
>>
>> It is a buffer, yes. Is it different from other buffers?
>
> I now own it, thus it's "My_Buffer", of course. ;)
>
>> How?  What lives in it?  How does the program use it?
>>
>> I believe answering these questions leads to a better name.
>
> Yes, things like "Message_Buffer" are usually better here. Even a
> generic name like "Read_Buffer" could help somewhat.

Notice that the "find a better name" camp always suggests _several_
names, and each person suggests _different_ ones. That means there is no
common solution, and the resulting code will be confusing, and subject
to endless arguments about "the right name" in code reviews.

At least with _Type, the solution is very clear.

So it takes less time to write good code using the _Type convention :).

(Ok, it's late, and I'm tired, and this is more fun than real work :)

-- 
-- Stephe



^ permalink raw reply	[relevance 0%]

* Re: Beginners question: Compound types, how-to?
  2010-11-03 20:38  0%                 ` Warren
@ 2010-11-03 22:32  0%                   ` Georg Bauhaus
  0 siblings, 0 replies; 200+ results
From: Georg Bauhaus @ 2010-11-03 22:32 UTC (permalink / raw)


On 11/3/10 9:38 PM, Warren wrote:
> Georg Bauhaus expounded in
> news:4cd19583$0$6977$9b4e6d93@newsspool4.arcor-online.net:
>
>> On 03.11.10 17:56, Warren wrote:
>>
>>> There is a good practical case for _Type, IMO. If Buffer_Type is
>>> defined simply as Buffer, then we develop an inconvenient name clash:
>>>
>>>>      subtype Buffer is
>>>>         System.Storage_Elements.Storage_Array (1..Buffer_Size);
>>>
>>> In use now:
>>>
>>> declare
>>>     Buffer : Buffer;   -- hmmmm
>>> begin
>>
>> What role does the object named Buffer play?
>>
>> It is a buffer, yes. Is it different from other buffers?
>> How?  What lives in it?  How does the program use it?
>>
>> I believe answering these questions leads to a better name.
>
> Ok, so the type is a Storage_Buffer. So is the instance
> of the type.

Actually, the type is not a Storage_Buffer.  The type has no
"is a" relation to Storage_Buffer, the type defines what
instances of Storage_Buffers are going to be like. Each object
"is a"  Storage_Buffer. A type is not.   OK, that's nitpicking.

A child born is of type Child.  A son is of type Son.  Sometimes
fathers address the Child: "Son, ...!"  But the son still
has a name.  If you have another son, maybe younger, you
know how to tell them apart.  And if there are two or more
around, "Son, ...!" may not work as intended.So they've got
names, to resolve the issue.  Suppose there
is just one.  Should computer programming therefore dismiss
assigning single sons a name and just name them "Son"?

In natural language, "Son, ..." may be a special form
of address.  Something out of the ordinary.  This meaning
is not covered by the *type* Son.  Maybe our overloading
of meanings of Son lets us think we might use the same naming
scheme in formal programming, if *we* know there is one
particular Son object around and we write the statements
addressing it.  Doesn't seem like a good idea to me to carry
this over to formal programming.

The Romans just counted sons, Primus, ..., Quintus, say.
Every son "is a" Son, but none of them were without identity
and none was *named* son!   Just *called*, at times, and
in special situations where ambiguity is resolved by human
means, not by a compiler.

Therefore, then, do we do ourselves a favor if we use  this
style of anonymity by duplicating the type name for objects?
For example, "Tu quoque, fili?" can be clarified in programming
by just injecting the name Brute, for an object of type Son.
As in

package body Caesar

  procedure Last_Words is
  begin
     Say ("To quoque, Brute, fili mi?")
  end Last_Words;

end Caesar;

I guess that for insiders, the phrase might not be catchy enough.
Too long. But for a more formal analysis, the specific object is nicely
spelled out (Brute), and the relation is clear, too (mi): Brutus,
that's the son's name, is Caesar's son (fili mi), not just someone's
son (fili) as a computer could infer, absent a possessive pronoun.

Suppose the string had just been "To quoque, fili", without Brute and
without mi.  The program's author sure had known better.

He had known the name but decided not to give it.
Why not?


> Storage_Buffer : Storage_Buffer;
>
> doesn't get us any closer to solving the problem. ;-)
>
> Sometimes the number of instances is one -- matching the
> type.  In cases like these you are still left with the
> task of making them different-- merely for the purpose
> making them different.

I still think that not having a object name based on the object's
role, say,  shows that you have not yet clearly named the purpose
of this object in the program.   Sometimes that's enough.
I think, however, that quick and dirty anonymity characterizes
programs that need but a limited amount of engineering.




^ permalink raw reply	[relevance 0%]

* Re: Beginners question: Compound types, how-to?
  2010-11-03 17:01  0%               ` Georg Bauhaus
  2010-11-03 17:42  0%                 ` Vinzent Hoefler
  2010-11-03 20:38  0%                 ` Warren
@ 2010-11-03 20:44  0%                 ` Yannick Duchêne (Hibou57)
  2 siblings, 0 replies; 200+ results
From: Yannick Duchêne (Hibou57) @ 2010-11-03 20:44 UTC (permalink / raw)


Le Wed, 03 Nov 2010 18:01:55 +0100, Georg Bauhaus  
<rm.dash-bauhaus@futureapps.de> a écrit:

> On 03.11.10 17:56, Warren wrote:
>
>> There is a good practical case for _Type, IMO. If Buffer_Type is defined
>> simply as Buffer, then we develop an inconvenient name clash:
>>
>>>     subtype Buffer is
>>>        System.Storage_Elements.Storage_Array (1..Buffer_Size);
>>
>> In use now:
>>
>> declare
>>    Buffer : Buffer;   -- hmmmm
>> begin
>
> What role does the object named Buffer play?
>
> It is a buffer, yes. Is it different from other buffers?
> How?  What lives in it?  How does the program use it?
>
> I believe answering these questions leads to a better name.

Please, read all, up to the end (I am not totally contracting what I reply  
to, that is all about covering all cases).

It may be any Buffer : it is variable, not a constant (the buffer is not  
the better example here, but let go on with here)

Practical view : this buffer may (let imagine) be used consecutively for  
different things, and the analysis may say this is OK to have one buffer  
because of use always comes after the other (and the buffer may be big so  
we have to declare only one, to reach some specifications).

Abstract view : a Buffer_Type defines something. Right ? Now, what is a  
variable declared of type Buffer ? It is what is defined by the type  
Buffer, right ? (if this would be something different, then language or  
the compiler is really broken). Then, if you've named Buffer as Buffer,  
how will you name a variable of the same type without more (see later for  
the more) ? Use a different name ? But if you use a different name,  
doesn't that mean the name of the type could be different or is ambiguous  
? The good word to say what the type is, will be the same to say what the  
variable is (but there is one difference, see later).

First part of my agreement : I fully agree with the point “what is special  
with that buffer ?”. Ex. you have two buffers, one for input, one for  
output : “Input_Buffer : Buffer; Output_Buffer : Buffer;”. That sounds  
natural, OK. But some other times this is not feasible, because the entity  
declared of the type is simply fully generic (you can give it a tricky  
name, which will not sound natural, as the natural word is the one of the  
type, or else, the type does not hold the good name or holds an ambiguous  
name).

About the more : think about an inventory machine in a library, it has a  
method named Run_Inventory, and inside this, a loop and a book variable.  
This book has nothing special at all, as it is by definition, to hold any  
what book you may imagine. This variable, here, is, simply what the Book  
type, is. So your question is indeed very good : what is different ? The  
answer : one is a type, the other is an instance  So how do you name it ?  
With a name which expose the difference
  Either Book_Instance and Book or
else Book and Book_Type or even, if you like it Book_Instance and  
Book_Type. Book_Instance is the place for different name : A_Book,  
Any_Book, Current_Book, etc. What ever, you will add to the instance name,  
something which you reject for the type name (paradox ?).


Sometime it is possible to get ride of _Type, but sometime it is not  
always, and this is not predictable, and your design should cover the  
“always” otherwise it will hold a bug. If you decide it for the user, this  
is not good : premature decision. You cannot assert the user will never  
define very generic instance of that type (and there are common, see later  
[*]).

Now, how much or what is the average occurrence of generic use instance ?  
I would say, many (near to third or half, my experience says), at least  
with function and procedure parameters (especially when there is a single  
parameter of the same type, which is a common case), iterators, persistent  
storage, streams, intermediate expression, temporary variables, an so on;  
or else, simply the role is indicated by the outer scope and this is  
redundancy to add a mark for it to the variable. About the latter, what  
about “Inventored_Book” or “Current_Book” in the loop of the above  
inventory machine ? Is it worth to repeat it every where ? Does it really  
offers something to the reader ? (think of it in context)


You idea is good, but it does not cover all the range, and you are right,  
sometime, but not all the time. If an entity does not have enough thing  
special, you are not to invent it just to name it (this would not be to  
design anymore), you are to name it for what it is (that is design). And  
what if this has nothing special or else what is special with it, is  
already expressed in the direct outer context or what it is attached to  
(case of records or subprogram parameters) ?


Another alternative for people who do not like _Type and feels hurt with  
it, could be to serve each type declaration, with a name to be used for  
instances-without special identity.

    type Book is private; -- Typical instance name: Set_Of_Written_Sheets.
                          -- Sorry, I do not know a good English synonym.
                          -- Note: some API do something a bit similar, when
                          -- they define common abbreviations for variables
                          -- of a type.


[*] When I read sources which does not use the “_Type” convention (or  
something similar, there are multiple choice, and either on the variable  
or on the type), including some part of the ARM, there are tricky names  
(which are disturbing for the reader) or hard game to find synonyms, which  
makes me wonder what the next will be (funny game) or if the type was  
really given the good name. That is funny in literature to play with  
multiple synonymous of a word or close-meaning words; but although I enjoy  
the concept of Literate Programming, computer language source is not  
literature (the expression Literate Programming is only partly related to  
literature), it is not the same kind of entertainment. When a name does  
not sound natural and like to play the “guess what next” game with you,  
this is not good for readability (the reader has some other priorities).


P.S. For reader of this news-group: this only applies to languages which  
are case insensitive, as as-you know, there is a common convention in  
language with case sensitivity, to use a capital letter (like natural  
language when it needs to distinguish proper names) which plays the same  
role as _Type here.


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



^ permalink raw reply	[relevance 0%]

* Re: Beginners question: Compound types, how-to?
  2010-11-03 17:01  0%               ` Georg Bauhaus
  2010-11-03 17:42  0%                 ` Vinzent Hoefler
@ 2010-11-03 20:38  0%                 ` Warren
  2010-11-03 22:32  0%                   ` Georg Bauhaus
  2010-11-03 20:44  0%                 ` Yannick Duchêne (Hibou57)
  2 siblings, 1 reply; 200+ results
From: Warren @ 2010-11-03 20:38 UTC (permalink / raw)


Georg Bauhaus expounded in
news:4cd19583$0$6977$9b4e6d93@newsspool4.arcor-online.net: 

> On 03.11.10 17:56, Warren wrote:
> 
>> There is a good practical case for _Type, IMO. If Buffer_Type is
>> defined simply as Buffer, then we develop an inconvenient name clash:
>> 
>>>     subtype Buffer is
>>>        System.Storage_Elements.Storage_Array (1..Buffer_Size);
>> 
>> In use now:
>> 
>> declare
>>    Buffer : Buffer;   -- hmmmm
>> begin
> 
> What role does the object named Buffer play?
> 
> It is a buffer, yes. Is it different from other buffers?
> How?  What lives in it?  How does the program use it?
> 
> I believe answering these questions leads to a better name.

Ok, so the type is a Storage_Buffer. So is the instance
of the type.

Storage_Buffer : Storage_Buffer;

doesn't get us any closer to solving the problem. ;-)

Sometimes the number of instances is one -- matching the
type.  In cases like these you are still left with the 
task of making them different-- merely for the purpose
making them different.

Warren



^ permalink raw reply	[relevance 0%]

* Re: Beginners question: Compound types, how-to?
  2010-11-03 17:01  0%               ` Georg Bauhaus
@ 2010-11-03 17:42  0%                 ` Vinzent Hoefler
  2010-11-04  5:23  0%                   ` Stephen Leake
  2010-11-03 20:38  0%                 ` Warren
  2010-11-03 20:44  0%                 ` Yannick Duchêne (Hibou57)
  2 siblings, 1 reply; 200+ results
From: Vinzent Hoefler @ 2010-11-03 17:42 UTC (permalink / raw)


On Wed, 03 Nov 2010 18:01:55 +0100, Georg Bauhaus <rm.dash-bauhaus@futureapps.de> wrote:

> On 03.11.10 17:56, Warren wrote:
>
>> There is a good practical case for _Type, IMO. If Buffer_Type is defined
>> simply as Buffer, then we develop an inconvenient name clash:
>>
>>>     subtype Buffer is
>>>        System.Storage_Elements.Storage_Array (1..Buffer_Size);
>>
>> In use now:
>>
>> declare
>>    Buffer : Buffer;   -- hmmmm
>> begin
>
> What role does the object named Buffer play?
>
> It is a buffer, yes. Is it different from other buffers?

I now own it, thus it's "My_Buffer", of course. ;)

> How?  What lives in it?  How does the program use it?
>
> I believe answering these questions leads to a better name.

Yes, things like "Message_Buffer" are usually better here. Even a
generic name like "Read_Buffer" could help somewhat.


Vinzent.

-- 
There is no signature.



^ permalink raw reply	[relevance 0%]

* Re: Beginners question: Compound types, how-to?
  2010-11-03 16:56  0%             ` Warren
@ 2010-11-03 17:01  0%               ` Georg Bauhaus
  2010-11-03 17:42  0%                 ` Vinzent Hoefler
                                   ` (2 more replies)
  0 siblings, 3 replies; 200+ results
From: Georg Bauhaus @ 2010-11-03 17:01 UTC (permalink / raw)


On 03.11.10 17:56, Warren wrote:

> There is a good practical case for _Type, IMO. If Buffer_Type is defined 
> simply as Buffer, then we develop an inconvenient name clash:
> 
>>     subtype Buffer is
>>        System.Storage_Elements.Storage_Array (1..Buffer_Size);
> 
> In use now:
> 
> declare
>    Buffer : Buffer;   -- hmmmm
> begin

What role does the object named Buffer play?

It is a buffer, yes. Is it different from other buffers?
How?  What lives in it?  How does the program use it?

I believe answering these questions leads to a better name.



^ permalink raw reply	[relevance 0%]

* Re: Beginners question: Compound types, how-to?
  2010-11-01 19:41  4%           ` Yannick Duchêne (Hibou57)
  2010-11-01 20:56  0%             ` Jeffrey Carter
@ 2010-11-03 16:56  0%             ` Warren
  2010-11-03 17:01  0%               ` Georg Bauhaus
  1 sibling, 1 reply; 200+ results
From: Warren @ 2010-11-03 16:56 UTC (permalink / raw)


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

=?utf-8?Q?Yannick_Duch=C3=AAne_=28Hibou57?= =?utf-8?Q?=29?= expounded in
news:op.vlibn4shule2fv@garhos: 

> Le Mon, 01 Nov 2010 20:19:51 +0100, Jeffrey Carter  
> <spam.jrcarter.not@spam.not.acm.org> a écrit:
>> No, not nice. Terrible.
>>
>> "_Type" is just noise; you could use "_Global_Nuclear_Warfare" just
>> as 
>   
>> well. You should never be adding unnecessary noise to your code.
> 
> Actually, this convention appears in many places, like the ARM. Ex:
> 
>     subtype Buffer_Type is
>        System.Storage_Elements.Storage_Array (1..Buffer_Size);
> 
> And to talk about good names, you may agree _Global_Nuclear_Warfare
> does  not express the same at all as _Type does. This is even more
> clear if you  have some _Access.
> 
>>
>> S/W engineering involves putting in the effort to think of good names
>  
>> for everything in your code. "_Type" is a kludge to avoid doing that 
>> thinking.

There is a good practical case for _Type, IMO. If Buffer_Type is defined 
simply as Buffer, then we develop an inconvenient name clash:

>     subtype Buffer is
>        System.Storage_Elements.Storage_Array (1..Buffer_Size);

In use now:

declare
   Buffer : Buffer;   -- hmmmm
begin
...

Buffer_Type avoids this difficulty:

declare
   Buffer : Buffer_Type;
begin
...

So while I'd agree that "_Type" is noisy, it is sometimes the right 
choice. If you can devise a better name for the type, like perhaps 
Storage_Buffer, then perhaps that is preferred.

Warren



^ permalink raw reply	[relevance 0%]

* Re: Beginners question: Compound types, how-to?
  2010-11-01 19:41  4%           ` Yannick Duchêne (Hibou57)
@ 2010-11-01 20:56  0%             ` Jeffrey Carter
  2010-11-03 16:56  0%             ` Warren
  1 sibling, 0 replies; 200+ results
From: Jeffrey Carter @ 2010-11-01 20:56 UTC (permalink / raw)


On 11/01/2010 12:41 PM, Yannick Duchêne (Hibou57) wrote:
>
> Actually, this convention appears in many places, like the ARM. Ex:
>
> subtype Buffer_Type is
> System.Storage_Elements.Storage_Array (1..Buffer_Size);

Yes, some parts of the ARM are badly designed.

> And to talk about good names, you may agree _Global_Nuclear_Warfare does
> not express the same at all as _Type does.

And I may not. _Global_Nuclear_Warfare expresses exactly the same thing as 
_Type: nothing.

-- 
Jeff Carter
"Why don't you bore a hole in yourself and let the sap run out?"
Horse Feathers
49



^ permalink raw reply	[relevance 0%]

* Re: Beginners question: Compound types, how-to?
  @ 2010-11-01 19:41  4%           ` Yannick Duchêne (Hibou57)
  2010-11-01 20:56  0%             ` Jeffrey Carter
  2010-11-03 16:56  0%             ` Warren
  0 siblings, 2 replies; 200+ results
From: Yannick Duchêne (Hibou57) @ 2010-11-01 19:41 UTC (permalink / raw)


Le Mon, 01 Nov 2010 20:19:51 +0100, Jeffrey Carter  
<spam.jrcarter.not@spam.not.acm.org> a écrit:
> No, not nice. Terrible.
>
> "_Type" is just noise; you could use "_Global_Nuclear_Warfare" just as  
> well. You should never be adding unnecessary noise to your code.

Actually, this convention appears in many places, like the ARM. Ex:

    subtype Buffer_Type is
       System.Storage_Elements.Storage_Array (1..Buffer_Size);

And to talk about good names, you may agree _Global_Nuclear_Warfare does  
not express the same at all as _Type does. This is even more clear if you  
have some _Access.

>
> S/W engineering involves putting in the effort to think of good names  
> for everything in your code. "_Type" is a kludge to avoid doing that  
> thinking.
Names, roles, behavior, traits, and so on. There are many place where the  
sole surrounding context is not enough.

> In this case, the type defines the information for dealing with a  
> Character, so I'd probably use Character_Info as the type name.
If the design is good, then Character already holds what identifies a  
Character. With OO design, this _Info is then implicit and every where  
(this one, is really noise ;) )


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



^ permalink raw reply	[relevance 4%]

* Life-time of temporaries
@ 2010-10-30 12:03  5% Florian Weimer
  0 siblings, 0 replies; 200+ results
From: Florian Weimer @ 2010-10-30 12:03 UTC (permalink / raw)


Does the following program result in erroneous execution?

with Ada.Text_IO;
with System.Storage_Elements;

procedure T is
   
   type Ref is record
      Address : System.Address;
      Length : System.Storage_Elements.Storage_Count;
   end record;
   
   function "+" (S : String) return Ref is
   begin
      return Ref'(S'Address, S'Length);
   end "+";
   
   procedure Print (R : Ref) is
      subtype String_Type is String (1 .. Integer (R.Length));
      S : String_Type;
      pragma Import (Ada, S);
      for S'Address use R.Address;
   begin
      Ada.Text_IO.Put_Line (S);
   end Print;
   
begin
   Print (+Integer'Image(17));
end T;

It seems to me it doesn't, thanks to the clarification in AI95-162,
although it does not seem to be the main direction of that change.



^ permalink raw reply	[relevance 5%]

* Re: Interfacing C type, unconstrained array with record
  2010-10-16 18:36  5% ` Dmitry A. Kazakov
  2010-10-16 19:19  0%   ` Ron Wills
@ 2010-10-16 21:41  0%   ` Robert A Duff
  1 sibling, 0 replies; 200+ results
From: Robert A Duff @ 2010-10-16 21:41 UTC (permalink / raw)


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

> You need a flat array, e.g.
>
>    with Interfaces;  use Interfaces;
>    with Interfaces.C;  use Interfaces.C;

I'd probably write:

    with Interfaces.C;  use Interfaces;

and then refer to C.int instead of Int.
No big deal.

>    type SDL_Color is record
>       R, G, B, Unused : Unsigned_8;
>    end record;
>    pragma Convention (C, SDL_Color);
>    type SDL_Color_Array is array (Positive) of aliased SDL_Color;

I think you want this indexed by the same type as N_Colors.
And why does it need to have aliased components?
So perhaps:

    type SDL_Color_Array is array (Int range 1..1_000_000) of SDL_Color;

>    pragma Convention (C, SDL_Color_Array);
>    type SDL_Palette is record
>       N_Colors : Int;
>       Colors   : SDL_Color_Array;
>    end record;
>    pragma Convention (C, SDL_Palette);
>
> Now, you cannot directly declare a SDL_Palette variable, because it is too
> large. You should do it as you would do in C, i.e. allocate some amount of
> memory and then set structure pointer to it. You do not need 'new' or
> access types in Ada. It can be on the stack like this:
>
>    with System.Storage_Elements;  use System.Storage_Elements;
>       ...
>    Raw_Memory : Storage_Array (1..1_024); -- Memory
>    Palette    : SDL_Palette;
>    for Palette'Address use Raw_Memory'Address;

I think you need to worry about alignment here.
Perhaps:

    pragma Assert(SDL_Palette'Alignment = C.int'Alignment);
    for Raw_Memory'Alignment use C.int'Alignment;

> begin
>    Palette.N_Colors := 20;
>
> Of course computing memory size from N_Colors is up to you (as in C).

You might want to say:

    Colors: SDL_Color_Array renames Palette.Colors(1..Palette.N_Colors);

and then refer to components of Colors, so you get array bounds checking.

- Bob



^ permalink raw reply	[relevance 0%]

* Re: Interfacing C type, unconstrained array with record
  2010-10-16 18:36  5% ` Dmitry A. Kazakov
@ 2010-10-16 19:19  0%   ` Ron Wills
  2010-10-16 21:41  0%   ` Robert A Duff
  1 sibling, 0 replies; 200+ results
From: Ron Wills @ 2010-10-16 19:19 UTC (permalink / raw)


On Oct 16, 12:36 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> On Sat, 16 Oct 2010 10:35:39 -0700 (PDT), Ron Wills wrote:
> > Hi all
>
> > I've started learning Ada and started porting some software I had in C/
> > C++ as a learning exercise. The software uses SDL, so I started a thin
> > wrapper around it. I've been very successful with it, but with the
> > exception of the palette structure which in C is defined as:
>
> > typedef struct {
> >   int ncolors;
> >   SDL_Color colors[]; // Actually is SDL_Color *colors but this is how
> > it is laid out in memory
> > } SDL_Palette;
>
> > In Ada I'm trying to do something like:
>
> > type SDL_Color is
> >   record
> >     r, g, b, unused : Uint8;
> >   end;
> > type SDL_Color_Array is array(Positive range <>) of Color;
> > type SDL_Palette is
> >   record
> >     ncolors : Integer;
> >     colors : SDL_Color_Array;
> >   end;
>
> > Now Ada (GNAT) won't compile this because the colors component is
> > unconstrained, which is understandable. I've been googling for a
> > couple of days for a way of modeling this in Ada and still having
> > access to all the colors in the colors component. In other SDL
> > interface implementations, all I've seen is that the colors component
> > is made into a type of "Dummy" component and made more or less
> > useless. I've also been combing the reference manual, but nothing I've
> > noticed seems to solve this issue. I'm sure I'm not the only one that
> > has come across this problem and was wondering what solutions are
> > available.
>
> You need a flat array, e.g.
>
>    with Interfaces;  use Interfaces;
>    with Interfaces.C;  use Interfaces.C;
>       ...
>    type SDL_Color is record
>       R, G, B, Unused : Unsigned_8;
>    end record;
>    pragma Convention (C, SDL_Color);
>    type SDL_Color_Array is array (Positive) of aliased SDL_Color;
>    pragma Convention (C, SDL_Color_Array);
>    type SDL_Palette is record
>       N_Colors : Int;
>       Colors   : SDL_Color_Array;
>    end record;
>    pragma Convention (C, SDL_Palette);

The "pragma Convention" did the trick! I must say, Ada is the one
language I've encountered that seems to have the largest learning
curve because of the most cryptic references I ever seen ;)

> Now, you cannot directly declare a SDL_Palette variable, because it is too
> large. You should do it as you would do in C, i.e. allocate some amount of
> memory and then set structure pointer to it. You do not need 'new' or
> access types in Ada. It can be on the stack like this:
>
>    with System.Storage_Elements;  use System.Storage_Elements;
>       ...
>    Raw_Memory : Storage_Array (1..1_024); -- Memory
>    Palette    : SDL_Palette;
>    for Palette'Address use Raw_Memory'Address;
> begin
>    Palette.N_Colors := 20;
>
> Of course computing memory size from N_Colors is up to you (as in C).

Thanks for the tip, but I don't actually need to allocate any palette
records (this should never be done). The palette is a read-only field
within the pixel information structure of a surface. I just need this
record definition to define the constant access pointer to be able to
access the palette information.

Many thanks, now I move forward again :D

> --
> Regards,
> Dmitry A. Kazakovhttp://www.dmitry-kazakov.de




^ permalink raw reply	[relevance 0%]

* Re: Interfacing C type, unconstrained array with record
  @ 2010-10-16 18:36  5% ` Dmitry A. Kazakov
  2010-10-16 19:19  0%   ` Ron Wills
  2010-10-16 21:41  0%   ` Robert A Duff
  0 siblings, 2 replies; 200+ results
From: Dmitry A. Kazakov @ 2010-10-16 18:36 UTC (permalink / raw)


On Sat, 16 Oct 2010 10:35:39 -0700 (PDT), Ron Wills wrote:

> Hi all
> 
> I've started learning Ada and started porting some software I had in C/
> C++ as a learning exercise. The software uses SDL, so I started a thin
> wrapper around it. I've been very successful with it, but with the
> exception of the palette structure which in C is defined as:
> 
> typedef struct {
>   int ncolors;
>   SDL_Color colors[]; // Actually is SDL_Color *colors but this is how
> it is laid out in memory
> } SDL_Palette;
> 
> In Ada I'm trying to do something like:
> 
> type SDL_Color is
>   record
>     r, g, b, unused : Uint8;
>   end;
> type SDL_Color_Array is array(Positive range <>) of Color;
> type SDL_Palette is
>   record
>     ncolors : Integer;
>     colors : SDL_Color_Array;
>   end;
> 
> Now Ada (GNAT) won't compile this because the colors component is
> unconstrained, which is understandable. I've been googling for a
> couple of days for a way of modeling this in Ada and still having
> access to all the colors in the colors component. In other SDL
> interface implementations, all I've seen is that the colors component
> is made into a type of "Dummy" component and made more or less
> useless. I've also been combing the reference manual, but nothing I've
> noticed seems to solve this issue. I'm sure I'm not the only one that
> has come across this problem and was wondering what solutions are
> available.

You need a flat array, e.g.

   with Interfaces;  use Interfaces;
   with Interfaces.C;  use Interfaces.C;
      ...
   type SDL_Color is record
      R, G, B, Unused : Unsigned_8;
   end record;
   pragma Convention (C, SDL_Color);
   type SDL_Color_Array is array (Positive) of aliased SDL_Color;
   pragma Convention (C, SDL_Color_Array);
   type SDL_Palette is record
      N_Colors : Int;
      Colors   : SDL_Color_Array;
   end record;
   pragma Convention (C, SDL_Palette);

Now, you cannot directly declare a SDL_Palette variable, because it is too
large. You should do it as you would do in C, i.e. allocate some amount of
memory and then set structure pointer to it. You do not need 'new' or
access types in Ada. It can be on the stack like this:

   with System.Storage_Elements;  use System.Storage_Elements;
      ...
   Raw_Memory : Storage_Array (1..1_024); -- Memory
   Palette    : SDL_Palette;
   for Palette'Address use Raw_Memory'Address;
begin
   Palette.N_Colors := 20;

Of course computing memory size from N_Colors is up to you (as in C).

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



^ permalink raw reply	[relevance 5%]

* Re: Does mmap gives a right result?!
  @ 2010-10-04  8:05  6% ` 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 6%]

* Re: S-expression I/O in Ada
  2010-08-01 16:01  5% ` Ludovic Brenta
@ 2010-08-09 18:49  0%   ` Ludovic Brenta
  0 siblings, 0 replies; 200+ results
From: Ludovic Brenta @ 2010-08-09 18:49 UTC (permalink / raw)


Ludovic Brenta <ludovic@ludovic-brenta.org> writes on comp.lang.ada:
> Natacha Kerensikova <lithiumcat@gmail.com> writes:
>> Hi,
>>
>> I'm trying to learn Ada, coming from a C background. The first thing I
>> planned to code is a S-expression parser, because it's quite easy (at
>> least in C, less than 1000 lines including comments and memory
>> handling (dynamic arrays reinvented)) and very useful considering
>> almost all my existing programs use S-expressions as a serialization
>> format.
>>
>> To describe briefly S-expressions, I consider them to be the simplest
>> existing data organization beyond raw sequences of bits. They are
>> basically lists of elements, each element being either a list or an
>> atom, and atoms being raw sequences of bits.
>>
>> While I'm still not deep enough into Ada to know how to represent the
>> lists, I guess there won't be major issues, I think I can handle it
>> myself (though pointers and hints would still be welcome).
>>
>> My question here is about how to represent the atoms in Ada. In C it
>> was merely a void pointer and a size, but it seems more difficult in
>> Ada because of the strong typing. Because it's up to the application
>> to make sense (i.e. type) out of the raw sequences of bits in atoms,
>> the S-expression library has to handle them as a sort of untyped
>> memory chunk. Do you know of a way to handle that?
>>
>> Please correct me if I'm wrong, but my guess would be that the S-
>> expression library would provide a Sexp_Atom type, which refers to the
>> untyped memory chunks, and the application would have procedures to
>> convert back and forth between Sexp_Atom and whatever types it
>> internally uses (i.e. serialization and deserialization procedures).
>> However the library would provide these procedures for the most common
>> types (e.g. strings and numeric types).
>>
>> Though it looks like a fine Ada API (at least to my eyes), I have
>> absolutely no idea about how to implement the library. How to define
>> the application-opaque Sexp_Atom type? How to read Sexp_Atom objects
>> from a file? How to build them from Ada types? How to write them back
>> to disk?
>
> In Ada, you normally model blobs with
> System.Storage_Elements.Storage_Array; since arrays are first-class
> citizens (as opposed to C's void pointers), you do not need to carry the
> length of such an array separately.  Thus, a naive approach might be:
>
> type Sexp_Atom is access System.Storage_Elements.Storage_Array;
> type Sexp;
> type Sexp_Access is access Sexp;
> type Sexp is record
>   Car : Sexp_Atom;
>   Cdr : Sexp_Access;
> end record;
>
> However, the purpose of S-Expressions being to be read and written as
> text, a blob may not be the most appropriate; you might be better off
> with simply:
>
> type Sexp;
> type Sexp_Access is access Sexp;
> type Sexp is
>   Car : Ada.Strings.Unbounded.Unbounded_String;
>   Cdr : Sexp_Access;
>   Is_List : Boolean;
> end record;
>
> To write a sexp to disk and read back, you would leverage the Ada
> streams as Dmitry pointed out.
>
> You could then provide a generic package that serializes an arbitrary
> type T back and forth to the unbounded_string.

I pursued that idea a little further and actually wrote an embryonic
S-Expression library.  I'm not entirely satisfied with it because it
uses copy semantics instead of reference semantics and so is probably
inefficient.  But it does demonstrate how to read and write
S-Expressions on a stream (e.g. a file).  Also, it shows how to
hex-encode and hex-decode blobs, which I've modelled as Storage_Arrays.

You can browse the sources here:

http://green.ada-france.org:8081/branch/changes/org.ludovic-brenta.s_expressions

Enjoy.  (the license is the GPLv3 or later).

-- 
Ludovic Brenta.



^ permalink raw reply	[relevance 0%]

* Re: S-expression I/O in Ada
    2010-08-01 16:01  5% ` Ludovic Brenta
@ 2010-08-01 18:25  4% ` Jeffrey Carter
  1 sibling, 0 replies; 200+ results
From: Jeffrey Carter @ 2010-08-01 18:25 UTC (permalink / raw)


On 08/01/2010 05:17 AM, Natacha Kerensikova wrote:
>
> To describe briefly S-expressions, I consider them to be the simplest
> existing data organization beyond raw sequences of bits. They are
> basically lists of elements, each element being either a list or an
> atom, and atoms being raw sequences of bits.

You might very well be able to use something like:

package Byte_Lists is new Ada.Containers.Vectors (Index_Type => Positive, 
Element_Type => System.Storage_Elements.Storage_Element);

type Content_ID is (Atom, List);

type S_Expression;
type S_Expression_Ptr is access all S_Expression;

type S_Expression_Element (Content : Content_ID := Atom) is record
    case Content is
    when Atom =>
       Byte : Byte_Lists.Vector;
    when List =>
       Ptr : S_Expression_Ptr;
    end case;
end record;

package S_Expression_Lists is new Ada.Containers.Doubly_Linked_Lists 
(Element_Type => S_Expression_Element);

type S_Expression is new S_Expression_Lists.List;

If you can use unbounded strings as Brenta suggested, instead of an unbounded 
array of bytes (Storage_Element), then this would be even simpler.

-- 
Jeff Carter
"People called Romanes, they go the house?"
Monty Python's Life of Brian
79

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



^ permalink raw reply	[relevance 4%]

* Re: S-expression I/O in Ada
  @ 2010-08-01 16:01  5% ` Ludovic Brenta
  2010-08-09 18:49  0%   ` Ludovic Brenta
  2010-08-01 18:25  4% ` Jeffrey Carter
  1 sibling, 1 reply; 200+ results
From: Ludovic Brenta @ 2010-08-01 16:01 UTC (permalink / raw)


Natacha Kerensikova <lithiumcat@gmail.com> writes:
> Hi,
>
> I'm trying to learn Ada, coming from a C background. The first thing I
> planned to code is a S-expression parser, because it's quite easy (at
> least in C, less than 1000 lines including comments and memory
> handling (dynamic arrays reinvented)) and very useful considering
> almost all my existing programs use S-expressions as a serialization
> format.
>
> To describe briefly S-expressions, I consider them to be the simplest
> existing data organization beyond raw sequences of bits. They are
> basically lists of elements, each element being either a list or an
> atom, and atoms being raw sequences of bits.
>
> While I'm still not deep enough into Ada to know how to represent the
> lists, I guess there won't be major issues, I think I can handle it
> myself (though pointers and hints would still be welcome).
>
> My question here is about how to represent the atoms in Ada. In C it
> was merely a void pointer and a size, but it seems more difficult in
> Ada because of the strong typing. Because it's up to the application
> to make sense (i.e. type) out of the raw sequences of bits in atoms,
> the S-expression library has to handle them as a sort of untyped
> memory chunk. Do you know of a way to handle that?
>
> Please correct me if I'm wrong, but my guess would be that the S-
> expression library would provide a Sexp_Atom type, which refers to the
> untyped memory chunks, and the application would have procedures to
> convert back and forth between Sexp_Atom and whatever types it
> internally uses (i.e. serialization and deserialization procedures).
> However the library would provide these procedures for the most common
> types (e.g. strings and numeric types).
>
> Though it looks like a fine Ada API (at least to my eyes), I have
> absolutely no idea about how to implement the library. How to define
> the application-opaque Sexp_Atom type? How to read Sexp_Atom objects
> from a file? How to build them from Ada types? How to write them back
> to disk?

In Ada, you normally model blobs with
System.Storage_Elements.Storage_Array; since arrays are first-class
citizens (as opposed to C's void pointers), you do not need to carry the
length of such an array separately.  Thus, a naive approach might be:

type Sexp_Atom is access System.Storage_Elements.Storage_Array;
type Sexp;
type Sexp_Access is access Sexp;
type Sexp is record
  Car : Sexp_Atom;
  Cdr : Sexp_Access;
end record;

However, the purpose of S-Expressions being to be read and written as
text, a blob may not be the most appropriate; you might be better off
with simply:

type Sexp;
type Sexp_Access is access Sexp;
type Sexp is
  Car : Ada.Strings.Unbounded.Unbounded_String;
  Cdr : Sexp_Access;
  Is_List : Boolean;
end record;

To write a sexp to disk and read back, you would leverage the Ada
streams as Dmitry pointed out.

You could then provide a generic package that serializes an arbitrary
type T back and forth to the unbounded_string.

-- 
Ludovic Brenta.



^ permalink raw reply	[relevance 5%]

* Re: How to access this package written in C?
  @ 2010-04-23 15:39  5%       ` John B. Matthews
  0 siblings, 0 replies; 200+ results
From: John B. Matthews @ 2010-04-23 15:39 UTC (permalink / raw)


In article <nospam-84056C.10444823042010@news.aioe.org>,
 "John B. Matthews" <nospam@nospam.invalid> wrote:

> In article 
> <e98bcf01-46cc-44dd-b57b-3cc7e273d9e2@j21g2000yqh.googlegroups.com>,
>  resander <kresander@gmail.com> wrote:
> 
> > Prodrecord address: -1079352648
> >  code field address: -1079352648
> >  bcode field address: -1079352644
> >  ccode field address: -1079352643
> >  third field address: -1079352640
> >  descr field address: -1079352636
> >  price field address: -1079352624
> >   ...
> > Q1.
> > Addresses are not negative. How do I output a System.Address?
> 
> -1079352648 = 0xBFAA62B8
> -1079352644 = 0xBFAA62BC
> ...
> 
> This recent thread discusses several ways to display hexadecimal:
> 
> <http://groups.google.com/group/comp.lang.ada/browse_frm/thread/f3514db0a21f9b
> 44>
> 
> A.10.8 Input-Output for Integer Types may be the most straightforward:
> 
> <http://www.adaic.com/standards/05rm/html/RM-A-10-8.html>

For example,

with Ada.Text_IO;
with System.Storage_Elements;

procedure Modular is

package Memory renames System.Storage_Elements;
package Address_IO is
   new Ada.Text_IO.Modular_IO(Memory.Integer_Address);
     
begin
   Ada.Text_IO.Put("Address of procedure Modular: ");
   Address_IO.Put(
      Item => Memory.To_Integer(Modular'Address),
      Width => 0,
      Base => 16);
   Ada.Text_IO.New_Line;
end Modular;

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



^ permalink raw reply	[relevance 5%]

* Re: How to access this package written in C?
  @ 2010-04-23 14:15  4%     ` Dmitry A. Kazakov
    1 sibling, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2010-04-23 14:15 UTC (permalink / raw)


On Fri, 23 Apr 2010 05:58:05 -0700 (PDT), resander wrote:

> It may help if I give some background info, so just briefly the
> program (with guidb as the main entry routine) moves record data to/
> from GUI dialogs and to and from SQL databases via ODBC.

There is GNADE ODBC, Ada bindings to ODBC. So you can drop C/C++
altogether.

> for record
>    code : integer; bcode : character;
>    ccode : character; third : integer;
>    descr : String(1..10); price : float;
> by:
>  prod : PRODUCT;
>  a: System.Address;
>    function Conv is new Ada.Unchecked_Conversion (
>                      Source => System.Address,
>                      Target => Integer);
>   ...
>   a := prod'Address;
>   put( "Prodrecord address: " );
>   s := conv ( a ) ;
>   put(s);
>   new_line;
> 
>   a := prod.code'Address;
>   put( " code field address: " );
>   s := conv ( a ) ;
>   put(s);
>   new_lin
>   ...
> Q1.
> Addresses are not negative.

Never use Unchecked_Conversion unless you exactly know what you are
doing... Address is modular, when bit-wise converted to a *signed* integer
the result is expectedly surprising.

> How do I output a System.Address?

The example above in legal Ada:

with Ada.Text_IO;              use Ada.Text_IO;
with System.Storage_Elements;  use System.Storage_Elements;
with Interfaces.C;             use Interfaces.C;

procedure Test_Fields is
   type Product is record
      Code : int;     -- Use only C-compatible types when you communicate
      Bcode : char; -- to C
      Ccode : char;
      Third : int;
      Descr : char_array (1..10);
      Price : c_float;
   end record;
   pragma Convention (C, Product);
   P : aliased Product;
begin
   Put_Line ("P'Address:" & Integer_Address'Image (To_Integer
(P'Address)));
   Put_Line ("P.Code'Address:" & Integer_Address'Image (To_Integer
(P.Code'Address)));
   Put_Line ("P.Descr'Address:" & Integer_Address'Image (To_Integer
(P.Descr'Address)));
end Test_Fields;

gives:

P'Address: 38207168
P.Code'Address: 38207168
P.Descr'Address: 38207180

> Dmitri:
> Many thanks for showing how to code the generic Get routine. I have
> never used generics or interfaced to C before and it was so long time
> ago I used Ada (where is my walking stick?) so I don't understand it
> well enough.

Ada generic is roughly what C++ calls template.

> Q2.
> What is the effect of aliased in 'Data : aliased Data_Type;'?
> 
> Data is a local variable. I am confused by the aliased keyword, but it
> would seem guidb copies the record into this and then the record value
> is copied once more into final location (X:Product). If so, one copy
> operation is redundant.

"aliased" means "dear compiler, I plan to take pointers (access type) to
this thing." The compiler will reject Data'Access otherwise, because
without your hint it is free to allocate it in a way that Data would have
no valid machine address at all.

> Q3.
> The wrapper:
> procedure getprod (p:out PRODUCT;res:out int) is
> begin
>    result = guidb ( 0 , addrin(p)??? ) ;
> end
> 
> hides the details of calling the C function and returns data to the
> record variable in the calling program if the address carried by the
> formal parameter can be obtained inside the wrapper. Using p'Address
> for the second actual parameter of guidb would probably just give the
> address of the formal (will check when I know how to output a
> System.Address).
> Is it possible to obtain the memory address of the record variable via
> formal parameter p?

In general case no, because see above. However if you declare PRODUCT a
"limited type" it will be passed by reference. You also [worse] can

   procedure getprod (p: access PRODUCT; ...);

BTW, your concern about copying records is absolutely ungrounded.
Especially because you are using ODBC + a relational DBMS! These are so
extraordinary slow, that you will note no difference even if you did
hundreds of copies.

> Q4.
> Would it be easier to implement this if the wrapper was changed to:
> 
> procedure getprod (p: in System.Address; res:out int) is
> begin
>    result = guidb ( 0 , what goes here??? ) ;
> end
> 
> with user calling it as:
> 
>   getprod ( recordvar'Address , result );

The preferences are as follows:

in out >> access >>>>>>>>>>> address

> Q5.
> Host language event handler procedures are stored as an array of
> procedure addresses which is local to guidb. A procedure is called
> indirectly via this array. This was designed for C/C++, but it would
> be nice to use the same or similar mechanism for Ada.
> Is this going to be possible?

Yes, it is possible, you can have an array of access-to-procedure type. But
an OO way is preferable.

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



^ permalink raw reply	[relevance 4%]

* Re: Table of pointers question
       [not found]         ` <3YSdnY7SXPNd_yPXnZ2dnUVZ_sydnZ2d@earthlink.com>
@ 2009-09-26 21:00  4%       ` Georg Bauhaus
  0 siblings, 0 replies; 200+ results
From: Georg Bauhaus @ 2009-09-26 21:00 UTC (permalink / raw)


Dennis Lee Bieber wrote:

> 	Note that, as with Pascal, Modula-2 requires the user to explicitly
> code pointer dereference operations. Ada rarely needs such as one can
> not perform arithmetic on access types.

Still, Ada programmers can do any pointer arithmetic they want,
using System.Storage_Elements (cf. 13.7.1).



^ permalink raw reply	[relevance 4%]

* Re: put of access type
  2009-08-20  1:54  0%       ` Rob Solomon
@ 2009-08-20  2:06  0%         ` Rob Solomon
  0 siblings, 0 replies; 200+ results
From: Rob Solomon @ 2009-08-20  2:06 UTC (permalink / raw)


On Wed, 19 Aug 2009 21:54:05 -0400, Rob Solomon
<usenet@drrob1-noreply.com> wrote:

>>> >You probably meant the address of the pointed object. Here you go. Let Ptr
>>> >be a pointer to some object
>>>
>>> >(with System.Storage_Elements; �use System.Storage_Elements;)
>>>
>>> > � Integer_Address'Image (To_Integer (Ptr.all'Address)));
>>>
>>> >Ptr.all'Address is the address of the object. To_Integer converts the
>>> >address to a plain integer type (Integer_Address defined in
>>> >System.Storage_Elements). This type can be output as any other.
>>>
>>> I am trying to understand this. �
>>>
>>> Back when I learned Modula-2, I learned that pointer types are
>>> assignment compatible with System.Address and I understand them as
>>> being the same thing. �They �differ in context, not value.
>>>
>>> I see that access types are being used the same as pointer types, but
>>> if I understand correctly, are actually quite different. �But I don't
>>> understand how. �ie, how are access types and pointers different?
>>
>>For simple types (integer; simple records) there's probably no
>>difference. For types with constraints/discriminants, bets are off:
>>consider
>>
>>  S : access String := "foo";
>>
>>S will most likely (this is compiler-dependent) *not* point to the 'f'
>>in "foo"; it might point to a structure containing
>>
>>   4-byte integer, lower bound of string (= 1)
>>   4-byte integer, upper bound of string (= 3)
>>   1-byte character = f
>>   1-byte character = o
>>   1-byte character = o
>>
>>> What is the difference between integer_address and address?
>>
>>integer_address is some sort of integer, with 'image, "=", "-" etc;
>>address is private, with no such operations (it does have comparators;
>>see package System).
>>
>>integer_address'image is going to be up to about 10 (32-bit addresses)
>>or 20 (64-bit addresses) characters long, and you are assigning it to
>>a string of length 255; that won't work.
>
>This is what I came up with, that works.  But I have another question,
>to follow the code:
>
>procedure adr is
>
>   type card32 is mod 4_294_967_296;
>   package card32_IO is new Ada.Text_IO.Modular_IO(card32);
>
>
>   X : aliased Integer := 1;
>   c,k : card32 := 0;
>
>   P1,P2,P3 : Access Integer;
>   Str,S : String(1..255);
>   begin
>   P1 := X'Access;
>   P2 := P1;
>   P3 := new integer;
>
>Ada.Strings.Fixed.Move(Integer_Address'Image(To_Integer(P1.all'Address)),Str);
>   Move(System.Address_Image(P1.all'address),s);
>   C   :=
>card32'value(Integer_Address'Image(To_Integer(P2.all'Address)));
>   K   :=
>card32'value(Integer_Address'Image(To_Integer(P3.all'Address)));
>   put("Str = ");
>   put(Str);
>   new_line;
>   put("s = ");
>   put(s);
>   put("C = ");
>   Card32_io.put(c);
>   new_line;
>   put("K = ");
>   Card32_io.put(k);
>   new_line;
>   end adr;
>
>My question is that the value of Str and S should be equal, after
>converting  hex <-> decimal.  They are not.  I am getting this as the
>relevent output
>Str = 3215841220
>S = BFADD7C4
>
>These numbers are not equal, according to my conversion.
>
>What am I missing?

NEVERMIND

I figured it out.  The output is not putting all digits on the same
line.  When I corrected for this, the actual output does match when
converting from hex <-> dec



^ permalink raw reply	[relevance 0%]

* Re: put of access type
  2009-08-19 19:44  0%     ` sjw
@ 2009-08-20  1:54  0%       ` Rob Solomon
  2009-08-20  2:06  0%         ` Rob Solomon
  0 siblings, 1 reply; 200+ results
From: Rob Solomon @ 2009-08-20  1:54 UTC (permalink / raw)


>> >You probably meant the address of the pointed object. Here you go. Let Ptr
>> >be a pointer to some object
>>
>> >(with System.Storage_Elements; �use System.Storage_Elements;)
>>
>> > � Integer_Address'Image (To_Integer (Ptr.all'Address)));
>>
>> >Ptr.all'Address is the address of the object. To_Integer converts the
>> >address to a plain integer type (Integer_Address defined in
>> >System.Storage_Elements). This type can be output as any other.
>>
>> I am trying to understand this. �
>>
>> Back when I learned Modula-2, I learned that pointer types are
>> assignment compatible with System.Address and I understand them as
>> being the same thing. �They �differ in context, not value.
>>
>> I see that access types are being used the same as pointer types, but
>> if I understand correctly, are actually quite different. �But I don't
>> understand how. �ie, how are access types and pointers different?
>
>For simple types (integer; simple records) there's probably no
>difference. For types with constraints/discriminants, bets are off:
>consider
>
>  S : access String := "foo";
>
>S will most likely (this is compiler-dependent) *not* point to the 'f'
>in "foo"; it might point to a structure containing
>
>   4-byte integer, lower bound of string (= 1)
>   4-byte integer, upper bound of string (= 3)
>   1-byte character = f
>   1-byte character = o
>   1-byte character = o
>
>> What is the difference between integer_address and address?
>
>integer_address is some sort of integer, with 'image, "=", "-" etc;
>address is private, with no such operations (it does have comparators;
>see package System).
>
>integer_address'image is going to be up to about 10 (32-bit addresses)
>or 20 (64-bit addresses) characters long, and you are assigning it to
>a string of length 255; that won't work.

This is what I came up with, that works.  But I have another question,
to follow the code:

procedure adr is

   type card32 is mod 4_294_967_296;
   package card32_IO is new Ada.Text_IO.Modular_IO(card32);


   X : aliased Integer := 1;
   c,k : card32 := 0;

   P1,P2,P3 : Access Integer;
   Str,S : String(1..255);
   begin
   P1 := X'Access;
   P2 := P1;
   P3 := new integer;

Ada.Strings.Fixed.Move(Integer_Address'Image(To_Integer(P1.all'Address)),Str);
   Move(System.Address_Image(P1.all'address),s);
   C   :=
card32'value(Integer_Address'Image(To_Integer(P2.all'Address)));
   K   :=
card32'value(Integer_Address'Image(To_Integer(P3.all'Address)));
   put("Str = ");
   put(Str);
   new_line;
   put("s = ");
   put(s);
   put("C = ");
   Card32_io.put(c);
   new_line;
   put("K = ");
   Card32_io.put(k);
   new_line;
   end adr;

My question is that the value of Str and S should be equal, after
converting  hex <-> decimal.  They are not.  I am getting this as the
relevent output
Str = 3215841220
S = BFADD7C4

These numbers are not equal, according to my conversion.

What am I missing?



^ permalink raw reply	[relevance 0%]

* Re: put of access type
  2009-08-19 19:00  0%   ` Rob Solomon
@ 2009-08-19 19:44  0%     ` sjw
  2009-08-20  1:54  0%       ` Rob Solomon
  0 siblings, 1 reply; 200+ results
From: sjw @ 2009-08-19 19:44 UTC (permalink / raw)


On Aug 19, 8:00 pm, Rob Solomon <use...@drrob1-noreply.com> wrote:
> >> I would like to output a pointer to the screen.  (I am just learning
> >> Ada).  
>
> >> How do I put(Any_Access_Type)
>
> >You probably meant the address of the pointed object. Here you go. Let Ptr
> >be a pointer to some object
>
> >(with System.Storage_Elements;  use System.Storage_Elements;)
>
> >   Integer_Address'Image (To_Integer (Ptr.all'Address)));
>
> >Ptr.all'Address is the address of the object. To_Integer converts the
> >address to a plain integer type (Integer_Address defined in
> >System.Storage_Elements). This type can be output as any other.
>
> I am trying to understand this.  
>
> Back when I learned Modula-2, I learned that pointer types are
> assignment compatible with System.Address and I understand them as
> being the same thing.  They  differ in context, not value.
>
> I see that access types are being used the same as pointer types, but
> if I understand correctly, are actually quite different.  But I don't
> understand how.  ie, how are access types and pointers different?

For simple types (integer; simple records) there's probably no
difference. For types with constraints/discriminants, bets are off:
consider

  S : access String := "foo";

S will most likely (this is compiler-dependent) *not* point to the 'f'
in "foo"; it might point to a structure containing

   4-byte integer, lower bound of string (= 1)
   4-byte integer, upper bound of string (= 3)
   1-byte character = f
   1-byte character = o
   1-byte character = o

> What is the difference between integer_address and address?

integer_address is some sort of integer, with 'image, "=", "-" etc;
address is private, with no such operations (it does have comparators;
see package System).

> I need help with this code:
>
> procedure adr is
>
> c: integer;
> x: aliased integer;
> p1, p2 : access integer;
> str : string (1..255);
>
> Begin
>   p1 := x'access;
>   p2 := p1;
>   str := integer_address'image(to_integer(p1.all'address));
>   c := integer(to_integer(p2.all'address));
>
> some put statements
> end adr;
>
> This compiles w/ GNAT under Ubuntu 9.04, but I am getting
> constraint_error, range check failed.
>
> I don't understand why

integer_address'image is going to be up to about 10 (32-bit addresses)
or 20 (64-bit addresses) characters long, and you are assigning it to
a string of length 255; that won't work.

Either pass the value directly to the put routine -- put
(integer_address'image(... -- or (probably less useful to you?) use a
declare block:

declare
   str : constant string := integer_address'image(....
begin
   put(str);



^ permalink raw reply	[relevance 0%]

* Re: put of access type
  2009-08-19  7:21  6% ` Dmitry A. Kazakov
@ 2009-08-19 19:00  0%   ` Rob Solomon
  2009-08-19 19:44  0%     ` sjw
  0 siblings, 1 reply; 200+ results
From: Rob Solomon @ 2009-08-19 19:00 UTC (permalink / raw)


>> I would like to output a pointer to the screen.  (I am just learning
>> Ada).  
>> 
>> How do I put(Any_Access_Type)
>
>You probably meant the address of the pointed object. Here you go. Let Ptr
>be a pointer to some object
>
>(with System.Storage_Elements;  use System.Storage_Elements;)
>
>   Integer_Address'Image (To_Integer (Ptr.all'Address)));
>
>Ptr.all'Address is the address of the object. To_Integer converts the
>address to a plain integer type (Integer_Address defined in
>System.Storage_Elements). This type can be output as any other.

I am trying to understand this.  

Back when I learned Modula-2, I learned that pointer types are
assignment compatible with System.Address and I understand them as
being the same thing.  They  differ in context, not value.

I see that access types are being used the same as pointer types, but
if I understand correctly, are actually quite different.  But I don't
understand how.  ie, how are access types and pointers different?

What is the difference between integer_address and address?

I need help with this code:

procedure adr is

c: integer;
x: aliased integer;
p1, p2 : access integer;
str : string (1..255);

Begin
  p1 := x'access;
  p2 := p1;
  str := integer_address'image(to_integer(p1.all'address));
  c := integer(to_integer(p2.all'address));

some put statements
end adr;

This compiles w/ GNAT under Ubuntu 9.04, but I am getting
constraint_error, range check failed.

I don't understand why



^ permalink raw reply	[relevance 0%]

* Re: put of access type
    2009-08-18 23:17  4% ` Jeffrey R. Carter
@ 2009-08-19  7:21  6% ` Dmitry A. Kazakov
  2009-08-19 19:00  0%   ` Rob Solomon
  1 sibling, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2009-08-19  7:21 UTC (permalink / raw)


On Tue, 18 Aug 2009 18:26:26 -0400, Rob Solomon wrote:

> I would like to output a pointer to the screen.  (I am just learning
> Ada).  
> 
> How do I put(Any_Access_Type)

You probably meant the address of the pointed object. Here you go. Let Ptr
be a pointer to some object

(with System.Storage_Elements;  use System.Storage_Elements;)

   Integer_Address'Image (To_Integer (Ptr.all'Address)));

Ptr.all'Address is the address of the object. To_Integer converts the
address to a plain integer type (Integer_Address defined in
System.Storage_Elements). This type can be output as any other.

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



^ permalink raw reply	[relevance 6%]

* Re: put of access type
  2009-08-18 23:17  4% ` 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  4% ` Jeffrey R. Carter
  2009-08-19  3:36  0%   ` Rob Solomon
  2009-08-19  7:21  6% ` Dmitry A. Kazakov
  1 sibling, 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 4%]

* Re: addr2line i mingw gcc 4.4.0
  2009-06-27 12:29  3%         ` Dmitry A. Kazakov
@ 2009-06-27 13:05  0%           ` Ludovic Brenta
  0 siblings, 0 replies; 200+ results
From: Ludovic Brenta @ 2009-06-27 13:05 UTC (permalink / raw)


On Jun 27, 2:29 pm, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> On Sat, 27 Jun 2009 07:28:32 -0400, Stephen Leake wrote:
> > Ludovic Brenta <ludo...@ludovic-brenta.org> writes:
>
> >> libaddr2line.a is an invention from AdaCore several years ago; it is a
> >> patch against the program "addr2line" in certain versions of binutils,
> >> not GCC.  I am not aware of any binary distribution of it apart from
> >> AdaCore's own.  In Debian, I've patched GCC so that it supports
> >> symbolic tracebacks by calling addr2line in an external process rather
> >> than using libaddr2line in-process.  An early version of this patch
> >> was in the Ada for Linux Team distribution by Jürgen Pfeiffer for Red
> >> Hat Linux 6 (in 1999).
>
> >> So, I think you can have symbolic tracebacks in mingw in one of two
> >> ways: patch binutils to build libaddr2line.a then link libgnat against
> >> it; or patch libgnat to use the same method as on Debian.
>
> > A third alternative is to output numeric traceback from the failing
> > program, and then use addr2line (the program) to get the symbolic
> > traceback in a separate manual step.
>
> It is quite simple to print the symbolic traceback from the program:
>
> with Ada.Text_IO;              use Ada.Text_IO;
> with GNAT.Traceback;           use GNAT.Traceback;
> with GNAT.Traceback.Symbolic;  use GNAT.Traceback.Symbolic;
>
> procedure Call_Stack is
>    TB  : Tracebacks_Array (1..100);
>    Len : Natural;
> begin
>    Call_Chain (TB, Len);
>    Put_Line (Symbolic_Traceback (TB (1..Len)));
> end Call_Stack;
>
> This prints the call stack. I am using this for tracing Gtk errors before
> they corrupt the stack due to exception propagation.
>
> Note that Tracebacks_Array is merely an array of addresses, so if you get
> it in other way, for example, from Exception_Information, you can convert
> each number there to Address (using System.Storage_Elements.To_Address) and
> then pass the result to (Symbolic_Traceback.

Like I explained, this works in GNAT GPL Edition only because this
distribution includes libaddr2line.a, which GNAT.Tracebacks.Symbolic
uses.  For GCC, a patch is required either to binutils or to GCC
(libgnat, actually) itself.

--
Ludovic Brenta.



^ permalink raw reply	[relevance 0%]

* Re: addr2line i mingw gcc 4.4.0
  @ 2009-06-27 12:29  3%         ` Dmitry A. Kazakov
  2009-06-27 13:05  0%           ` Ludovic Brenta
  0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2009-06-27 12:29 UTC (permalink / raw)


On Sat, 27 Jun 2009 07:28:32 -0400, Stephen Leake wrote:

> Ludovic Brenta <ludovic@ludovic-brenta.org> writes:
> 
>> libaddr2line.a is an invention from AdaCore several years ago; it is a
>> patch against the program "addr2line" in certain versions of binutils,
>> not GCC.  I am not aware of any binary distribution of it apart from
>> AdaCore's own.  In Debian, I've patched GCC so that it supports
>> symbolic tracebacks by calling addr2line in an external process rather
>> than using libaddr2line in-process.  An early version of this patch
>> was in the Ada for Linux Team distribution by J�rgen Pfeiffer for Red
>> Hat Linux 6 (in 1999).
>>
>> So, I think you can have symbolic tracebacks in mingw in one of two
>> ways: patch binutils to build libaddr2line.a then link libgnat against
>> it; or patch libgnat to use the same method as on Debian.
> 
> A third alternative is to output numeric traceback from the failing
> program, and then use addr2line (the program) to get the symbolic
> traceback in a separate manual step.

It is quite simple to print the symbolic traceback from the program:

with Ada.Text_IO;              use Ada.Text_IO;
with GNAT.Traceback;           use GNAT.Traceback;
with GNAT.Traceback.Symbolic;  use GNAT.Traceback.Symbolic;

procedure Call_Stack is
   TB  : Tracebacks_Array (1..100);
   Len : Natural;
begin
   Call_Chain (TB, Len);
   Put_Line (Symbolic_Traceback (TB (1..Len)));
end Call_Stack; 

This prints the call stack. I am using this for tracing Gtk errors before
they corrupt the stack due to exception propagation.

Note that Tracebacks_Array is merely an array of addresses, so if you get
it in other way, for example, from Exception_Information, you can convert
each number there to Address (using System.Storage_Elements.To_Address) and
then pass the result to (Symbolic_Traceback.

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



^ permalink raw reply	[relevance 3%]

* Re: GNAT on WinXP: System.OS_Lib.Spawn raises Program_Error
  2009-05-02 20:39  4%   ` 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  4%   ` 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 4%]

* Re: C getchar() functionality in Ada
  @ 2009-02-16 21:43  4% ` Jeffrey R. Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey R. Carter @ 2009-02-16 21:43 UTC (permalink / raw)


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

This program duplicates standard input on standard output.

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

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

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



^ permalink raw reply	[relevance 4%]

* Exceptions (was Re: How do I go about creating a minimal GNAT runtime?)
  @ 2009-02-10  2:34  4% ` anon
  0 siblings, 0 replies; 200+ results
From: anon @ 2009-02-10  2:34 UTC (permalink / raw)


To compile and execute a simple program that uses a raise statement 
such as in the following code:

    --
    -- Sample code
    --
    procedure test is
      begin
        raise Program_Error ;
      end test ;

you will need the following list of packages in your "rts/adainclude" and 
the *.ali stored in "rts/adalib". You will also need to build the 
"libgnat.a" by using the "ar r <list of object files>" command and store 
in the "rts/adalib" dir.


a-except.adb  -- Ada.Exceptions            Edited to conform to RM.
a-except.ads                               Simpler design. That removes
                                           most Import/Exports except for
                                           exports for the RChecks 
                                           routines.
                                           Rchecks routines defined in 
                                           body and are rewritten to use 
                                           Raise_Exception instead of 
                                           GNAT's complex algorithm. 
                              

a-unccon.ads  -- Ada.Unchecked_Conversion
ada.ads       -- Ada

s-secsta.adb  -- System.Secondary_Stack    Compiler uses this package for 
s-secsta.ads                               functions that return a string 
                                           value. Also requires
                                           System.Storage_Elements.

s-memory.adb  -- System.Memory             This is a test environmental
s-memory.ads                               package that simulates a heap
                                           Needs a true hardware memory 
                                           management.  That can handle 
                                           static and virtual system.

s-stalib.adb  -- System.Standard_Library   Defines standard Exceptions
s-stalib.ads                               and storage. Basically copied 
                                           from GNAT. 

s-stoele.adb  -- System.Storage_Elements   
s-stoele.ads

system.ads    -- System                    GNAT compiler based.

--
-- Extra packages use for output of exception message
--

g-io.adb      -- GNAT.IO                   use for Put/Put_Line/New_Line
g-io.ads                                   connects to Video_IO

gnat.ads      -- GNAT

video_io.adb  -- Video_IO                  Text/Graphic SAGA device driver
video_io.ads                              



The reason you must rewrite "Ada.Exceptions" is that it uses multiple 
c-to-os functions, which some are defined in:

System.CRTL   -- defines C RTL ( not used in an Ada only OS )
System.Memory -- defines C memory functions. ( Needs be defined 
                 Ada to CPU Memory routines first )
              -- In other words a complete memory management system 
              -- is needs to make this package fully functional, but
              -- it can be simulate by using a large array of bytes.
              -- 
cio.c         -- defines C RTS to OS for I/O operations.  Must be 
              -- converted to a complete sub-system. In my example 
              -- I used a modified "GNAT.IO" and the "Video_IO" 
              -- device driver.

Then there the "System.Soft_Links" package. Do you really need 
it.  In most cases, for the core of the kernel the answer is No!


Now there are some binder variables are procedures that needs to be 
define in Ada, they are normally found in "Initialize.c", "init.c", 
"finalize.c". In my example I create a package called "gnat_library"
to store these in Ada routines and variables.
#
#
#
rm test
gnat compile  gnat_library.adb --RTS=rts
#
gnat compile  test.adb         --RTS=rts
gnat bind     test.ali         --RTS=rts
#
# To make the routine executable, must move the "function main" to 
# the beginning of the ada_main package before compiling.
#
gnat compile  b~test.adb       --RTS=rts -gnatA -gnatWb -gnatiw -gnatws
#
#  gnatlink test.ali gnat_library.o -n -v -v --RTS=rts
#
#  Problem: Adds all gcc libraries and includes host Ada Library Path 
#           and in some case will cause linker to stop processing. So 
#           it still better to use the "gcc" program.
#
gcc  b~test.o gnat_library.o ./test.o text_io.o video_io.o --RTS=rts       \
     -o test -L./ -L/example/ada/gnat/rts/adalib/                          \
     /example/ada/gnat/rts/adalib/libgnat.a
#
#
#


In <eb511600-6446-4bad-b859-0d7444416a4c@d36g2000prf.googlegroups.com>, Lucretia <lucretia9@lycos.co.uk> writes:
>Hi (again),
>
>It's been a while, but I'm coming back to my Ada kernel again. I've
>been messing with my helo_world_kernel which I built using no runtime
>(see http://www.archeia.com for more info).
>
>Having just spoken to Ludovic on #Ada, he pointed out that the gnat
>tools can use a basic cross tool set, like the ones I have built
>myself (again, see the above link). My toolset comprises of a gnat1
>compiler and a gnatbind for my targets. I found that it does work
>using the --GCC and --GNATBIND flags, and I need to make sure the
>cross tools and the host tools are of the same GCC version otherwise
>GNAT throws up ALI format errors.
>
>The thing is, I've been trying to enable exceptions, but keep coming
>across big problems in that the runtime requires features that are
>being restricted, such as returning aggregates and assigning
>composites, returning unconstrained objects which requires the
>secondary stack. So, what I really need to know is, how do I create a
>runtime which is restricted in this way for bare hw access?
>
>Thanks,
>Luke.




^ permalink raw reply	[relevance 4%]

* Re: cannot generate code for file a-excach.adb (subunit)
  2009-01-27 14:21  4% cannot generate code for file a-excach.adb (subunit) Lucretia
@ 2009-01-27 14:38  0% ` xavier grave
  0 siblings, 0 replies; 200+ results
From: xavier grave @ 2009-01-27 14:38 UTC (permalink / raw)


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

You need to include excach.adb source file but it is part of the
Ada.Exceptions package and is compiled when you compile a-except.adb
so you don't need to compile it.

As far as I remember...
xavier

Lucretia a �crit :
> Hi,
> 
> In my attempts to enable exceptions in my test kernel, I've come
> across a problem when building up my configurable runtime.
> 
> x86_64-unknown-elf-gcc -fno-pic -c -nostdinc -I. -ffunction-sections -
> fdata-sections -gnato -gnatE -m32 -g2 -gnatf -gnatu -gnatv -gnatpg a-
> excach.adb
> 
> GNAT 4.3.0
> Copyright 1992-2007, Free Software Foundation, Inc.
> 
> Unit name                        File name                     Time
> stamp
> ---------                        ---------
> ----------
> 
> Ada (spec)                       ada.ads
> 20070406091342
> Ada.Exceptions (spec)            a-except.ads
> 20070606104609
> Ada.Exceptions (body)            a-except.adb
> 20071213102130
> Ada.Exceptions.Call_Chain (body) a-excach.adb
> 20051115140645
> Ada.Unchecked_Conversion (spec)  a-unccon.ads
> 20070406091342
> System (spec)                    system.ads
> 20090127135815
> System.Exceptions (spec)         s-except.ads
> 20070912115821
> System.Parameters (spec)         s-parame.ads
> 20090127133535
> System.Soft_Links (spec)         s-soflin.ads
> 20071213103411
> System.Stack_Checking (spec)     s-stache.ads
> 20070912115821
> System.Standard_Library (spec)   s-stalib.ads
> 20070912115821
> System.Storage_Elements (spec)   s-stoele.ads
> 20070912115821
> System.Traceback (spec)          s-traceb.ads
> 20070912115821
> System.Traceback_Entries (spec)  s-traent.ads
> 20070912115821
> System.Wch_Con (spec)            s-wchcon.ads
> 20071213102052
> System.Wch_Stw (spec)            s-wchstw.ads
> 20071213102130
> 
> cannot generate code for file a-excach.adb (subunit)
> to check subunit for errors, use -gnatc
> 
> Compiling: a-excach.adb (source file time stamp: 2005-11-15 14:06:45)
>  76 lines: No errors
> make: *** [a-excach.o] Error 1
> 
> Compiling it with -gnatc returns no errors. I'm confused as to why it
> won't compile properly.
> 
> Thanks,
> Luke.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkl/HIMACgkQVIZi0A5BZF54lACfc5F2dF6qW6WJarlqrDDI19cE
/3QAn03PIsifQjamX13o50FCBZmpy00R
=sx51
-----END PGP SIGNATURE-----



^ permalink raw reply	[relevance 0%]

* cannot generate code for file a-excach.adb (subunit)
@ 2009-01-27 14:21  4% Lucretia
  2009-01-27 14:38  0% ` xavier grave
  0 siblings, 1 reply; 200+ results
From: Lucretia @ 2009-01-27 14:21 UTC (permalink / raw)


Hi,

In my attempts to enable exceptions in my test kernel, I've come
across a problem when building up my configurable runtime.

x86_64-unknown-elf-gcc -fno-pic -c -nostdinc -I. -ffunction-sections -
fdata-sections -gnato -gnatE -m32 -g2 -gnatf -gnatu -gnatv -gnatpg a-
excach.adb

GNAT 4.3.0
Copyright 1992-2007, Free Software Foundation, Inc.

Unit name                        File name                     Time
stamp
---------                        ---------
----------

Ada (spec)                       ada.ads
20070406091342
Ada.Exceptions (spec)            a-except.ads
20070606104609
Ada.Exceptions (body)            a-except.adb
20071213102130
Ada.Exceptions.Call_Chain (body) a-excach.adb
20051115140645
Ada.Unchecked_Conversion (spec)  a-unccon.ads
20070406091342
System (spec)                    system.ads
20090127135815
System.Exceptions (spec)         s-except.ads
20070912115821
System.Parameters (spec)         s-parame.ads
20090127133535
System.Soft_Links (spec)         s-soflin.ads
20071213103411
System.Stack_Checking (spec)     s-stache.ads
20070912115821
System.Standard_Library (spec)   s-stalib.ads
20070912115821
System.Storage_Elements (spec)   s-stoele.ads
20070912115821
System.Traceback (spec)          s-traceb.ads
20070912115821
System.Traceback_Entries (spec)  s-traent.ads
20070912115821
System.Wch_Con (spec)            s-wchcon.ads
20071213102052
System.Wch_Stw (spec)            s-wchstw.ads
20071213102130

cannot generate code for file a-excach.adb (subunit)
to check subunit for errors, use -gnatc

Compiling: a-excach.adb (source file time stamp: 2005-11-15 14:06:45)
 76 lines: No errors
make: *** [a-excach.o] Error 1

Compiling it with -gnatc returns no errors. I'm confused as to why it
won't compile properly.

Thanks,
Luke.



^ permalink raw reply	[relevance 4%]

* Re: Restarting Tread: Why isn't this program working with Unchecked_Converstion
  @ 2009-01-16 23:14  6%   ` sjw
  0 siblings, 0 replies; 200+ results
From: sjw @ 2009-01-16 23:14 UTC (permalink / raw)


On Jan 16, 12:18 pm, "Stuart" <stu...@0.0> wrote:
> "ChristopherL" <clusard...@aol.com> wrote in message
>
> news:83d19cd8-71ca-43c1-a3eb-05832290e565@r36g2000prf.googlegroups.com...
>
> > I'm restarting the tread [How to put 200 into an integer sub-type of
> > 16 bits (code included)] with a new subject because the last was too
> > long!
>
> <snip problem with Unchecked_Conversion>
>
> > I want to copy bits from an Ada float to a user defined short integer
> > maintaining the same bit representation.

(I'm sorry to reply to Stuart's post rather than OP's, but Google
fails to show OP's posts at all! (perhaps there's a reason for that?))

Sorry to shout, Chris, but you CAN NOT FIT THE BITS OF A STANDARD
FLOAT INTO ANYTHING SMALLER!!! IF YOU WANT THE SAME BIT REPRESENTATION
YOU HAVE TO USE THE SAME NUMBER OF BITS!!!

The following is another way of achieving unchecked conversion - the
results on a little-endian machine (i686) are

 2.00000E+02 ->  0  0  72  67
 3.14159E+00 ->  219  15  73  64

with Ada.Numerics;
with Ada.Text_IO; use Ada.Text_IO;
with System.Storage_Elements;

procedure Foo is
   F : Float;
   A : System.Storage_Elements.Storage_Array (1 .. 4);
   for A'Address use F'Address;
   pragma Import (Ada, A);  -- prevent unwanted auto-initialisations
   function Image (B : System.Storage_Elements.Storage_Element) return
String
     renames System.Storage_Elements.Storage_Element'Image;
begin
   F := 200.0;
   Put_Line (Float'Image (F)
               & " -> "
               & Image (A (1))
               & " "
               & Image (A (2))
               & " "
               & Image (A (3))
               & " "
               & Image (A (4)));
   F := Ada.Numerics.Pi;
   Put_Line (Float'Image (F)
               & " -> "
               & Image (A (1))
               & " "
               & Image (A (2))
               & " "
               & Image (A (3))
               & " "
               & Image (A (4)));
end Foo;





^ permalink raw reply	[relevance 6%]

* Re: Adding offset to 'Address
    @ 2008-09-12 15:23  6% ` Adam Beneschan
  1 sibling, 0 replies; 200+ results
From: Adam Beneschan @ 2008-09-12 15:23 UTC (permalink / raw)


On Sep 12, 1:35 am, Kim Rostgaard Christensen <k...@greenpc.dk> wrote:
> Hi
>
> How does one go about setting a 'Address + (size of other record) to a
> record at runtime ?
>
> In brief, I am switching over "Frametype" in a Ethernet frame record, to
> dynamically assign the next record by type (IPv4,IPv6,ARP, etc.)
> My "datablob" is a *u_char from a imported C function.
>
> So I have:
>
>   Raw_Bytes : access Unsigned_Char
>   for Ethernet_Header'Address use Raw_Bytes.all'Address;
>
> and additionally need something like:
>   for IP_Packet'Address use Raw_Bytes.all'Address + Ethernet_Header'Size;

Well, 'Size gives you a value in bits, not bytes, so this needs to be
changed.  The value in "storage units" (which is 8-bit bytes on most
machines but is occasionally something different) would be given by

  (Ethernet_Header'Size + System.Storage_Unit - 1) /
System.Storage_Unit

which rounds the size in bits up to the next multiple of
System.Storage_Unit.  [System.Storage_Unit will equal 8 on most
systems.]

Then, there's a "+" function in System.Storage_Elements that adds an
Address to a Storage_Offset and yields an Address (and another "+"
function that takes the arguments in the other order).  If you say
"use System.Storage_Elements" or "use type
System.Storage_Elements.Storage_Offset", then you can say

for IP_Packet'Address use Raw_Bytes.all'Address +
  ((Ethernet_Header'Size + System.Storage_Unit - 1) /
System.Storage_Unit);

assuming that the IP packet always starts at the next memory location
after the Ethernet_Header.

                                  -- Adam





^ permalink raw reply	[relevance 6%]

* Re: Adding offset to 'Address
  @ 2008-09-12 11:18  4%     ` petter_fryklund
  0 siblings, 0 replies; 200+ results
From: petter_fryklund @ 2008-09-12 11:18 UTC (permalink / raw)


On 12 Sep, 12:17, Kim Rostgaard Christensen <k...@greenpc.dk> wrote:
> Georg Bauhaus wrote:
> > Kim Rostgaard Christensen wrote:
> >> Hi
>
> >> How does one go about setting a 'Address + (size of other record) to a
> >> record at runtime ?
>
> > Have you had a chance to look at Interfaces.C.Pointers?
>
> > -- Georg Bauhaus
>
> I have thought about it, yes - but I cannot figure out witch datatype I
> should instantiate my pointer with (other than Byte & Byte_Array).
>
> Can you give an example ?
>
> regards
> Kim Rostgaard Christensen

System.Storage_Elements can be useful for arithmetic on 'Address.



^ permalink raw reply	[relevance 4%]

* Re: Problems with Ada.Streams.Read (blocking)
  @ 2008-08-08 18:00  4%   ` Dennis Hoppe
  0 siblings, 0 replies; 200+ results
From: Dennis Hoppe @ 2008-08-08 18:00 UTC (permalink / raw)


Hi Dmitri,

thank you for your reply, but it does not solve my problem. You just 
encapsulate the challenge in a nicer way. The application stops
at runtime while invoking Ada.Streams.Read to often, again.

I corrected your snippet to be compatible with my test-framework.


with Ada.Text_IO;
with Ada.Streams; use Ada.Streams;
with GNAT.Sockets; use GNAT.Sockets;
use type Ada.Streams.Stream_Element_Count;
with System.Storage_Elements; use System.Storage_Elements;

procedure Test is
   Client: Socket_Type;
   Address: Sock_Addr_Type;
   Channel: Stream_Access;
   Data   : Ada.Streams.Stream_Element_Array (1 .. 2);
   Offset : Ada.Streams.Stream_Element_Count := 1;

   procedure Read_Record (
       Channel : in out Stream_Access;
       Buffer  : in out Stream_Element_Array;
       Last    : out Stream_Element_Offset)  is
     Index : Stream_Element_Offset := 1;
     Has_CR : Boolean := False;
   begin
     while Index in Buffer'Range loop
       Ada.Streams.Read (Channel.all, Buffer, Index);
       if Has_CR and then
	Stream_Element'Pos (Buffer (Index)) = Character'Pos (ASCII.LF)
       then
	Last := Index - 2;
         return;
       else
	Has_CR :=
          Stream_Element'Pos (Buffer (Index)) = Character'Pos (ASCII.CR);
       end if;
     end loop;
     raise Constraint_Error; -- Too large packet
   end Read_Record;

begin
    Initialize;
    Create_Socket(Client);
    Address.Addr := Inet_Addr("127.0.0.1");
    Address.Port := 21;
    Connect_Socket (Client, Address);
    Channel := Stream (Client);

    Read_Record (Channel, Data, Offset);

    for I in 1 .. Offset loop
      Ada.Text_IO.Put (Character'Val (Data(I)));
    end loop;
end Test;


The Ada specification mentions the following:

"The Read operation transfers stream elements from the specified stream 
to fill the array Item. Elements are transferred until Item'Length 
elements have been transferred, or until the end of the stream is 
reached. If any elements are transferred, the index of the last stream 
element transferred is returned in Last. Otherwise, Item'First - 1 is 
returned in Last. Last is less than Item'Last only if the end of the 
stream is reached."

(<http://www.adaic.org/standards/05aarm/html/AA-13-13-1.html>)


Actually, some invocation of Ada.Streams.Read (Channel.all, Buffer, 
Index) should lead to

   Index < Buffer'Last

if the end of the stream is reached. This is never the case, because 
"read" is blocking, if not all elements in Buffer could be filled up.
If Buffer is Buffer(1..1), Index went never to 0, for example.

I am now able to read line per line sent by the ftp server, but if
I only once invoke my read method to often, the whole program hangs up
due to the blocking behavior of Ada.Stream.Read.


Best regards,
   Dennis



^ permalink raw reply	[relevance 4%]

* Re: Allocators and memory reclamation
  2008-01-28 22:27  5%   ` Maciej Sobczak
@ 2008-01-28 23:54  0%     ` Adam Beneschan
  0 siblings, 0 replies; 200+ results
From: Adam Beneschan @ 2008-01-28 23:54 UTC (permalink / raw)


On Jan 28, 2:27 pm, Maciej Sobczak <see.my.homep...@gmail.com> wrote:

> I understand that I can create my own pool with any behaviour I need.
> Let's try:
>
> with Ada.Text_IO;
> with Ada.Finalization;
> with System.Storage_Pools;
> with System.Storage_Elements;
>
> procedure Main is
>
>    use System.Storage_Pools;
>
>    -- used to acquire reference to the standard storage pool
>    type Integer_Ptr is access Integer;
>
>    procedure Test is
>
>       type My_Type is new Ada.Finalization.Controlled with null
> record;
>
>       procedure Finalize (T : in out My_Type) is
>       begin
>          Ada.Text_IO.Put_Line ("Finalize");
>       end Finalize;
>
>       use System;
>
>       type My_Pool_Type is new Root_Storage_Pool with null record;
>
>       procedure Allocate (Pool : in out My_Pool_Type;
>                           Storage_Address : out Address;
>                           Size_In_Storage_Elements : in
> Storage_Elements.Storage_Count;
>                           Alignment : in
> Storage_Elements.Storage_Count);
>       procedure Deallocate (Pool : in out My_Pool_Type;
>                             Storage_Address : in Address;
>                             Size_In_Storage_Elements : in
> Storage_Elements.Storage_Count;
>                             Alignment : in
> Storage_Elements.Storage_Count);
>       function Storage_Size (Pool : in My_Pool_Type) return
> Storage_Elements.Storage_Count;
>
>       procedure Allocate (Pool : in out My_Pool_Type;
>                           Storage_Address : out Address;
>                           Size_In_Storage_Elements : in
> Storage_Elements.Storage_Count;
>                           Alignment : in
> Storage_Elements.Storage_Count) is
>       begin
>          Allocate (Integer_Ptr'Storage_Pool, Storage_Address,
> Size_In_Storage_Elements, Alignment);
>          Ada.Text_IO.Put_Line ("allocating " &
>                                Storage_Elements.Storage_Count'Image
> (Size_In_Storage_Elements));
>       end Allocate;
>
>       procedure Deallocate (Pool : in out My_Pool_Type;
>                             Storage_Address : in Address;
>                             Size_In_Storage_Elements : in
> Storage_Elements.Storage_Count;
>                             Alignment : in
> Storage_Elements.Storage_Count) is
>       begin
>          Deallocate (Integer_Ptr'Storage_Pool, Storage_Address,
> Size_In_Storage_Elements, Alignment);
>          Ada.Text_IO.Put_Line ("deallocating");
>       end Deallocate;
>
>       function Storage_Size (Pool : in My_Pool_Type) return
> Storage_Elements.Storage_Count is
>       begin
>          return Storage_Size (Integer_Ptr'Storage_Pool);
>       end Storage_Size;
>
>       My_Pool : My_Pool_Type;
>
>       type My_Type_Ptr is access My_Type;
>       for My_Type_Ptr'Storage_Pool use My_Pool;
>
>       P : My_Type_Ptr;
>
>    begin
>       Ada.Text_IO.Put_Line ("starting to allocate objects");
>       P := new My_Type;
>       P := new My_Type;
>       Ada.Text_IO.Put_Line ("finished with objects and leaving the
> scope");
>    end Test;
>
> begin
>    Ada.Text_IO.Put_Line ("Running test");
>    Test;
>    Ada.Text_IO.Put_Line ("Test finished");
> end Main;
>
> (the code has lengthy lines and can get broken in your readers)
>
> In the above example I tried to create my own pool that is backed up
> by the standard pool acquired from some dummy access type. The new
> pool just forwards all primitive operations to the standard pool and
> prints some messages to see what's going on.
> It looks like I got it correctly, because it compiles and even works:
>
> Running Test
> Starting To Allocate Objects
> Allocating  12
> Allocating  12
> Finished With Objects And Leaving The Scope
> Finalize
> Finalize
> Test Finished
>
> I understand (now) that two objects are allocated with the help of my
> own pool. Since nobody deallocated explicitly (no
> Unchecked_Deallocation was used), the Deallocate procedure was not
> called and the memory is effectively leaked. I could have remembered
> the allocated addresses and deallocate the dangling blocks in the
> finalizer of my own pool (it is controlled after all) and this way the
> pool would guard the memory and prevent the leak. It didn't, so
> effectively there is a leak.
> More precisely, the allocated blocks come from the standard pool and
> they will be deallocated when the whole program will finish.
>
> The interesting part is that finalizers of My_Type were called and
> this is even before the pool gets finalized itself (I've checked it by
> overriding Finalize for My_Pool_Type). This is good, because after
> that only raw memory remained to be reclaimed.
> The question is - who called the finalizers of allocated objects? Any
> AARM paragraphs for this would be welcome.

As Randy pointed out, 7.6.1(11) is the key; it discusses when objects
created by an <allocator> are finalized.  It also says that those
objects are finalized in an arbitrary order.

>
> > > Another question relates to the order of finalizing objects. If the
> > > storage pool is torn down when the access type goes out of scope, is
> > > the order of finalizing objects guaranteed?
>
> > AFAIK, it is not. Why should it be?
>
> Why not? :-)
>
> If not, then there is additional (automatic) question: how can I make
> it guaranteed? Since finalizers seem to be called by some magic, then
> I don't think there is any way for me to influence the behaviour here
> - at least not by providing my own pool, which does not even get a
> chance to have anything to say on this subject.

I'm not completely clear on what you are trying to accomplish.  Are
you trying to ensure that if you allocate a number of objects of a
controlled type, then when those objects are finalized, you want them
to be finalized in a particular order, for example in the reverse
order in which you allocated them?

If this is what you want, you'll need to invent your own solution, but
I think it's doable.  I can envision an implementation where all the
allocated records of a type are linked together in a list; then when
one of these is finalized according to 7.6.1(11), the Finalize routine
recognizes this and finalizes *all* of the objects in the linked list,
perhaps setting a flag in the records to indicate that the
finalization took place.  Then when the other objects are finalized
according to 7.6.1(11), the Finalize routine would recognize that the
finalization has already been done, and do nothing.  If you do this,
you can certainly control the order in which allocated objects are
finalized.  But I think something like this has to be done.  There's
nothing in the language that I  know of to assert any control over the
order in which allocated objects are finalized.

>
> There is a related problem which I've found while playing with the
> above code example: I cannot have a pointer to the standard pool.
> In other words, this:
>
> type Pool_Ptr is access Root_Storage_Pool'Class;
> PP : Pool_Ptr := Integer'Storage_Pool'Access;
>
> is not possible, because the standard storage pool is not aliased.
> How can I get a reference to the standard pool so that I don't have to
> repeat the "Integer'Storage_Pool" million times?
> What about this:
>
> P : Root_Storage_Pool'Class := Integer_Ptr'Storage_Pool;
>
> I expect that P will be a reference to the standard pool, not its copy
> (it cannot be a copy, because Root_Storage_Pool is limited). Is this
> reasoning correct?

No.  Declaring an object of a limited type does *not* create a
reference; it creates an object.  Here, the compiler will think you're
trying to make a copy of a limited object, and it will complain.  Try
"renames".


> Last but not least: does AARM 13.11/20 mean that the above program is
> incorrect? How to implement it correctly, then?

You're probably OK in this particular case, since you're simply
passing through the arguments that the compiler is passing to another
Deallocate.  But the potential for trouble is that when the
implementation generates code for an <allocator> or for a call to an
Unchecked_Deallocation instance, it may do other things besides call
Allocate or Deallocate, and a direct call to Allocate or Deallocate
doesn't do those things.  It seems unlikely to me that, for an
implementation, those "other things" would do anything that involves
the storage pool, which means that this pass-through usage should be
fine.  But I could be wrong.

                                  -- Adam



^ permalink raw reply	[relevance 0%]

* Re: Allocators and memory reclamation
  @ 2008-01-28 22:27  5%   ` Maciej Sobczak
  2008-01-28 23:54  0%     ` Adam Beneschan
  0 siblings, 1 reply; 200+ results
From: Maciej Sobczak @ 2008-01-28 22:27 UTC (permalink / raw)


On 28 Sty, 16:15, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:

> The language does not prescribe the effect of a call to Deallocate on the
> program's environment.

I'm not interested in the interaction on this level.
I'm interested in the pattern of calls to Deallocate in the given
program.
My understanding, initially, was that Deallocate is called kind of
implicitly when the storage pool is torn down together with its
associated access type.
It does not seem to be the case, but the storage pool itself can keep
track of the allocated blocks and at the end do "something" with them.
For example, the storage pool might be based on static memory block
that just gives new addresses for each Allocate and have empty
Deallocate - a fairly compliant implementation. When the pool goes out
of scope, so does its memory.

I understood that the memory that was used by the pool is deallocated
even in the following simple case:

type Integer_Ptr is access Integer;

but the AARM claims it can be otherwise (that the memory might be
bound to library-level pool).

I understand that I can create my own pool with any behaviour I need.
Let's try:

with Ada.Text_IO;
with Ada.Finalization;
with System.Storage_Pools;
with System.Storage_Elements;

procedure Main is

   use System.Storage_Pools;

   -- used to acquire reference to the standard storage pool
   type Integer_Ptr is access Integer;

   procedure Test is

      type My_Type is new Ada.Finalization.Controlled with null
record;

      procedure Finalize (T : in out My_Type) is
      begin
         Ada.Text_IO.Put_Line ("Finalize");
      end Finalize;

      use System;

      type My_Pool_Type is new Root_Storage_Pool with null record;

      procedure Allocate (Pool : in out My_Pool_Type;
                          Storage_Address : out Address;
                          Size_In_Storage_Elements : in
Storage_Elements.Storage_Count;
                          Alignment : in
Storage_Elements.Storage_Count);
      procedure Deallocate (Pool : in out My_Pool_Type;
                            Storage_Address : in Address;
                            Size_In_Storage_Elements : in
Storage_Elements.Storage_Count;
                            Alignment : in
Storage_Elements.Storage_Count);
      function Storage_Size (Pool : in My_Pool_Type) return
Storage_Elements.Storage_Count;

      procedure Allocate (Pool : in out My_Pool_Type;
                          Storage_Address : out Address;
                          Size_In_Storage_Elements : in
Storage_Elements.Storage_Count;
                          Alignment : in
Storage_Elements.Storage_Count) is
      begin
         Allocate (Integer_Ptr'Storage_Pool, Storage_Address,
Size_In_Storage_Elements, Alignment);
         Ada.Text_IO.Put_Line ("allocating " &
                               Storage_Elements.Storage_Count'Image
(Size_In_Storage_Elements));
      end Allocate;

      procedure Deallocate (Pool : in out My_Pool_Type;
                            Storage_Address : in Address;
                            Size_In_Storage_Elements : in
Storage_Elements.Storage_Count;
                            Alignment : in
Storage_Elements.Storage_Count) is
      begin
         Deallocate (Integer_Ptr'Storage_Pool, Storage_Address,
Size_In_Storage_Elements, Alignment);
         Ada.Text_IO.Put_Line ("deallocating");
      end Deallocate;

      function Storage_Size (Pool : in My_Pool_Type) return
Storage_Elements.Storage_Count is
      begin
         return Storage_Size (Integer_Ptr'Storage_Pool);
      end Storage_Size;

      My_Pool : My_Pool_Type;

      type My_Type_Ptr is access My_Type;
      for My_Type_Ptr'Storage_Pool use My_Pool;

      P : My_Type_Ptr;

   begin
      Ada.Text_IO.Put_Line ("starting to allocate objects");
      P := new My_Type;
      P := new My_Type;
      Ada.Text_IO.Put_Line ("finished with objects and leaving the
scope");
   end Test;

begin
   Ada.Text_IO.Put_Line ("Running test");
   Test;
   Ada.Text_IO.Put_Line ("Test finished");
end Main;

(the code has lengthy lines and can get broken in your readers)

In the above example I tried to create my own pool that is backed up
by the standard pool acquired from some dummy access type. The new
pool just forwards all primitive operations to the standard pool and
prints some messages to see what's going on.
It looks like I got it correctly, because it compiles and even works:

Running Test
Starting To Allocate Objects
Allocating  12
Allocating  12
Finished With Objects And Leaving The Scope
Finalize
Finalize
Test Finished

I understand (now) that two objects are allocated with the help of my
own pool. Since nobody deallocated explicitly (no
Unchecked_Deallocation was used), the Deallocate procedure was not
called and the memory is effectively leaked. I could have remembered
the allocated addresses and deallocate the dangling blocks in the
finalizer of my own pool (it is controlled after all) and this way the
pool would guard the memory and prevent the leak. It didn't, so
effectively there is a leak.
More precisely, the allocated blocks come from the standard pool and
they will be deallocated when the whole program will finish.

The interesting part is that finalizers of My_Type were called and
this is even before the pool gets finalized itself (I've checked it by
overriding Finalize for My_Pool_Type). This is good, because after
that only raw memory remained to be reclaimed.
The question is - who called the finalizers of allocated objects? Any
AARM paragraphs for this would be welcome.

> > Another question relates to the order of finalizing objects. If the
> > storage pool is torn down when the access type goes out of scope, is
> > the order of finalizing objects guaranteed?
>
> AFAIK, it is not. Why should it be?

Why not? :-)

If not, then there is additional (automatic) question: how can I make
it guaranteed? Since finalizers seem to be called by some magic, then
I don't think there is any way for me to influence the behaviour here
- at least not by providing my own pool, which does not even get a
chance to have anything to say on this subject.


There is a related problem which I've found while playing with the
above code example: I cannot have a pointer to the standard pool.
In other words, this:

type Pool_Ptr is access Root_Storage_Pool'Class;
PP : Pool_Ptr := Integer'Storage_Pool'Access;

is not possible, because the standard storage pool is not aliased.
How can I get a reference to the standard pool so that I don't have to
repeat the "Integer'Storage_Pool" million times?
What about this:

P : Root_Storage_Pool'Class := Integer_Ptr'Storage_Pool;

I expect that P will be a reference to the standard pool, not its copy
(it cannot be a copy, because Root_Storage_Pool is limited). Is this
reasoning correct?

Last but not least: does AARM 13.11/20 mean that the above program is
incorrect? How to implement it correctly, then?

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



^ permalink raw reply	[relevance 5%]

* Re: Default array base index
  @ 2008-01-28 17:02  2% ` Adam Beneschan
  0 siblings, 0 replies; 200+ results
From: Adam Beneschan @ 2008-01-28 17:02 UTC (permalink / raw)


On Jan 27, 11:20 am, Scott Burson <FSet....@gmail.com> wrote:
> Hi,
>
> I just came across this Wikipedia page:
>
> http://en.wikipedia.org/wiki/Comparison_of_programming_languages_%28a...
>
> which claims that the default base index for arrays in Ada is 1.  It
> has been over 15 years since I have written any Ada, so my memory is
> fuzzy, but what I recall is that there actually is no default: the
> base index must always be specified explicitly when the array is
> declared.  However, it does appear that Ada culture leans toward the
> use of 1 as a default (for example, the language numbers the
> dimensions of the array from 1 in attribute expressions).
>
> Do you agree?

There may be some small ways in which this is correct.  For example,
the predefined type String is defined with "Positive" as the index
subtype, which means you can't define a String subtype that starts at
index 0.  Of course, you can define one that starts at positive
integers larger than 1, but (without having read the article in
question) I suspect that this is part of a long-running debate over
whether it's "better" to start arrays and other sequences at 0 or 1
(as if there were one answer that fit every situation).  At least
once, I've seen articles in SIGPLAN or other places where an author
decided to number the sections, subsections, sub-subsections, etc., of
his article starting with section 0 instead of the more traditional 1,
apparently for no good reason except to declare which side of this
debate he was on.  So anyway, bases larger than 1 aren't really
relevant to this "culture" or stylistic issue.

Back to Ada, when I opened my Ada 95 RM to see if I could find other
predefined arrays, I did find this in A.9:

subtype Buffer_Type is
System.Storage_Elements.Storage_Array(1..Buffer_Size);

In general, though, I think the statement you quote is nonsense.  As
you mention, Ada doesn't really have a default base, and programmers
are free to choose whichever one suits the problem more.  In my own
code, when I don't have a particular reason to choose 1 or 0 as the
base, I tend to gravitate toward using 1, but I think that has less to
do with "Ada culture" and more to do with the fact that when I was one
year old and my mother started teaching me to count, she started with
"one" and not "zero".  Also, we always number everything else starting
with "first", "second", etc.; ever seen a baseball game played with
"zero-th base", "first base", and "second base"?  ("Who's on zero-
th?"  "Yes."
"I mean his name."  "Who."  "The guy on zero-th."  "Who."  "The zero-
th baseman."  "Who."  Just doesn't have the same ring to it.)  So it
isn't an "Ada culture" at all---it's the fact that using 1 seems more
natural, and that I get to use a language that gives me a choice,
rather than struggling with a low-level language like C that forces me
into unnatural behaviors like using 0 as the index base.

                               -- Adam






^ permalink raw reply	[relevance 2%]

* 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: Direct Quote from the RM
  2007-11-20 17:07  0%         ` Direct Quote from the RM Vadim Godunko
@ 2007-11-21  6:44  0%           ` anon
  0 siblings, 0 replies; 200+ results
From: anon @ 2007-11-21  6:44 UTC (permalink / raw)


>> Plus, not all project require Elaboration to be used.
>>
>Can you please provide an real example?

1. Since a persion was asking about "Ada OS" the other day!
   An Ada version of a Multi-Boot program simular to XP or LILO.

2. Another type can be partitions that use other language I/O and library 
   functions with or without the "pragma No_Run_Time;" statement. In 
   the GNAT examples there is a program called "use_of_import.adb" 
   which requires "impoerted_function.c".


In <a954e769-3822-4079-a77d-957d56be4a9e@d61g2000hsa.googlegroups.com>, Vadim Godunko <vgodunko@gmail.com> writes:
>On Nov 20, 4:43 pm, a...@anon.org (anon) wrote:
>>
>> So, teaching or using "gnatmake" is a waste of the newbee time!
>> Because most project require more than one or two extra packages!
>>
>1) gnatmake has special -jX command line switch, where X is a number
>of parallel gcc commands.
>
>1a) you may use classic make program and its parallel modifications.
>
>2) two dual core processors and 4Gb of RAM doesn't really many
>resources even for medium size projects. Real projects may utilize up
>to 3Gb of RAM per one compiler process.
>
>> 6. gnat compile s-stoele.adb -gnatpg -nostdinc
>>    This file is a child of system.  But where is the error?
>What are you expecting? You are _exactly_ ask _compiler_ rebuild
>specific file. Note, _compiler_! Compiler must prepare relevant
>elaboration code, but it doesn't responsible for partition elaboration
>at hole, ...
>
>> Note: Only if you "bind" a program that uses the
>>       System.Storage_Elements will you see the Error based
>>       on the "Elaboration rule" in this example.
>>
>.... bind program is responsible for generation of partition
>elaboration code.
>
>> Plus, not all project require Elaboration to be used.
>>
>Can you please provide an real example?




^ permalink raw reply	[relevance 0%]

* Re: Direct Quote from the RM
  2007-11-20 13:43  4%       ` anon
  2007-11-20 15:10  4%         ` parallel translation (was: Direct Quote from the RM) Georg Bauhaus
@ 2007-11-20 17:07  0%         ` Vadim Godunko
  2007-11-21  6:44  0%           ` anon
  1 sibling, 1 reply; 200+ results
From: Vadim Godunko @ 2007-11-20 17:07 UTC (permalink / raw)


On Nov 20, 4:43 pm, a...@anon.org (anon) wrote:
>
> So, teaching or using "gnatmake" is a waste of the newbee time!
> Because most project require more than one or two extra packages!
>
1) gnatmake has special -jX command line switch, where X is a number
of parallel gcc commands.

1a) you may use classic make program and its parallel modifications.

2) two dual core processors and 4Gb of RAM doesn't really many
resources even for medium size projects. Real projects may utilize up
to 3Gb of RAM per one compiler process.

> 6. gnat compile s-stoele.adb -gnatpg -nostdinc
>    This file is a child of system.  But where is the error?
What are you expecting? You are _exactly_ ask _compiler_ rebuild
specific file. Note, _compiler_! Compiler must prepare relevant
elaboration code, but it doesn't responsible for partition elaboration
at hole, ...

> Note: Only if you "bind" a program that uses the
>       System.Storage_Elements will you see the Error based
>       on the "Elaboration rule" in this example.
>
... bind program is responsible for generation of partition
elaboration code.

> Plus, not all project require Elaboration to be used.
>
Can you please provide an real example?



^ permalink raw reply	[relevance 0%]

* Re: parallel translation (was: Direct Quote from the RM)
  2007-11-20 13:43  4%       ` anon
@ 2007-11-20 15:10  4%         ` Georg Bauhaus
  2007-11-20 17:07  0%         ` Direct Quote from the RM Vadim Godunko
  1 sibling, 0 replies; 200+ results
From: Georg Bauhaus @ 2007-11-20 15:10 UTC (permalink / raw)


On Tue, 2007-11-20 at 13:43 +0000, anon wrote:
> For Georg Bauhaus
> 
> As for parallel, I was talking about compiling up to 3_000 packages or 
> files used in a partition for a computer system with 4GB.

OK. This was my understanding, too.

> Task 1 in memmory -> (copy #1 of gnat compiler system) + (package 1) 
> Task 2 in memmory -> (copy #2 of gnat compiler system) + (package 2) 
> Task 3 in memmory -> (copy #3 of gnat compiler system) + (package 3) 
>   ...
> Task N in memmory -> (copy #4 of gnat compiler system) + (package N) 

Right. Now,

with P2;
package P1 is
   ...
end P1;

P1 (in file "p1.ads", say) depends on P2 (in file "p2.ads", say).
I am assuming that Task 1 is supposed to compile P1, and task 2
is supposed to compile P2. An elaboration order will have to be
established in order to translate almost anything. Here, for
example, task 1 (compiling P1) must know what is in P2 (compiled
in task 2) because P1 depends on P2. How do the compilers etc.
communicate?

> For "Elaboration rule"! Well try this:

Why should a programmer new to Ada mess with compiler files?
And how will the GNAT specifics of System.Storage_Elements and
special processing of System affect the package dependences in an
Ada project?





^ permalink raw reply	[relevance 4%]

* Re: Direct Quote from the RM
  @ 2007-11-20 13:43  4%       ` anon
  2007-11-20 15:10  4%         ` parallel translation (was: Direct Quote from the RM) Georg Bauhaus
  2007-11-20 17:07  0%         ` Direct Quote from the RM Vadim Godunko
  0 siblings, 2 replies; 200+ results
From: anon @ 2007-11-20 13:43 UTC (permalink / raw)


For Georg Bauhaus

As for parallel, I was talking about compiling up to 3_000 packages or 
files used in a partition for a computer system with 4GB. Not all parallel 
operations are about threads or a thread hopping onto different 
processor's job schedulers. In this parallel design the system can contain 
up to 3_000 copies of "gcc", "gnat1" and "as" in memory and excuting 
in parallel design with each other to utilize the cpu and memory to the 
fullest! In other words,

Task 1 in memmory -> (copy #1 of gnat compiler system) + (package 1) 
Task 2 in memmory -> (copy #2 of gnat compiler system) + (package 2) 
Task 3 in memmory -> (copy #3 of gnat compiler system) + (package 3) 
  ...
Task N in memmory -> (copy #4 of gnat compiler system) + (package N) 

Note: "gnat compiler system" is "gcc" and "gnat1" and as", which is 
done by the "gnat compile" command or "gcc -c".  

In this design it does not matter the number of processors or the number 
of threads. This can be done by creating a script file like (linux version):

#script
#
gnat compile <name1>.adb &
gnat compile <name2>.adb &
gnat compile <name3>.adb &
..
gnat compile <nameN>.adb &
#
#end script


Usage of the Swapper file must be turn off. Swapping defeat the purpose. 
And you may have to up the priority of the background tasks but that not 
a problem either. Also I could of used "gcc -c" but that too much like C 
programming. so I choose not too use it. 

Note: "gnatmake" or "make" can not be setup in this way to preform is 
type of parallel processing. 


Now as for "gnatmake" try this "gnatmake *".  It does not work in 
Linux/FreeBSD.  So, to compile packages before you create the main 
program you must use "gnat compile" or better yet "gcc -c". Also, If you 
have more than a couple of packages you normally build a script file to 
compile the code, which can easily be turn into loading multiple copies of 
the compiler and fully use the system resources aka parallel compiling. 
Then when you build the main procedure out of habit you will again use 
the "gcc -c" or "gnat compile" instead of "gnatmake" and then 
"gnatbind" and then "gnatlink".

So, teaching or using "gnatmake" is a waste of the newbee time! 
Because most project require more than one or two extra packages!


For "Elaboration rule"! Well try this:

1. create a temporary dir
2. cd to that temporary dir
3. copy system.ads to this temporary dir.
4. copy s-stoele.ad* to this temporary dir    
   -- System.Storage_Elements package for example.
5. edit system.ads and remove the comment at the top of the file.
 Note: Any child package should, by the "Elaboration rules" force the 
       operator to recompile system.ads first.

6. gnat compile s-stoele.adb -gnatpg -nostdinc
   This file is a child of system.  But where is the error?
7. gnat compile system.ads -gnatpg -nostdinc

Note: Only if you "bind" a program that uses the 
      System.Storage_Elements will you see the Error based 
      on the "Elaboration rule" in this example.

Plus, not all project require Elaboration to be used.


In <4740d5f0$0$27131$9b4e6d93@newsspool1.arcor-online.net>, Georg Bauhaus <rm.tsoh+bauhaus@maps.futureapps.de> writes:
>anon wrote:
>
>> "Any proposed construct whose implementation was unclear or that required 
>> excessive machine resources was rejected." That statement suggest that 
>> "gnatmake" in using requires 5 complete programs to be loaded at one time 
>> just to compile a single routine or package when 3 to 3 will do should be 
>> rejected!
>
>I had been under the impression that Ada was designed for software
>systems of more than one compilation unit...
>
>
>> Note: Parallel => I mean the number of complete compilers loaded and 
>> running in core (no swapper file usage) at the same time.
>
>I'm curious about the elaboration rules when a compilation system
>of 3_000 complete compilers is working on the same source at the
>same time (not using gnatmake).
>How many compilation units would be under the control of the
>3_000 compilers in this example? How do they get organized?
>
> > Note: The "make -jN" or "gnatmake -jN" does not allow multiple
> > compilers to be loaded in core at the same time.
>
>Ehr, why is that?
>"`-jn'
>   Use n processes to carry out the (re)compilations. On a
>   multiprocessor machine compilations will occur in parallel."




^ permalink raw reply	[relevance 4%]

* Re: copying data between memory locations
  @ 2007-09-04 15:57  3%   ` Adam Beneschan
  0 siblings, 0 replies; 200+ results
From: Adam Beneschan @ 2007-09-04 15:57 UTC (permalink / raw)


On Sep 3, 3:38 am, Martin Krischik <krisc...@users.sourceforge.net>
wrote:
> jef.mangelsch...@gmail.com schrieb:
>
> > 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.
>
> straightforward and highly dangerous.
>
> > I can't figure out a way to do this in Ada (at least not Ada83).
>
> You just have not found the right features yet. Suggested reading:
>
> http://en.wikibooks.org/wiki/Ada_Programming/Types/access#Access_vs._...http://en.wikibooks.org/wiki/Ada_Programming/Type_System#Address_conv...http://en.wikibooks.org/wiki/Ada_Programming/Type_System#Overlays
>
> and from the reference manual:
>
> http://www.adaic.com/standards/05rm/html/RM-13-7-2.html#I4643http://www.adaic.com/standards/05rm/html/RM-13-3.html#I4496
>
> As you can see (once you read the articles) you have even got two
> options open and now you are left with choosing the right one ;-).

Unfortunately, most of the features you've referred to are not
available in Ada 83, and the original poster hinted that he needed an
Ada 83 way to accomplish this.

In Ada 83, you'll need to do something like:

   type Byte_Array is array (1 .. Num_Bytes) of Byte;
--or--
   subtype Byte_Array is BYTE_ARRAY_TYPE (1 .. Num_Bytes);
   Dest : Byte_Array;
   for Dest use at Buffer_Details(idx) + Offset;

   Dest := Data;

I don't know what "data" is, but if its type is an unconstrained array
whose length is guaranteed to be Num_Bytes, the above assignment will
work; otherwise you'll need a slice, like

   Dest := Data (Data'First .. Data'First + Num_Bytes - 1);

I also don't know that "Buffer_Details(idx) + Offset" will work.
Probably not.  Someone already pointed out that
System.Storage_Elements is available in Ada 95 (and later) to do this
sort of address arithmetic, but in Ada 83 you have to invent your own
method.  If you know that a System.Address type is represented as just
a simple address whose size is the same as an Integer, then using
Unchecked_Conversion to convert System.Address to an Integer, add
Offset to it, and convert it back to System.Address may be necessary.
If a System.Address is more complicated, you'll need a more
complicated method.  Of course, anything you do is likely to be non-
portable but that's probably not your concern.

I agree with others that trying to deal with addresses directly like
this *may* be evidence of a poor design decision; it's better to try
to see if Ada has nicer features for accomplishing something than to
assume you have to do things the same way you do it in C.  (I've seen
a lot of needlessly horrendous Ada code written by programmers who
still tried to do things the C way.)  I say *may* because we can't say
for sure, without knowing more about your particular problem.  Also,

rant: begin

I'd like to gripe about those who respond to a question like this by
telling them how they should have designed their program in the first
place, rather than by answering their question.  We do want Ada to be
used in the Real World, after all (we do, right?), and the Real World
can be messy sometimes---sometimes you have to come up with a quick
solution to cope with a previous poor design decision, because your
customer has a problem and can't wait for you to rewrite a billion
lines of code or whatever to make the design nice and clean and
perfect.  I've had to do ugly things like that.  Ada generally
provides ways to get around problems like this, and this is a strength
of the language rather than a weakness, despite the fact that these
features are things you're better off not using if you don't have to.
Anyway, maybe a better design is feasible in this particular poster's
case and maybe it isn't.  But I'm afraid that being unhelpful could
help scare programmers back to using C.

end rant;

                        -- Adam








^ permalink raw reply	[relevance 3%]

* Re: copying data between memory locations
    @ 2007-09-03 11:09  3% ` Niklas Holsti
  1 sibling, 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 3%]

* Re: Byte streams
  @ 2007-08-03  5:34  5% ` 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 5%]

* Re: Does 3.9.3(10) apply to untagged private whose full view is tagged?
  @ 2007-07-26  8:58  3% ` anon
  0 siblings, 0 replies; 200+ results
From: anon @ 2007-07-26  8:58 UTC (permalink / raw)


Compiling: pak1.ads (source file time stamp: 2007-07-25 03:45:40)

     1. package Pak1 is
     2.    type T1 is private ;
     3. 
     4. private
     5.    type T1 is tagged record
     6.       F1 : Integer ;
     7.   end record ;
     8.   function Func ( X : Integer ) return T2 ;
                                               |
        >>> "T2" is undefined

     9. end Pak1;
    10. 

T2 must be defined.  So, assume T2 is a typo for T1

Compiling: pak1.ads (source file time stamp: 2007-07-25 03:27:16)

     1. package Pak1 is
     2.    type T1 is private;
     3. 
     4. private
     5.    type T1 is tagged record
     6.       F1 : Integer;
     7.   end record;
     8.   function Func (X : Integer) return T1 ;
                   |
        >>> private function with tagged result must override visible-part function
        >>> move subprogram to the visible part (RM 3.9.3(10))

     9. end Pak1;
    10. 

GNAT is correct!  A better example of how to write is type 
of code is System.Storage_Pools package (RM 13.11) which 
uses the System.Storage_Elements package (RM 13.7.1).


Ada 95: RM 3.9.3 (10) says 
10   For an abstract type declared in a visible part, an abstract primitive
subprogram shall not be declared in the private part, unless it is overriding
an abstract subprogram implicitly declared in the visible part.  For a tagged
type declared in a visible part, a primitive function with a controlling
result shall not be declared in the private part, unless it is overriding a
function implicitly declared in the visible part.

In your code there is no function or abstract subprogram that is 
implicitly declared in the visible part! So the code result is a 
compiler error.


Note: AARM is for compiler developers, so it has changes which may 
or may not be valid in the L(RM). Also, since there are 3 current 
83/95/2005 specifications use should denote which version you are 
talking about. Because some things are valid in 83 that are not in 
95/2005, while others are only valid in 2005. And with GNAT 
inter-mixing specifications it can be confusing without using the 
GNAT language specifiction pragma.



In <1185401098.912519.245650@z28g2000prd.googlegroups.com>,  Adam Beneschan <adam@irvine.com> writes:
>I think the following is legal, but the version of GNAT I'm using
>rejects it, citing 3.9.3(10):
>
>package Pak1 is
>   type T1 is private;
>private
>   type T1 is tagged record
>      F1 : Integer;
>  end record;
>  function Func (X : Integer) return T2;
>end Pak1;
>
>3.9.3(10) says, in part, "For a tagged type declared in a visible
>part, a primitive function with a controlling result shall not be
>declared in the private part, unless it is overriding a function
>implicitly declared in the visible part."  My interpretation, though,
>is that it doesn't apply here, and that it only applies to types that
>are *visibly* tagged in the visible part---not to untagged private
>types whose full view is tagged.  The AARM reasoning for the rule has
>to do with other packages that declare type extensions of the type
>that wouldn't know that there's a private function that needs to be
>overridden---but in this case, other packages (except for private
>children, which have access to the entire private part of Pak1) can't
>declare a type extension of T1; so it would make sense that the rule
>wouldn't apply to this code.  Anyway, that's my interpretation, but it
>seems within the realm of possibility to interpret it the other way.
>
>So who's right?  Me or GNAT?
>
>                           -- Adam
>




^ permalink raw reply	[relevance 3%]

* Alternative Index implementation? (Was: Reading and writing a big file in Ada (GNAT) on Windows XP)
  @ 2007-05-04  6:53  5%       ` Jacob Sparre Andersen
  0 siblings, 0 replies; 200+ results
From: Jacob Sparre Andersen @ 2007-05-04  6:53 UTC (permalink / raw)


Simon Wright <simon.j.wright@mac.com> wrote:

> That was me. I could give you my version of Index if you want ..

I would like to have a copy as well.

My demonstration of how you can make a fast implementation of the Unix
command "tail" with POSIX.Memory_Mapping was not very successful, and
I suspect that the sinner may be Index.

Greetings,

Jacob
-- 
Ada - the programming language still ahead of its time.

-- tail1.adb - show the last ten lines from a named text file

with Ada.Characters.Latin_1;
with Ada.Command_Line;
with Ada.Strings.Fixed;
with Ada.Text_IO;
with POSIX;
with POSIX.IO;
with POSIX.Memory_Mapping;
with System;
with System.Storage_Elements;

procedure Tail is
   use POSIX;
   use POSIX.IO;
   use POSIX.Memory_Mapping;
   use System.Storage_Elements;

   Text_File    : File_Descriptor;
   Text_Size    : System.Storage_Elements.Storage_Offset;
   Text_Address : System.Address;
begin
   Text_File := Open (Name => To_POSIX_String (Ada.Command_Line.Argument (1)),
                      Mode => Read_Only);
   Text_Size := Storage_Offset (File_Size (Text_File));
   Text_Address := Map_Memory (Length     => Text_Size,
                               Protection => Allow_Read,
                               Mapping    => Map_Shared,
                               File       => Text_File,
                               Offset     => 0);

   declare
      use Ada.Strings;
      use Ada.Strings.Fixed;
      package Latin_1 renames Ada.Characters.Latin_1;
      Bit_Count       : constant Natural :=
                          Natural (Text_Size) * Storage_Element'Size;
      Character_Count : constant Natural :=
                          Bit_Count / Character'Size;

      Text : String (1 .. Character_Count);
      for Text'Address use Text_Address;
      Last : Natural := Text'Last + 1;
   begin
      for Lines in 1 .. 10 loop
         Last := Index (Source  => Text (Text'First .. Last - 1),
                        Pattern => (1 => Latin_1.LF),
                        Going   => Backward);
         exit when Last = 0;
      end loop;

      declare
         POSIX_Text : POSIX_String (Text'Range);
         for POSIX_Text'Address use Text'Address;
      begin
         while Last < Text'Last loop
            NONSTANDARD_Write
              (File   => Standard_Output,
               Buffer => POSIX_Text (Last + 1 .. Text'Last),
               Last   => Last);
         end loop;
      end;
   end;

   Unmap_Memory (First  => Text_Address,
                 Length => Text_Size);
   Close (File => Text_File);
end Tail;



^ permalink raw reply	[relevance 5%]

* Re: Finding out minimal allocation unit
  @ 2007-04-06 17:17  5%                 ` Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2007-04-06 17:17 UTC (permalink / raw)


Stefan Bellon <sbellon@sbellon.de> writes:

> Well, our idea was to build a generic storage pool which can handle
> only memory chunks of one size. And the generic storage pool is
> instantiated with that size as generic parameter. So that each data
> structure instance (be it a list, a tree, hash table, ...) has its
> own storage pool with the exact Item_Type'Size instantiated.

I have a feeling that generics were problematic when I tried something
like this -- but you can always use a constraint:

   with System.Storage_Pools;
   with System.Storage_Elements;

   package BC.Support.Managed_Storage is

      pragma Elaborate_Body;

      package SSE renames System.Storage_Elements;
      package SSP renames System.Storage_Pools;

      type Pool (Chunk_Size : SSE.Storage_Count) is
        new SSP.Root_Storage_Pool with private;

from the Booch Components (this particular pool has a bug filed
against it at the moment, caused by a perceived need to allocate
variously-sized items from within large chunks and the resulting need
to chain the free list through chunks ...)



^ permalink raw reply	[relevance 5%]

* Re: Finding out minimal allocation unit
    @ 2007-04-06 12:38  6%         ` Stephen Leake
  1 sibling, 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 6%]

* Re: Text Processing in Ada 95
  @ 2007-02-23  7:53  3% ` Jacob Sparre Andersen
  0 siblings, 0 replies; 200+ results
From: Jacob Sparre Andersen @ 2007-02-23  7:53 UTC (permalink / raw)


Rob Norris wrote:

> Suppose I have a text file such as:
>
> tom
> dick
> harry
>
> Then I want to insert the line "dave" after tom so the file is
>
> tom
> dave
> dick
> harry
>
> Also suppose text file can get rather large.
>
> Currently I'm using text_io which means I have to copy the whole
> thing into memory, insert the line then over write the file with new
> contents. direct_io is not an option (varing string lengths)
>
> What alternatives should I consider for making insertions faster?
> (NB retrieval of a line needs to be fairly quick as well).

I would first of all consider using POSIX.Memory_Mapping.Map_Memory to
get access to the complete file as an in-memory string.  Here is a
piece of code I wrote recently for that purpose:

   Name         : POSIX_String;
   Text_File    : File_Descriptor;
   Text_Size    : System.Storage_Elements.Storage_Offset;
   Text_Address : System.Address;
begin
   [...]
   Text_File := Open (Name => Name,
                      Mode => Read_Only);
   Text_Size := Storage_Offset (File_Size (Text_File)); -- + Inserted_Size ?
   Text_Address := Map_Memory (Length     => Text_Size,
                               Protection => Allow_Read,
                               Mapping    => Map_Shared,
                               File       => Text_File,
                               Offset     => 0);

   declare
      Bit_Count       : constant Natural :=
                          Natural (Text_Size) * Storage_Element'Size;
      Character_Count : constant Natural :=
                          Bit_Count / Character'Size;

      Text : String (1 .. Character_Count);
      for Text'Address use Text_Address;
   begin

My reason for suggesting that you map the file into memory is that you
can avoid messing with buffers, caching and several copies of the file
content.

If you need to make lots of insertions, then I would consider mapping
the lines into a insertion-friendly data structure such as a linked
list.  This data structure should keep track of 'First and 'Last for
each line in the file.  Inserting new lines would simply be a matter
of writing the text of the lines to the end of the "Text" string, and
inserting a pointer at the appropriate place in the data structure
keeping track of the lines.

The costly part of this method is to write back the lines to the file.
Since it will have to be done one line at a time.  Depending on the
number of insertions needed, it may be cheaper simply to do the
insertions with plain string slices on "Text".

Greetings,

Jacob
-- 
"I've got _plenty_ of common sense!"
"I just choose to ignore it."



^ permalink raw reply	[relevance 3%]

* Re: Reading Float Data from a binary file into ada
  @ 2007-02-01  0:05  4%       ` Jeffrey R. Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey R. Carter @ 2007-02-01  0:05 UTC (permalink / raw)


frikk wrote:
> 
> So my main question at this point is: How do I create the equivelant
> of this:
> union float_union
> {
>   float x;
>   unsigned char c[4];
> };

That's pretty simple. You put your input bytes into

subtype Raw_Bytes is System.Storage_Elements.Storage_Array (1 .. 4);

Raw : constant Raw_Bytes := Reorder (Get_Bytes (Raw_Bytes'Length) );

(Raw is in the proper order, of course). You define

function To_Float is new Ada.Unchecked_Conversion
    (Source => Raw_Bytes, Target => Interfaces.C.C_Float);

and then

Result : constant Interfaces.C.C_Float := To_Float (Raw);

You probably want that in some application-friendly type, though, so 
you'd really do something like

Result : constant My_Type := My_Type (To_Float (Raw) );

Finally

return Result;

This can end up being one of those functions where everything's done in 
the declarations.

-- 
Jeff Carter
"Alms for an ex-leper!"
Monty Python's Life of Brian
75



^ permalink raw reply	[relevance 4%]

* A novel design of linked lists (was: Address of an object)
@ 2006-09-19 13:30  3% Dmitry A. Kazakov
  0 siblings, 0 replies; 200+ results
From: Dmitry A. Kazakov @ 2006-09-19 13:30 UTC (permalink / raw)


[ 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.

An alternative to these two variants would be to add links transparently
without intervening with *what* is the element. Ada's pools provide this
functionality. The package could go as follows:

with System;                   use System;
with System.Storage_Elements;  use System.Storage_Elements;
with System.Storage_Pools;     use System.Storage_Pools;

generic
   type List_Identification_Type is (<>);
   type List_Item_Type (<>) is limited private;
   Pool : in out Root_Storage_Pool'Class;
package Generic_Linked_Lists is

Here:

- List_Identification_Type is an enumeration type to name the lists. An
element may participate in exactly one list corresponding to the given
value of List_Identification_Type.
- List_Item_Type is the type of elements.
- Pool is the pool where elements will be eventually allocated

The package defines its own pool type, which takes memory from another pool
and the object Items_Pool of this type bound to the actual pool passed as
the generic formal parameter Pool. [ It would be nice to default it to the
standard pool, but, I don't know any good way to do it. ]

   type Items_Storage_Pool (Host : access Root_Storage_Pool'Class) is
      new Root_Storage_Pool with null record;
   ...
   Items_Pool : Items_Storage_Pool (Pool'Access);

Then it defines a pointer type to refer the list items:

   type Item_Ptr is access List_Item_Type;
   for Item_Ptr'Storage_Pool use Items_Pool;

Then it defines the list operations in the terms of this pointer type. Note
that unlikely to Ada.Containers the semantics is referential. Nothing is
copied. So Insert looks like:

   procedure Insert
             (  List  : List_Identification_Type;
                Head  : in out Item_Ptr;
                Item  : Item_Ptr;
                Order : Item_Disposition := After
             );

- List identifies the list type we are dealing with. The same item can be
situated in as many lists as the range of List_Identification_Type.

- Head is the pointer to the list. In can be null. when the first item is
inserted.

- Item is the pointer to the item to insert.

- Order is an enumeration After or Before. When Item is placed before Head,
Head is set to Item.

The use of Insert is trivial and need not to be illustrated. A new Item is
created using plain "new." Other operations could be:

   procedure Move
             (  List   : List_Identification_Type;
                Target : in out Item_Ptr;
                Item   : Item_Ptr;
                Source : in out Item_Ptr;
                Order  : Item_Disposition := After
             );

Moves Item form one list to another. Both lists are of the same type.

   function Next
            (  List : List_Identification_Type;
               Item : Item_Ptr
            )  return Item_Ptr;

Returns the next item in the list

   function Previous
            (  List : List_Identification_Type;
               Item : Item_Ptr
            )  return Item_Ptr;

   procedure Remove
             (  List : List_Identification_Type;
                Head  : in out Item_Ptr; 
                Item  : Item_Ptr;
                Order : Item_Disposition := After
             );

Removes Item from the list.

For dealing with the elements of one list type without specifying the type,
a small wrapper package could be provided:

generic
   List : List_Identification_Type;
package Generic_Linked_Lists.Generic_List is
   type List_Ptr is new Item_Ptr;
   procedure Insert
             (  Head  : in out List_Ptr;
                Item  : Item_Ptr;
                Order : Item_Disposition := After
             );
   procedure Move
             (  Target : in out List_Ptr;
                Item   : Item_Ptr;
                Source : in out List_Ptr;
                Order  : Item_Disposition := After
             );
   function Next (Item : Item_Ptr)  return List_Ptr;
   function Previous (Item : Item_Ptr) return List_Ptr;
   procedure Remove
             (  Head  : in out List_Ptr; 
                Item  : Item_Ptr;
                Order : Item_Disposition := After
             );
end Generic_Linked_Lists.Generic_List;

Note that locally defined List_Ptr is a "list specific" pointer, while Item
is a sort of "class-wide" pointer, valid across all list types. So Item in
all calls is just a pointer to an item, while Head controls "dispatch" to
the proper list. [ Of course no dynamic dispatch happens. It is a static
polymorphism. ]

Now how this works. When an element is allocated, Allocate of
Items_Storage_Pool places the array of links

   type List_Header is record
      Next : Address;
      Prev : Address;
   end record;
   type Item_Header is array (List_Identification_Type) of List_Header;

in front of it. Allocate looks like this:

   procedure Allocate
             (  Pool            : in out Items_Storage_Pool;
                Storage_Address : out Address; 
                Size            : Storage_Count;
                Alignment       : Storage_Count
             )  is
      Header_Alignment : constant Storage_Count :=
         Storage_Count'Max (Item_Header'Alignment, Alignment);
      Header_Offset    : constant Storage_Offset :=
         Header_Size + (-Header_Size) mod Header_Alignment;
   begin
      Allocate -- Grab memory in the host pool
      (  Pool.Host.all,
         Storage_Address,
         Size + Header_Offset,
         Header_Alignment
      );
      Storage_Address := Storage_Address + Header_Offset;
      declare
         Header : Item_Header renames To_Header (Storage_Address).all;
      begin
         for List in Header'Range loop
            Header (List).Next := Null_Address; -- Links initialization
         end loop;
      end;
   end Allocate;

When Next, Insert etc are called Item_Header is obtained from the pointer
and, the rest is obvious. For example Next:

   function Next
            (  List : List_Identification_Type;
               Item : Item_Ptr
            )  return Item_Ptr is
   begin
      return To_Item_Ptr (To_Header (From_Item_Ptr (Item)) (List).Next);
   end Next;

It works perfectly well for all types except ones for which the compiler
mangles pointers, as I have explained in other thread.

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



^ permalink raw reply	[relevance 3%]

* call procedure in Linux-Ada-module from "normal" program
@ 2006-08-24 16:33  3% Frank
  0 siblings, 0 replies; 200+ results
From: Frank @ 2006-08-24 16:33 UTC (permalink / raw)



Hi
Debian sarge kernel 2.4.27, gcc-3.3

I've been tinkering with modules by using Ada.
The module compiles, and I manage to do insmod on it.
The symbols appears in ksyms; like "some_call_me".

Now I wish to call "some_call_me" from the test program (3) - is that 
possible?

I compile it with "gnatmake test_somemodule.adb"
It fails during linking :

gnatbind -x test_somemodule.ali
gnatlink test_somemodule.ali
./test_somemodule.o(.text+0x1f): In function `_ada_test_somemodule':
: undefined reference to `some_call_me'
collect2: ld returned 1 exit status
gnatlink: cannot call /usr/bin/gcc-3.3
gnatmake: *** link failed.


How do I make the linker link with the kernel symbol?


Frank





-----------
1 (slightly edited in this post)
--------------------------------------------------------------------------------------------------------------
with Interfaces.C;

package SomeModule is

  -- Module Variables

  type Aliased_String is array (Positive range <>) of aliased Character;
  pragma Convention (C, Aliased_String);

  Kernel_Version: constant Aliased_String:="2.4.27-2-386" & 
Character'Val(0);
  pragma Export (C, Kernel_Version, "kernel_version");

  Mod_Use_Count: Integer;
  Pragma Export (C, Mod_Use_Count, "mod_use_count_");

  -- Kernel Calls

  procedure Printk( s : string );
  pragma import( C, printk, "printk" );

-- Our Module Functions

  function Init_Module return Interfaces.C.int;
  pragma Export (C, Init_Module, "init_module");

  procedure Cleanup_Module;
  pragma Export (C, Cleanup_Module, "cleanup_module");

  procedure Call_Me;
  Pragma Export (C, Call_Me, "some_call_me");

end SomeModule;


with Interfaces.C;

with System.Machine_Code; use System.Machine_Code;

--with System.Storage_Elements;

with Interfaces; use Interfaces;

2 (slightly edited in this post)
--------------------------------------------------------------------------------------------------------------
package body SomeModule is



  function Init_Module return Interfaces.C.int is
  begin
    Printk("Hello,World! Hi Frank" & Character'val(10) & character'val(0));
    return 0;
  end Init_Module;

  procedure Cleanup_Module is
  begin
    Printk("Goodbye , World! Bye Frank!" & Character'val(10) & 
character'val(0));
  end Cleanup_Module;

  procedure Call_Me
  is
  begin
    Printk("Call me" & Character'val(10) & character'val(0));
  end Call_Me;

end SomeModule;

3
-------------------------------------------------------------------------------------------------------------------------

procedure test_somemodule
is
  procedure Call_Me;
  pragma Import (C, Call_Me, "some_call_me");
begin
  text_io.put_line("Test_Somemodule");
  Call_Me;
end test_somemodule; 





^ permalink raw reply	[relevance 3%]

* "User-Defined Assignment" question
@ 2006-08-12  8:05  4% Yves Bailly
  0 siblings, 0 replies; 200+ results
From: Yves Bailly @ 2006-08-12  8:05 UTC (permalink / raw)


Hello all,

Here's a behaviour that sounds strange to me. After carefully reading
the ARM (7.6), I'm not sure if it's legal or not.

Here's a package spec:
--8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<---
with Ada.Finalization; use Ada.Finalization;
with System.Storage_Elements; use System.Storage_Elements;
package Pkg is
   type T is new Controlled with
   record
      self: Integer_Address;
      id  : Natural;
   end record;
   overriding
   procedure Initialize(tt: in out T);
   overriding
   procedure Adjust(tt: in out T);
   overriding
   procedure Finalize(tt: in out T);
end Pkg;
--8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<---

Here's the body:
--8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<---
with Ada.Text_IO; use Ada.Text_IO;
package body Pkg is

   overriding
   procedure Initialize(tt: in out T) is
   begin
      tt.self := To_Integer(tt.id'Address);
      Put_Line("Initialize " &
         Integer_Address'Image(tt.self));
   end Initialize;
    
   overriding
   procedure Adjust(tt: in out T) is
   begin
      tt.self := To_Integer(tt.id'Address);
      Put_Line("Adjust " &
         Integer_Address'Image(tt.self));
   end Adjust;
   
   overriding
   procedure Finalize(tt: in out T) is
   begin
      tt.self := To_Integer(tt.id'Address);
      Put_Line("Finalize " &
         Integer_Address'Image(tt.self));
   end Finalize;

end Pkg;
--8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<---

So basically, each procedure prints a message showing which instance of
Pkg.T it is given.

Now a small test program:
--8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<---
with Ada.Text_IO; use Ada.Text_IO;
with Pkg;
procedure Test is
   function Func return Pkg.T is
      dummy: Pkg.T;
   begin
      Put_Line("    Func");
      return dummy;
   end Func;
   tt_1: Pkg.T;
begin
   Put_Line("----- START");
   tt_1 := Func;
   Put_Line("----- END");
end Test;
--8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<---

And finally the output:
--8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<---
Initialize  3218775648
----- START
Initialize  3218775520
    Func
Adjust  134660136
Finalize  3218775520
Finalize  3218775648
Adjust  3218775648
Finalize  134660136
----- END
Finalize  3218775648
--8<-----8<-----8<-----8<-----8<-----8<-----8<-----8<---

What seems strange to me is that there is an "Adjust" and a "Finalize"
call on an object which has never been "Initialize"d... look at the
instance identified by 134660136. I guess is some temporary anonymous
object. If I understand well ARM 7.6, the clause 7.6-23/2 seems to tell
that omitting the Initialize call is *not* permitted...

What do you think?

This has been tested using GNAT 2006.

Best regards,

-- 
(o< | Yves Bailly  : http://kafka-fr.net   | -o)
//\ | Linux Dijon  : http://www.coagul.org | //\
\_/ |                                      | \_/`



^ permalink raw reply	[relevance 4%]

* Re: How to pass two dimensional arrays to C
  @ 2006-07-30 11:18  5%           ` Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2006-07-30 11:18 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.not.jrcarter@acm.not.spam.org> writes:

> So to my mind, and using the notation I've described here, the row
> elements are contiguous. So I don't know whether we agree or
> disagree.

We agree, I think.

I don't remember the last time I wrote anything to do with matrices,
which is some sort of explanation; if you have a 4x4 state transition
table it's not an issue!

with Ada.Text_IO; use Ada.Text_IO;
with System.Storage_Elements; use System.Storage_Elements;
procedure Rows_And_Columns is
   package Address_IO is new Modular_IO (Integer_Address); use Address_IO;
   type Matrix is array (Integer range <>, Integer range <>) of Integer;
   M : Matrix (0 .. 2, 0 .. 3);
begin
   for A in M'Range (1) loop
      for B in M'Range (2) loop
         Put (To_Integer (M (A, B)'Address));
      end loop;
      New_Line;
   end loop;
end Rows_And_Columns;

grendel:~/tmp simon$ ./rows_and_columns 
 3221223544 3221223548 3221223552 3221223556
 3221223560 3221223564 3221223568 3221223572
 3221223576 3221223580 3221223584 3221223588

so the last index is the one that has contiguous elements. I guess I
have never looked up 'row-major order' before.



^ permalink raw reply	[relevance 5%]

* Re: Separate type for byte arrays
  @ 2006-05-04 18:15  4% ` Jeffrey R. Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey R. Carter @ 2006-05-04 18:15 UTC (permalink / raw)


Florian Weimer wrote:
> 
> I'm not interested in machines which use strange character sets such
> as EBCDIC, or machines whose storage unit or stream element size is
> not 8 bit.

It's not clear what you're asking. I would think all low-level I/O would 
be done in terms of bytes/storage elements/stream elements; anything 
else (such as String) would be a higher-level abstraction on top of this.

Anyway, given an 8-bit machine, you probably want 
System.Storage_Elements.Storage_Array or 
Ada.Streams.Stream_Element_Array rather than your own byte array type. 
Note that conversions to and from Storage_Array can be done with 
Ada.Storage_IO, avoiding Unchecked_Conversion. Similar things can be 
done with Streams, but it takes a bit more work than using Storage_IO.

-- 
Jeff Carter
"All citizens will be required to change their underwear
every half hour. Underwear will be worn on the outside,
so we can check."
Bananas
29



^ permalink raw reply	[relevance 4%]

* Re: Don't use the "use" clause
  @ 2005-11-19 22:33  4%                       ` Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2005-11-19 22:33 UTC (permalink / raw)


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

> What about the time spent on reading something like A.B.C.D.E.F.G.H?

As used in the GNAT sources, for example ..

  package SSE renames System.Storage_Elements;

within a reasonably short local scope (a page or two, perhaps).



^ permalink raw reply	[relevance 4%]

* Re: Re-exporting primitive operations of a private type (like "-", and 'min)
  @ 2005-10-31  8:27  3%     ` Niklas Holsti
  0 siblings, 0 replies; 200+ results
From: Niklas Holsti @ 2005-10-31  8:27 UTC (permalink / raw)


Anonymous Coward wrote:
>>The whole point of private types is that the only visible operations
>>on them are assignment, equality and inequality, and any explicitly
>>defined operations in the visible part of the package
>>specification. 
> 
> 
> That makes sense.  As a default, it probably would be a poor language
> design to have private types automatically export public primitive
> operations.  If I created an Altitude_Type, I wouldn't want to inherit
> the "+" operation.

The following is perhaps not quite on the original topic, but this 
thread reminds me of an idea for a new feature related to private 
types that I would like to present.

My Ada packages often define types that are *mostly* private in 
the sense that I only want the clients to use a restricted set of 
operations and properties of the type. However, I often do not 
make these types actual private types because I want to reveal 
some properties, such as discreteness, that I cannot now specify 
for a private type.

I would like to be able to reveal some properties of private types 
in the same way as we can now define generic formal types, for 
example saying that the type is discrete (type T is (<>)) or is a 
modular type (type T is mod <>). So I would like to write, for 
example, a package like this:

    package P is

       type Element is private (<>);
       -- This is not Ada. The intended meaning is that type
       -- Element is private, but is a discrete type.

       -- Some operations using Element.

    private

       type Element is (This, That, The_Other);
       -- See, Element is really a discrete type.

    end P;

Other (client) packages can then use the fact that P.Element is a 
discrete type, for example by using P.Element as an index type:

    with P;

    package Client is

       type Set is array (P.Element) of Boolean;
       ...
    end Client;

However, the whole definition of P.Element would still be hidden, 
so clients could not refer for example to P.Element'(P.This).

There would be a pleasing symmetry in this new feature if the 
properties that could be revealed about a private type would match 
exactly the properties that can now be defined for a generic 
formal type. A private type with some properties revealed in this 
way could then be used as the actual type to instantiate a generic 
with a formal type that has matching properties.

There are even some places in the Ada LRM where the proposed 
feature would be useful. For example, the LRM (95) now defines, in 
13.7.1:

    package System.Storage_Elements is
       ...
       type Storage_Offset is range "implementation defined";
       ...
       type Storage_Element is mod "implementation defined";
       ...
    end System.Storage_Elements;

With the new feature, the "implementation defined" pseudocode 
could be replaced by real code:

       type Storage_Offset is private range <>;  -- Not Ada.
       type Storage_Element is private mod <>;   -- Not Ada.

The full type declarations would be in the private part of the 
package, as usual.

In such declarations, the "private" keyword is perhaps 
unnecessary, since the presence of the box "<>" shows that the 
declared type is partly hidden.

Does this idea appeal to anyone?

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



^ permalink raw reply	[relevance 3%]

* Re: hashed_maps
  @ 2005-10-14  4:49  4%     ` Matthew Heaney
  0 siblings, 0 replies; 200+ results
From: Matthew Heaney @ 2005-10-14  4:49 UTC (permalink / raw)


Robert A Duff <bobduff@shell01.TheWorld.com> writes:

> Addresses usually have the low 2 or 3 bits equal to zero, because of
> alignment concerns.  So use Address_To_Integer and shift right 3 bits.
> Then mod by the size of the hash table, or take some high-order bits
> and add them into the low-order bits.

In the case of the standard hashed containers, I'm not sure you would
need to bother, since the mod'ing is done internally by the container.

I think you'd only need to right shift if you were to throw away upper
bits, say because System.Storage_Elements.Integer_Address has a wider
range than Ada.Containers.Hash_Type.



^ permalink raw reply	[relevance 4%]

* Re: hashed_maps
  @ 2005-10-14  4:41  4%             ` Matthew Heaney
  0 siblings, 0 replies; 200+ results
From: Matthew Heaney @ 2005-10-14  4:41 UTC (permalink / raw)


"Lucretia" <lucretia9@lycos.co.uk> writes:

> Now, I just need to know that what I'm doing with the ordered map
> isn't going to generate a linked list in which the search will end up
> linear as new C++ types are allocated as the key will be the address
> of the C++ instance. Should a hashed map be used, if so, how do you do
> this?  I've only seen examples of hashing with strings.

The container standard guarantees that associative containers must
perform better than O(n), so a linked list would not be an acceptable
implementation.

It's probably quicker and easier to use the ordered map, since the "<"
operator for type Address is declared right there in package System.

If you want to use a hash table, then you can use To_Integer declared in
System.Storage_Elements to implement a hash function for type Adddress.
The generic actual for Equivalent_Keys is just "=".



^ permalink raw reply	[relevance 4%]

* Re: ++ of C in ada
  @ 2005-07-25 20:15  4% ` 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 4%]

* Re: GCC 4.0 Ada.Containers Cursor danger.
  @ 2005-07-16  1:45  3%                                   ` Matthew Heaney
  0 siblings, 0 replies; 200+ results
From: Matthew Heaney @ 2005-07-16  1:45 UTC (permalink / raw)


"Dmitriy Anisimkov" <anisimkov@yahoo.com> writes:

> So Ada.Containers is an "Adaified STL". 

Yes.


> Cursors in the C++ STL looks normally, because it looks like high
> level analog of the pointer arithmetic.

The pointer arithmetic in C conforms to the "machine model."  Iterators
in the C++ STL look like pointer arithmetic, because both follow the
machine model.

You can do pointer arithmetic in Ada too (see System.Storage_Elements),
so there's nothing special about C++ here.


> I don't think that such analog should be ported into Ada, where was no
> pointer arithmetic due to the safety reasons.

But Ada does support pointer arithmetic.

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.


> I think [that if] runtime checks of the Ada cursors are worse, then do
> not use the cursors at all.

But didn't just complain that there were too few checks?  Do you want
the library to detect dangling cursors, or not?

I can only speak about the GCC implementation (I am its author), but the
overhead of a cursor compared to the overhead of a raw access type is
minimal.

I have recently started adding additional checks to detect dangling
cursors, that are enabled via pragma Assert.

You don't have to guess about whether using a cursor instead of an
access type is less efficient, since you can just read the sources
yourself.  You can get the sources from either of these sites:

<http://charles.tigris.org/>
<http://gcc.gnu.org/>


> If programmer wants to keep pointer to container elements in the
> somewhere else, he should put elements into container dynamically
> allocated, and have an access to it whereever he need.

You appear to not understand the machine model, upon which the library
is based.  I recommend reading about the design of the STL.

I thought you didn't like things that aren't safe?  Your suggestion to
use raw access types is *less* safe than using cursors, since the
programmer would have to assume responsability for memory management.

Of course, the current library design doesn't preclude your approach.
If you don't like cursors, then don't use them...



^ permalink raw reply	[relevance 3%]

* Re: Interrupt handler seems not to be called in GNAT 3.15p
  2005-06-15 15:39  2% Interrupt handler seems not to be called in GNAT 3.15p Thorsten
@ 2005-06-16  6:52  0% ` David C. Hoos, Sr.
  0 siblings, 0 replies; 200+ results
From: David C. Hoos, Sr. @ 2005-06-16  6:52 UTC (permalink / raw)
  To: Thorsten; +Cc: comp.lang.ada

Did you use the pragma Unreserved_all_Interrupts?

See the discussion of that Pragma un the GNAT Reference Manual
----- Original Message ----- 
From: "Thorsten" <thorsten.behrens@dorunth.de>
Newsgroups: comp.lang.ada
To: <comp.lang.ada@ada-france.org>
Sent: June 15, 2005 10:39 AM
Subject: Interrupt handler seems not to be called in GNAT 3.15p


> Hi!
> 
> I'm currently writing a small package that does a memory dump in an
> 'od' like format. The program is compiled using GNTA 3.15p under Win2k,
> but will be compiled with AdaMulti as well and shall later on run on a
> special hardware.
> 
> When accessing memory, I might not have access to some memory location.
> I've therefore implemented an interrupt handler to take care of
> SIGSEGV. This, however, does not seem to be called - at least not under
> Windows (I haven't tested on the target hardware yet, because it has to
> run under Windows as well).
> 
> Running the program with gdb, I can see SIGSEGV being raised. However,
> it is not passed to my interrupt handler, but causes the program to
> terminate (as is the "normal" behaviour defined for SIGSEGV).
> 
> Here's some code snippets which to me seem quite OK ;-)
> 
> package body MONITOR is
>  ...
>  -- Definition of signal handler to react on SIGSEGV. The procedure
>  -- HANDLE_SIGSEGV just sets the boolean variable and returns
>  -- therafter to handle the interrupt with a minimum of time. Whether
>  -- or not an interrupt occured can be checked with entry
>  -- SIGSEGV_RAISED, which is callable then.
>  protected SIGNAL_HANDLER is
>    pragma UNRESERVE_ALL_INTERRUPTS;
>    procedure HANDLE_SIGSEGV;
>    pragma INTERRUPT_HANDLER(HANDLE_SIGSEGV);
>    entry SIGSEGV_RAISED;
>  private
>    SIGSEGV_RECEIVED : BOOLEAN := FALSE;
>  end SIGNAL_HANDLER;
> 
>  protected body SIGNAL_HANDLER is
>    procedure HANDLE_SIGSEGV is
>    begin
>       SIGSEGV_RECEIVED := TRUE;
>    end HANDLE_SIGSEGV;
> 
>    entry SIGSEGV_RAISED when SIGSEGV_RECEIVED is
>    begin
>      IO_PACKAGE.PUT_LINE("There was a SIGSEGV");
>      SIGSEGV_RECEIVED := FALSE;
>    end SIGSEGV_RAISED;
>  end SIGNAL_HANDLER;
> 
>  ...
> 
> begin
> 
>  ...
> 
>  if not ATTACHED_SIGSEGV then
>    if not ADA.INTERRUPTS.IS_RESERVED(SIGSEGV) then
>      begin
>        NEW_SIGSEGV_HANDLER := SIGNAL_HANDLER.HANDLE_SIGSEGV'ACCESS;
>        ADA.INTERRUPTS.EXCHANGE_HANDLER(OLD_SIGSEGV_HANDLER,
>                                        NEW_SIGSEGV_HANDLER,
>                                        SIGSEGV);
>        ATTACHED_SIGSEGV := TRUE;
>      exception
>        when THE_ERROR: PROGRAM_ERROR =>
>          IO_PACKAGE.PUT_LINE
>            ("SIGNAL_HANDLER installation: " &
>             ADA.TEXT_IO.UTIL.LINE_TERMINATION_STRING &
>             ADA.EXCEPTIONS.EXCEPTION_INFORMATION(THE_ERROR));
>          raise;
>      end;
>    end if;
>  end if;
> 
>  ...
> 
>  -- THE_BUFFER is an array of SYSTEM.STORAGE_ELEMENTs
>  for I in THE_BUFFER'RANGE loop
>  begin
>    -- Access storage only once (i.e. THE_BUFFER(I) is only acessed
>    -- here). We add this to the previous value of STORAGE_ELEMENT
>    -- (which is 0 in case we format the output in bytes and may hold
>    -- the values of upper (double)word(s) in other cases).
>    STORAGE_ELEMENT := THE_BUFFER(I);
> 
>    -- Test, whether there was a segmentation violation when accessing
>    -- memory. If it was, the entry of our signal handler is callable
>    -- and we will set STORAGE_ELEMENT to 0. Otherwise everything is
>    -- fine.
>    select
>      SIGNAL_HANDLER.SIGSEGV_RAISED;
>      STORAGE_ELEMENT := 0;
>    else
>      null;
>    end select;
> 
>  exception
>    when THE_ERROR: others =>
>      IO_PACKAGE.DEBUG("Exception " &
>                       ADA.EXCEPTIONS.EXCEPTION_NAME(THE_ERROR) &
>                       " is raised when accessing memory!");
>      STORAGE_ELEMENT := 0;
>  end;
> 
>  ...
> 
> end MONITOR;
> 
> When running the program SIGSEGV is raised twice (which I can see only
> in gdb) for the same memory location and the program terminates. If I
> put a delay 5.0 (or some other time) statement just before accessing
> the memory, I also get the output of the exception handler, which
> means an exception (PROGRAM_ERROR) is raised.
> 
> Can anyone give me a hint? Is this a known problem with GNAT 3.15p?
> Is it possible to handle SIGSEGV at all in this environment?
> 
> Regards,
> Thorsten
> 
> _______________________________________________
> comp.lang.ada mailing list
> comp.lang.ada@ada-france.org
> http://www.ada-france.org/mailman/listinfo/comp.lang.ada
> 
>



^ permalink raw reply	[relevance 0%]

* Interrupt handler seems not to be called in GNAT 3.15p
@ 2005-06-15 15:39  2% Thorsten
  2005-06-16  6:52  0% ` David C. Hoos, Sr.
  0 siblings, 1 reply; 200+ results
From: Thorsten @ 2005-06-15 15:39 UTC (permalink / raw)


Hi!

I'm currently writing a small package that does a memory dump in an
'od' like format. The program is compiled using GNTA 3.15p under Win2k,
but will be compiled with AdaMulti as well and shall later on run on a
special hardware.

When accessing memory, I might not have access to some memory location.
I've therefore implemented an interrupt handler to take care of
SIGSEGV. This, however, does not seem to be called - at least not under
Windows (I haven't tested on the target hardware yet, because it has to
run under Windows as well).

Running the program with gdb, I can see SIGSEGV being raised. However,
it is not passed to my interrupt handler, but causes the program to
terminate (as is the "normal" behaviour defined for SIGSEGV).

Here's some code snippets which to me seem quite OK ;-)

package body MONITOR is
  ...
  -- Definition of signal handler to react on SIGSEGV. The procedure
  -- HANDLE_SIGSEGV just sets the boolean variable and returns
  -- therafter to handle the interrupt with a minimum of time. Whether
  -- or not an interrupt occured can be checked with entry
  -- SIGSEGV_RAISED, which is callable then.
  protected SIGNAL_HANDLER is
    pragma UNRESERVE_ALL_INTERRUPTS;
    procedure HANDLE_SIGSEGV;
    pragma INTERRUPT_HANDLER(HANDLE_SIGSEGV);
    entry SIGSEGV_RAISED;
  private
    SIGSEGV_RECEIVED : BOOLEAN := FALSE;
  end SIGNAL_HANDLER;

  protected body SIGNAL_HANDLER is
    procedure HANDLE_SIGSEGV is
    begin
       SIGSEGV_RECEIVED := TRUE;
    end HANDLE_SIGSEGV;

    entry SIGSEGV_RAISED when SIGSEGV_RECEIVED is
    begin
      IO_PACKAGE.PUT_LINE("There was a SIGSEGV");
      SIGSEGV_RECEIVED := FALSE;
    end SIGSEGV_RAISED;
  end SIGNAL_HANDLER;

  ...

begin

  ...

  if not ATTACHED_SIGSEGV then
    if not ADA.INTERRUPTS.IS_RESERVED(SIGSEGV) then
      begin
        NEW_SIGSEGV_HANDLER := SIGNAL_HANDLER.HANDLE_SIGSEGV'ACCESS;
        ADA.INTERRUPTS.EXCHANGE_HANDLER(OLD_SIGSEGV_HANDLER,
                                        NEW_SIGSEGV_HANDLER,
                                        SIGSEGV);
        ATTACHED_SIGSEGV := TRUE;
      exception
        when THE_ERROR: PROGRAM_ERROR =>
          IO_PACKAGE.PUT_LINE
            ("SIGNAL_HANDLER installation: " &
             ADA.TEXT_IO.UTIL.LINE_TERMINATION_STRING &
             ADA.EXCEPTIONS.EXCEPTION_INFORMATION(THE_ERROR));
          raise;
      end;
    end if;
  end if;

  ...

  -- THE_BUFFER is an array of SYSTEM.STORAGE_ELEMENTs
  for I in THE_BUFFER'RANGE loop
  begin
    -- Access storage only once (i.e. THE_BUFFER(I) is only acessed
    -- here). We add this to the previous value of STORAGE_ELEMENT
    -- (which is 0 in case we format the output in bytes and may hold
    -- the values of upper (double)word(s) in other cases).
    STORAGE_ELEMENT := THE_BUFFER(I);

    -- Test, whether there was a segmentation violation when accessing
    -- memory. If it was, the entry of our signal handler is callable
    -- and we will set STORAGE_ELEMENT to 0. Otherwise everything is
    -- fine.
    select
      SIGNAL_HANDLER.SIGSEGV_RAISED;
      STORAGE_ELEMENT := 0;
    else
      null;
    end select;

  exception
    when THE_ERROR: others =>
      IO_PACKAGE.DEBUG("Exception " &
                       ADA.EXCEPTIONS.EXCEPTION_NAME(THE_ERROR) &
                       " is raised when accessing memory!");
      STORAGE_ELEMENT := 0;
  end;

  ...

end MONITOR;

When running the program SIGSEGV is raised twice (which I can see only
in gdb) for the same memory location and the program terminates. If I
put a delay 5.0 (or some other time) statement just before accessing
the memory, I also get the output of the exception handler, which
means an exception (PROGRAM_ERROR) is raised.

Can anyone give me a hint? Is this a known problem with GNAT 3.15p?
Is it possible to handle SIGSEGV at all in this environment?

Regards,
Thorsten




^ permalink raw reply	[relevance 2%]

* Re: Hashing on System.Address
  2005-06-14  7:18  0%   ` Duncan Sands
@ 2005-06-14 15:18  0%     ` Matthew Heaney
  0 siblings, 0 replies; 200+ results
From: Matthew Heaney @ 2005-06-14 15:18 UTC (permalink / raw)




Duncan Sands wrote:
> > Use System.Storage_Elements.To_Integer to convert the address to an
> > Integer_Address, and then convert that to type Hash_Type.
>
> that's what I'm doing.  But there's no guarantee that they have the
> same size, so it's not portable.

Even if the Integer_Address type is 64 bits, that doesn't necessarily
mean To_Address will return values > 2**32.  The easiest thing is to do
is just throw away the upper 32 bits of of the integer value, and then
convert that to type Hash_Type.

Yes, then means you won't have a perfect hash function, but that's
typical for hash functions anyway.  (The Birthday Paradox applies to
hash functions too, I think.)

You might want to post your question on comp.compilers or one of the OS
newgroups.  This is most probably a solved problem.

-Matt




^ permalink raw reply	[relevance 0%]

* Re: Hashing on System.Address
  2005-06-14  2:22  0%     ` Matthew Heaney
@ 2005-06-14  8:44  0%       ` Larry Kilgallen
  0 siblings, 0 replies; 200+ results
From: Larry Kilgallen @ 2005-06-14  8:44 UTC (permalink / raw)


In article <u8y1dllt8.fsf@earthlink.net>, Matthew Heaney <matthewjheaney@earthlink.net> writes:
> Robert A Duff <bobduff@shell01.TheWorld.com> writes:
> 
>> "Matthew Heaney" <mheaney@on2.com> writes:
>> > Use System.Storage_Elements.To_Integer to convert the address to an
>> > Integer_Address, and then convert that to type Hash_Type.
>> 
>> It might be a good idea to divide that by 8, since most addresses have
>> zeros in the low three bits.
> 
> Good idea.  The other thing I haven't really figured out is what to do
> if you have a 64-bit address, and Hash_Type is only 32.  Ideally you'd
> like to compute a 32-bit hash value that uses all 64 bits of the
> address.

I think ignoring the high bits is better than ignoring the low bits,
since most data sets are likely to be somewhat localized.



^ permalink raw reply	[relevance 0%]

* Re: Hashing on System.Address
  2005-06-13 23:41  0%   ` Robert A Duff
  2005-06-14  2:22  0%     ` Matthew Heaney
@ 2005-06-14  8:42  0%     ` Larry Kilgallen
  1 sibling, 0 replies; 200+ results
From: Larry Kilgallen @ 2005-06-14  8:42 UTC (permalink / raw)


In article <wcc3brlrfj5.fsf@shell01.TheWorld.com>, Robert A Duff <bobduff@shell01.TheWorld.com> writes:
> "Matthew Heaney" <mheaney@on2.com> writes:
> 
>> Duncan Sands wrote:
>> > Does anyone have an efficient portable algorithm for hashing
>> > on a System.Address?
>> >
>> > The Ada 2005 package Ada.Containers defines Hash_Type as
>> >
>> > 	type Hash_Type is mod implementation-defined;
>> >
>> > This is the target type I would like for the hash.
>> 
>> Use System.Storage_Elements.To_Integer to convert the address to an
>> Integer_Address, and then convert that to type Hash_Type.
> 
> It might be a good idea to divide that by 8, since most addresses have
> zeros in the low three bits.

Or it might not be, since he said portable.  Looking at addresses of
_instructions_ (which are the closest to that pattern) on the machine
architectures on which VMS runs:

	VAX - No restriction, 1 bit (odd and even) just as likely to be
		one as the other
	Alpha - 4 byte boundary, 4 bit (100) just as likely to be one
		as the other
	Itanium - 8 byte boundary for VLIW instructions, but in software
		the last octet of the address is 0, 1 or 2 depending on
		which instruction in the bundle is addressed.



^ permalink raw reply	[relevance 0%]

* Re: Hashing on System.Address
  2005-06-13 21:57  4% ` Matthew Heaney
  2005-06-13 23:41  0%   ` Robert A Duff
@ 2005-06-14  7:18  0%   ` Duncan Sands
  2005-06-14 15:18  0%     ` Matthew Heaney
  1 sibling, 1 reply; 200+ results
From: Duncan Sands @ 2005-06-14  7:18 UTC (permalink / raw)
  To: comp.lang.ada; +Cc: Matthew Heaney

Hi Matthew,

> Use System.Storage_Elements.To_Integer to convert the address to an
> Integer_Address, and then convert that to type Hash_Type.

that's what I'm doing.  But there's no guarantee that they have the
same size, so it's not portable.  It's easy enough to thunk Integer_Address
to a modular type (which I'll also call Integer_Address here).  If
Integer_Address is smaller than or equal to Hash_Type then there's no
problem.  If it's larger then you can do some bit rotation, but it's surprisingly
awkward to do when you don't know the sizes in advance.  I was hoping
someone knew how to do this in a clean way.

All the best,

Duncan.



^ permalink raw reply	[relevance 0%]

* Re: Hashing on System.Address
  2005-06-13 23:41  0%   ` Robert A Duff
@ 2005-06-14  2:22  0%     ` Matthew Heaney
  2005-06-14  8:44  0%       ` Larry Kilgallen
  2005-06-14  8:42  0%     ` Larry Kilgallen
  1 sibling, 1 reply; 200+ results
From: Matthew Heaney @ 2005-06-14  2:22 UTC (permalink / raw)


Robert A Duff <bobduff@shell01.TheWorld.com> writes:

> "Matthew Heaney" <mheaney@on2.com> writes:
> > Use System.Storage_Elements.To_Integer to convert the address to an
> > Integer_Address, and then convert that to type Hash_Type.
> 
> It might be a good idea to divide that by 8, since most addresses have
> zeros in the low three bits.

Good idea.  The other thing I haven't really figured out is what to do
if you have a 64-bit address, and Hash_Type is only 32.  Ideally you'd
like to compute a 32-bit hash value that uses all 64 bits of the
address.

Alternatively, you could use the ordered container, since type
System.Address has a less than ("<") relational operator.



^ permalink raw reply	[relevance 0%]

* Re: Hashing on System.Address
  2005-06-13 21:57  4% ` Matthew Heaney
@ 2005-06-13 23:41  0%   ` Robert A Duff
  2005-06-14  2:22  0%     ` Matthew Heaney
  2005-06-14  8:42  0%     ` Larry Kilgallen
  2005-06-14  7:18  0%   ` Duncan Sands
  1 sibling, 2 replies; 200+ results
From: Robert A Duff @ 2005-06-13 23:41 UTC (permalink / raw)


"Matthew Heaney" <mheaney@on2.com> writes:

> Duncan Sands wrote:
> > Does anyone have an efficient portable algorithm for hashing
> > on a System.Address?
> >
> > The Ada 2005 package Ada.Containers defines Hash_Type as
> >
> > 	type Hash_Type is mod implementation-defined;
> >
> > This is the target type I would like for the hash.
> 
> Use System.Storage_Elements.To_Integer to convert the address to an
> Integer_Address, and then convert that to type Hash_Type.

It might be a good idea to divide that by 8, since most addresses have
zeros in the low three bits.

- Bob



^ permalink raw reply	[relevance 0%]

* Re: Hashing on System.Address
  @ 2005-06-13 21:57  4% ` Matthew Heaney
  2005-06-13 23:41  0%   ` Robert A Duff
  2005-06-14  7:18  0%   ` Duncan Sands
  0 siblings, 2 replies; 200+ results
From: Matthew Heaney @ 2005-06-13 21:57 UTC (permalink / raw)




Duncan Sands wrote:
> Does anyone have an efficient portable algorithm for hashing
> on a System.Address?
>
> The Ada 2005 package Ada.Containers defines Hash_Type as
>
> 	type Hash_Type is mod implementation-defined;
>
> This is the target type I would like for the hash.

Use System.Storage_Elements.To_Integer to convert the address to an
Integer_Address, and then convert that to type Hash_Type.




^ permalink raw reply	[relevance 4%]

* Re: Large arrays (again), problem case for GNAT
  @ 2005-04-13 19:54  6% ` Randy Brukardt
  0 siblings, 0 replies; 200+ results
From: Randy Brukardt @ 2005-04-13 19:54 UTC (permalink / raw)


"Dr. Adrian Wrigley" <amtw@linuxchip.demon.co.uk.uk.uk> wrote in message
news:pan.2005.04.13.12.46.52.518681@linuxchip.demon.co.uk.uk.uk...
> Hi guys!
>
> A month or two back I hinted that I had been having problems
> the GNAT code accessing large data structures.  It seemed that
> incorrect code was silently being generated.  Since I didn't
> have a test case available, no progress could be made.

I tried to make an all-Ada version to test on Janus/Ada. But there is not
enough memory on my machine to run it (at least, I think that's why I'm
getting Storage_Error; the Janus/Ada runtime bypasses the system heap and
goes directly to the Windows virtual memory manager for large blocks of
memory, so the failure should indicate that Windows couldn't allocate it.)

I made three changes to the program:
    Added a type Big_Int to replace Integer (better portability, especially
for a compiler
       with Integer'Size = 16);
    Replaced the GNAT-specific "Address_Image" with
      System.Storage_Elements.Integer_Address (clunky, but pure Ada);
    Replaced the call to Malloc with New.

The latter was done simply because end-running the compiler's memory
management is likely to cause bugs. And ours, at least, is designed to work
with any reasonable-sized chunk of memory. Finally, if I hadn't changed
that, it would not have worked, as Janus/Ada does not allow random memory to
be used with a pool-specific type. (Really, the access type should be a
general access type if you are going to end-run Ada's heap management.)

The test works with small enough numbers to run on my machine with 384Meg of
RAM (the top value being about 130_000_000). If you were our customer, I'd
try to figure out why the Storage_Error is being raised. Probably the answer
really is to use a supported compiler; you do really get what you pay for.

                       Randy.


 with Text_IO;
with System.Storage_Elements; -- Added, RLB.

procedure TestBig2 is

-- Test devised by Adrian Wrigley, amtw@linuxchip.demon.co.uk.uk.uk (one uk
is e
-- I disclaim all rights to this code.  Do what you wish with it!

-- This test case illustrates a problem with code
-- compiled on GNAT 3.15p for x86 under Linux

-- It shows that the 'Address of elements of large
-- arrays can be silently incorrect

-- Redid by Randy Brukardt to work with Janus/Ada; added an appropriate
Integer
-- type, use New to allocate, and removed GNAT specific stuff.

-- Notes:
--
-- This test works if the word "constant" is removed
--
-- The test also works if the value is less than 200_000_000
-- Indexing element also works with computed index
   Size : constant := 210_000_000;
   type Big_Int is range 0 .. Size;

   type Big_T is array (Big_Int range 1 .. Size) of aliased Float;

   type Big_A is access Big_T;

   Big : Big_A;

--   function GetSomeMemory (X : Integer) return Big_A;
--   pragma Import (C, GetSomeMemory, "malloc");

begin

--   Big := GetSomeMemory (Size*4 + 16); -- This seems to work OK for now
   Big := new Big_T;

   Text_IO.Put_Line ("First element attribute " & Big_Int'Image
(Big_T'First));
   Text_IO.Put_Line ("Last element attribute  " & Big_Int'Image
(Big_T'Last));

   Text_IO.Put_Line ("Address of first element is " &
        System.Storage_Elements.Integer_Address'Image(
           System.Storage_Elements.To_Integer(Big (Big_T'First)'Address)));
   Text_IO.Put_Line ("Address of last element is  " &
        System.Storage_Elements.Integer_Address'Image(
           System.Storage_Elements.To_Integer(Big (Big_T'Last)'Address)));
   Text_IO.Put_Line ("(Last element should be at higher address than
first)");


   declare
      J : Big_Int := Size;
   begin
      Text_IO.Put_Line ("Address of last element is " &
        System.Storage_Elements.Integer_Address'Image(
           System.Storage_Elements.To_Integer(Big (J)'Address)));
   end;

   Text_IO.Put_Line ("Writing to all elements in loop");
   for I in Big_T'Range loop
      Big (I) := 0.0;
   end loop;

   Text_IO.Put_Line ("Writing to 'Last element");
--raised STORAGE_ERROR : stack overflow (or erroneous memory access):
   Big (Big_T'Last) := 0.0; -- Fails!!!!!

end TestBig2;






^ permalink raw reply	[relevance 6%]

* Re: Easy Question - Printing Out An Address
  @ 2005-03-09 21:22  5%     ` Mark Lorenzen
  0 siblings, 0 replies; 200+ results
From: Mark Lorenzen @ 2005-03-09 21:22 UTC (permalink / raw)


Bryan.Berns@gmail.com writes:

> Thanks.  The Address_Image method worked perfectly.  Now I'm working
> with trying to do the same with a type of Address_Int.   Any input
> appreciated.

What about:

with Ada.Text_IO;
with System.Storage_Elements;

procedure Print_Int_Address is
   package SE renames System.Storage_Elements;
     
   My_Var      : Positive; -- Or some other type.
   Sys_Address : System.Address;
   Int_Address : SE.Integer_Address;
begin
   Sys_Address := My_Var'Address;
   Int_Address := SE.To_Integer (Sys_Address);
   Ada.Text_IO.Put_Line ("Address is:" &
			 SE.Integer_Address'Image (Int_Address));
end Print_Int_Address;

Regards,
- Mark Lorenzen



^ permalink raw reply	[relevance 5%]

* Re: Easy Question - Printing Out An Address
  @ 2005-03-09 18:34  4% ` Dmitry A. Kazakov
    0 siblings, 1 reply; 200+ results
From: Dmitry A. Kazakov @ 2005-03-09 18:34 UTC (permalink / raw)


On 9 Mar 2005 10:03:34 -0800, Bryan.Berns@gmail.com wrote:

> How can I print out (for debugging purposes) a Machine.Address to the
> screen?
> 
> - Console.Write(????)
> 
> Any ideas?

See System.Storage_Elements ARM 13.7.1

It defines To_Integer that converts address to an integer type
Integer_Address (that can be either modular or signed depending on the
compiler). Anyway, you can then do Integer_Address'Image (X'Address).

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



^ permalink raw reply	[relevance 4%]

* Re: Advanced file manipulation (multiple question)
  @ 2005-03-02 16:56  5%   ` Jeffrey Carter
  0 siblings, 0 replies; 200+ results
From: Jeffrey Carter @ 2005-03-02 16:56 UTC (permalink / raw)


Steve wrote:

> If you use Ada.Direct_Io, there is a nice way to read the file in one read, 
> but it takes two steps.
>   First create an instance of Ada.Direct_Io of bytes.
>   Open the file as bytes.

System.Storage_Elements.Storage_Element.

>   Use the size function to get the size of the file.
>   Close the file
>   Create an instance of Ada.Direct_IO with an element that is the size of 
> the file (an array of bytes maybe?).

System.Storage_Elements.Storage_Array.

>   Read the file (a single read)
>   Close the file.
> 
> This approach tends to be quite fast since there is no iteration involved 
> over the bytes of the file.

Right, but this is limited to files that will fit in memory. The streams 
approach I described using varying-size chunks will work for all files, 
and is equivalent to this approach for smaller files. In addition, it 
does not require opening the file twice.

-- 
Jeff Carter
"What I wouldn't give for a large sock with horse manure in it."
Annie Hall
42



^ permalink raw reply	[relevance 5%]

* Re: POSIX.Memory_Mapping.Map_Memory
  2005-01-29 16:31  0%   ` POSIX.Memory_Mapping.Map_Memory Adrian Hoe
@ 2005-01-29 18:44  0%     ` Mark Lorenzen
  0 siblings, 0 replies; 200+ results
From: Mark Lorenzen @ 2005-01-29 18:44 UTC (permalink / raw)


"Adrian Hoe" <byhoe@greenlime.com> writes:

> Mark Lorenzen wrote:
> > "Adrian Hoe" <byhoe@greenlime.com> writes:
> >
> > > 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.
> >
> 
> >>>> snip <<<<
> 
> 
> > > Device.Fd := Open (To_POSIX_String (File_Name),
> > > Read_Only);
> >
> > You open the device in read-only.
> >
> > [cut]
> >
> > >
> > > -- 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);
> >
> > But you try to map it in read/write mode.
> 
> I open with Read_Write option and raised POSIX.POSIX_ERROR :
> INVALID_ARGUMENT at the same line.

In the way you are using Map_Memeory, it is probably because the value
of Offset (i.e. 0) is not page aligned.

On many implementations, you can only map a multiple of the page size
and the memory has to be page aligned.

> 
> > Maybe thats the case of the exception. Do you have to be root in
> order
> > to open the device at all?
> 
> 
> No, I don't have to be root to open the device. Some applications are
> able to open it and the camera and video card work.
> 
> 
> 
> --
> Adrian Hoe

- Mark Lorenzen



^ permalink raw reply	[relevance 0%]

* Re: POSIX.Memory_Mapping.Map_Memory
  2005-01-29 16:20  0% ` POSIX.Memory_Mapping.Map_Memory Mark Lorenzen
@ 2005-01-29 16:31  0%   ` Adrian Hoe
  2005-01-29 18:44  0%     ` POSIX.Memory_Mapping.Map_Memory Mark Lorenzen
  0 siblings, 1 reply; 200+ results
From: Adrian Hoe @ 2005-01-29 16:31 UTC (permalink / raw)



Mark Lorenzen wrote:
> "Adrian Hoe" <byhoe@greenlime.com> writes:
>
> > 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.
>

>>>> snip <<<<


> > Device.Fd := Open (To_POSIX_String (File_Name),
> > Read_Only);
>
> You open the device in read-only.
>
> [cut]
>
> >
> > -- 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);
>
> But you try to map it in read/write mode.

I open with Read_Write option and raised POSIX.POSIX_ERROR :
INVALID_ARGUMENT at the same line.

> Maybe thats the case of the exception. Do you have to be root in
order
> to open the device at all?


No, I don't have to be root to open the device. Some applications are
able to open it and the camera and video card work.



--
Adrian Hoe




^ permalink raw reply	[relevance 0%]

* Re: POSIX.Memory_Mapping.Map_Memory
  2005-01-29 15:58  3% POSIX.Memory_Mapping.Map_Memory Adrian Hoe
@ 2005-01-29 16:20  0% ` Mark Lorenzen
  2005-01-29 16:31  0%   ` POSIX.Memory_Mapping.Map_Memory Adrian Hoe
  0 siblings, 1 reply; 200+ results
From: Mark Lorenzen @ 2005-01-29 16:20 UTC (permalink / raw)


"Adrian Hoe" <byhoe@greenlime.com> writes:

> 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
> 
> -----------------------------------------------------------------------

[cut]

> Device.Fd := Open (To_POSIX_String (File_Name),
> Read_Only);

You open the device in read-only.

[cut]

> 
> -- 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);

But you try to map it in read/write mode.

Maybe thats the case of the exception. Do you have to be root in order
to open the device at all?

[cut]

> Adrian Hoe

- Mark Lorenzen



^ permalink raw reply	[relevance 0%]

* POSIX.Memory_Mapping.Map_Memory
@ 2005-01-29 15:58  3% Adrian Hoe
  2005-01-29 16:20  0% ` POSIX.Memory_Mapping.Map_Memory Mark Lorenzen
  0 siblings, 1 reply; 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 3%]

* Re: Pointer address
  2004-12-30 11:29  5% Pointer address Bj?rn
  2004-12-30 12:18  0% ` Martin Krischik
@ 2004-12-30 12:23  5% ` Vinzent 'Gadget' Hoefler
  1 sibling, 0 replies; 200+ results
From: Vinzent 'Gadget' Hoefler @ 2004-12-30 12:23 UTC (permalink / raw)


Bj?rn wrote:

> I'm trying to convert some C code into Ada.
> I'm stuck on the follwing:
> cpdata.dwData = 0x0001B001 (dwData being a ptr to an ulong)

What was the target architecture/OS of the original C-Code? Using fixed
addresses looks like it was assuming DOS or some other system with
fixed memory areas (like some microcontroller stuff). Such code simply
will not work with Windows.

> Trying to execute the code below gives me a:
> EXCEPTION_ACCESS_VIOLATION

Yes, of course.

> I'm quite sure I'm doing something wrong here and need to read up a
> bit on it. Could someone please give me some pointers here and maybe
> the applicable parts of the ARM.

You _seem_ to confuse pointers with address clauses.

> Adding an import pragma didn't seem to help more than removing the
> warnings.

The problem here is that you're declaring DwData as access type and the
ARM requires that access types are initialized to null. This seems to
be true even with the Import pragma (maybe because the variable is
delcared locally). So you're accessing memory that is not valid for
your application and *boom*.

> procedure Temp is
> 
>    type PULONG is access all Interfaces.C.Unsigned_Long;
[...]

As I've written before, the code won't work on Windows, but if dwData
really is a pointer to some data at a fixed address you could declare
the data itself and apply the address clause to it directly. Again,
this is Ada -> no need for pointers. ;-)

with Interfaces.C;
with System.Storage_Elements;
with System.Address_Image;
with Ada.Text_IO;

procedure Temp is
   Some_Address : constant System.Address :=
      System.Storage_Elements.To_Address(16#0001B000#);

   DwData : Interfaces.C.Unsigned_Long;
   for DwData'Address use Some_Address;
   pragma Import (C, DwData);
begin
   Ada.Text_IO.Put      ("dwData address = ");
   Ada.Text_IO.Put_Line (System.Address_Image (DwData'Address));
end Temp;

This should work as long as noone is trying to access DwData.

Hmm, one problem: if I change the address to 16#0001B001#, I get

"raised PROGRAM_ERROR : temp.adb:13 misaligned address value".

Considering the code, I'm not really surprised. So you should check the
architecture the C code was targeted at, try to figure out what the
code was trying to accomplish, and "emulate" this on the new system.


Vinzent.



^ permalink raw reply	[relevance 5%]

* Re: Pointer address
  2004-12-30 11:29  5% Pointer address Bj?rn
@ 2004-12-30 12:18  0% ` Martin Krischik
  2004-12-30 12:23  5% ` Vinzent 'Gadget' Hoefler
  1 sibling, 0 replies; 200+ results
From: Martin Krischik @ 2004-12-30 12:18 UTC (permalink / raw)


Bj?rn wrote:

> I'm trying to convert some C code into Ada.
> I'm stuck on the follwing:
> cpdata.dwData = 0x0001B001 (dwData being a ptr to an ulong)
> 
> Trying to execute the code below gives me a:
> EXCEPTION_ACCESS_VIOLATION
> 
> If I change the address to 16#0001B000# the program just silently
> exits/terminates without printing my put_line.
> 
> If I try to set DwData with an unchecked_conversion instead, using
> address 16#0001B001#, the Address_Image returns 16#0001B000#.
> 
> I'm quite sure I'm doing something wrong here and need to read up a
> bit on it. Could someone please give me some pointers here and maybe
> the applicable parts of the ARM.
> 
> When I compile this on win-gnat-3.15 I get the following warnings:
> temp.adb:17:08: warning: default initialization of "DwData" may modify
> overlaid storage
> temp.adb:17:08: warning: use pragma Import for "DwData" to suppress
> initialization (RM B.1(24))
> Adding an import pragma didn't seem to help more than removing the
> warnings.
> 
> Thanks
> Bjï¿œrn
> 
> 
> with Interfaces.C;
> with Unchecked_Conversion;
> with System.Storage_Elements;
> with System.Address_Image;
> with Text_IO;
> 
> procedure Temp is
> 
>    type PULONG is access all Interfaces.C.Unsigned_Long;
>    function PULONG_To_Address is new Unchecked_Conversion
>      (PULONG, System.Address);
>    Some_Address : constant System.Address :=
>      System.Storage_Elements.To_Address(16#0001B000#);
>    DwData : PULONG;
>    for DwData'Address use Some_Address;
>    --  pragma Import (C, DwData);
> begin
>    Text_IO.Put_Line ("dwData address = " & System.Address_Image
>                      (PULONG_To_Address (DwData)));
> end;

You should not use Unchecked_Conversion. Read:

http://en.wikibooks.org/wiki/Programming:Ada:Subtypes#Address_Convertion

With Regards

Martin
-- 
mailto://krischik@users.sourceforge.net
http://www.ada.krischik.com



^ permalink raw reply	[relevance 0%]

* Pointer address
@ 2004-12-30 11:29  5% Bj?rn
  2004-12-30 12:18  0% ` Martin Krischik
  2004-12-30 12:23  5% ` Vinzent 'Gadget' Hoefler
  0 siblings, 2 replies; 200+ results
From: Bj?rn @ 2004-12-30 11:29 UTC (permalink / raw)


I'm trying to convert some C code into Ada.
I'm stuck on the follwing: 
cpdata.dwData = 0x0001B001 (dwData being a ptr to an ulong)

Trying to execute the code below gives me a:
EXCEPTION_ACCESS_VIOLATION

If I change the address to 16#0001B000# the program just silently
exits/terminates without printing my put_line.

If I try to set DwData with an unchecked_conversion instead, using
address 16#0001B001#, the Address_Image returns 16#0001B000#.

I'm quite sure I'm doing something wrong here and need to read up a
bit on it. Could someone please give me some pointers here and maybe
the applicable parts of the ARM.

When I compile this on win-gnat-3.15 I get the following warnings:
temp.adb:17:08: warning: default initialization of "DwData" may modify
overlaid storage
temp.adb:17:08: warning: use pragma Import for "DwData" to suppress
initialization (RM B.1(24))
Adding an import pragma didn't seem to help more than removing the
warnings.

Thanks
Bj�rn


with Interfaces.C;
with Unchecked_Conversion;
with System.Storage_Elements;
with System.Address_Image;
with Text_IO;

procedure Temp is

   type PULONG is access all Interfaces.C.Unsigned_Long;
   function PULONG_To_Address is new Unchecked_Conversion
     (PULONG, System.Address);
   Some_Address : constant System.Address :=
     System.Storage_Elements.To_Address(16#0001B000#);
   DwData : PULONG;
   for DwData'Address use Some_Address;
   --  pragma Import (C, DwData);
begin
   Text_IO.Put_Line ("dwData address = " & System.Address_Image
                     (PULONG_To_Address (DwData)));
end;



^ permalink raw reply	[relevance 5%]

* Re: Efficiently setting up large quantities of constant data
  @ 2004-12-17 13:53  4%     ` Dr. Adrian Wrigley
  0 siblings, 0 replies; 200+ results
From: Dr. Adrian Wrigley @ 2004-12-17 13:53 UTC (permalink / raw)


OK I have just tried this.

I have a plain text file "NigeriaScam4.txt", which I turn into
an object file "nigeria.o", and link in. (Source below)

I encountered one or two problems:

I can't access the "..._size" value.  This is an absolute value
in the object file, not the location where the value is stored.
If I try to Import the size, the program crashes at runtime,
because the size is incorrectly interpreted as the location of
the variable storing the size.

The code works, but seems a bit messy.  Calculating the size
is a nuisance, and I can't "import" the Message (local type
is not constant).
Aside from these issues, the code works.  The program
outputs the contents of the text file as
built into the executable.

Any ideas for:

1) Importing the value of the ..._size symbol
2) Making the contents constant
3) Tidying it up a bit

note that writing into the Message is possible, but probably
shouldn't be. (is there an option to make the data read-only?)

Of course, the Message could be copied into another value
which was constant, but that would be wasteful.  Or an
access to constant value could be used.

Thanks
-- 
Adrian (using GNAT 3.15p on Athlon/Linux)

with Text_IO;
with System.Storage_Elements;

-- Start out with two files, this source file, and a simple
-- text file, NigeriaScam4.txt
--
-- Build executable by creating object file containing txt data
-- using objcopy.  Include object file in link.
--
-- objcopy --input-target=binary --binary-architecture=i386 --output-target=elf32-i386 NigeriaScam4.txt nigeria.o
-- gnatmake demo

procedure Demo is

   pragma Linker_Options ("nigeria.o");

   Name : constant String := "NigeriaScam4_txt";

   use System.Storage_Elements;

   MessageStart, MessageEnd :  Character;
   pragma Import (C, MessageStart, "_binary_" & Name & "_start");
   pragma Import (C, MessageEnd,   "_binary_" & Name & "_end");

   Message :  String (1 .. Integer (MessageEnd'Address-MessageStart'Address));
   for Message'Address use MessageStart'Address;

begin

   Text_IO.Put_Line ("Length was : " & Integer'Image (Message'Length));
   Text_IO.Put_Line ("Message was : " & Message);

end Demo;




^ permalink raw reply	[relevance 4%]

* Re: Thick Ada bindings to C Win32
  @ 2004-11-28 23:45  3%             ` 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 3%]

* Re: Ada access vs C/C++ pointers and references
    2004-08-19  0:21  3% ` Nick Roberts
  2004-08-19  0:29  4% ` Jim Rogers
@ 2004-08-19  7:59  1% ` Ole-Hjalmar Kristensen
  2 siblings, 0 replies; 200+ results
From: Ole-Hjalmar Kristensen @ 2004-08-19  7:59 UTC (permalink / raw)


>>>>> "KHD" == Keith H Duggar <duggar@mit.edu> writes:

    KHD> In the "ADA Popularity Discussion Request" thread, the topic
    KHD> of C/C++ pointers and Ada access types came up. Here are the
    KHD> related quotes

    KHD> Keith H Duggar writes :
    >> Or are there simply missing features that preclude some
    >> efficient coding idioms (does Ada have pointers?).

    KHD> Ludovic Brenta writes :
    >> Yes, Ada does have pointers.  They're called
    >> "access types" in Ada.

    KHD> Dmitry A. Kazakov writes :
    >> Yes, Ada has pointers, and interestingly, because that
    >> wasn't design intent, richer than C++ has.
    >> ...
    >> 
    >> 5. Ada pointers are transparent to member extraction and
    >> array indexing. I.e. in Ada "->" and "." are same.

    KHD> Before I raise my examples and questions please keep in mind
    KHD> that I do not know Ada. Therefore, I'm purely seeking
    KHD> knowledge and all my statements about Ada should be regarded
    KHD> as questions rather than statements.

    KHD> It seems to me that Ada access types are more akin to C++
    KHD> references than there are to C/C++ pointers. For by pointer
    KHD> I literally mean an integral type supporting integer
    KHD> arithmetic which can be interpreted as a memory address.

Not really. C++ references are constant, Ada access types can be
changed.
Ada access types are *very* similar to C++ pointers.

    KHD> In reference to point 5. above, pointer arithmetic is partly
    KHD> why C++ has both "->" and "."

No. This is just syntax. "." would have worked just fine for
dereferencing C/C++ pointers. I suspect the reason for using "->" was
just to make it more visible that you are using a pointer.

    KHD> In C/C++ such pointer arithmetic allows for a number of
    KHD> idioms intended to produce faster or more efficient code.
    KHD> For example, consider array subscript access:

    KHD>     C++ :  x[i]
    KHD>     Ada :  x(i)

    KHD> Since both languages allow subscripting by integers that
    KHD> may not be available until runtime, both C++ and Ada
    KHD> compilers must produce machine code that effectively:

    KHD> 1) computes the location in memory of x[i] from the location
    KHD>    of x and the value of i
    KHD> 2) "dereferences" that location for either read or write (by
    KHD>    loading into a register, etc)

    KHD> Pointer arithmetic in C/C++ sometimes allows you to skip
    KHD> step 1 by keeping and updating the address directly. For
    KHD> example, consider the following two examples which both
    KHD> process all the characters of a null terminated array.

    KHD>     char buffer[80]

    KHD>     // read in some contents into buffer

    KHD>     // method one
    KHD>     for ( int i = 0 ; buffer[i] != '\0' ; ++i ) { ... }

    KHD>     // method two
    KHD>     for ( char * cp = buffer ; *cp != '\0' ; ++cp ) { ... }

    KHD> Here are the operations performed during each pass of the
    KHD> loop

    KHD> method one :  increment i
    KHD>               compute address of buffer[i]
    KHD>               dereference address of buffer[i]
    KHD>               compare to null '\0'

    KHD> method two :  increment address (pointer) cp
    KHD>               dereference address cp
    KHD>               compare to null '\0'

    KHD> As you can see, method two saves one instruction by storing
    KHD> and manipulating a memory address directly.

Except that the Ada construct "for i in buffer'range loop ... end
loop" will typically be optimized to yield the most efficient code.
The use of explicit pointer arithmetic may even prevent compilers from
generating the most efficient code, because you give them no choice in
strategy. I have even seen C++ compilers generate faster code for
your method one than your method two. But as usual, it all depends on
your compiler and hardware.

    KHD> Here is an example of saving space using pointer arithmetic
    KHD> in a doubly linked list

    KHD> http://c2.com/cgi/wiki?TwoPointersInOneWord

Yes, an old trick. You save some space, but I doubt you save time, and
it is utterly unreadable to someone who does not know the trick.

    KHD> Now please don't misunderstand me. I'm not advocating these
    KHD> techniques. Nor do I mean to imply that they are practically
    KHD> important. Furthermore, allowing pointer arithmetic creates
    KHD> a host of problems of which I'm sure you are aware.

    KHD> I'm simply asking four things.

    KHD> First, is it correct to say that Ada access types ore more
    KHD> similar to C++ references (T&) than they are to C/C++
    KHD> pointers (T*) ?

See above.

    KHD> Second, does Ada provide any facilities for direct and raw
    KHD> memory access by memory address and pointer arithmetic?

Yes. If you really want it, it's in System.Storage_Elements

    KHD> Third, if Ada does not provide arithmetic pointers do you
    KHD> know if this has played any part in acceptance of Ada for
    KHD> systems programming or efficiency critical applications?

    KHD> Fourth, have you experienced or can you think of any cases
    KHD> were pointer arithmetic has helped to solve a problem that
    KHD> would have been more difficult with Ada access types alone?

    KHD> Keith

As Ada does provide pointer arithmetic your two last questions are
somewhat hypothetical, but in my experince, the answer is no.

-- 
   C++: The power, elegance and simplicity of a hand grenade.


P.S. I do most of my programming in C++. It's fun, it's powerful, but
not my first choice to build large, reliable systems.



^ permalink raw reply	[relevance 1%]

* Re: Ada access vs C/C++ pointers and references
    2004-08-19  0:21  3% ` Nick Roberts
@ 2004-08-19  0:29  4% ` Jim Rogers
  2004-08-19  7:59  1% ` Ole-Hjalmar Kristensen
  2 siblings, 0 replies; 200+ results
From: Jim Rogers @ 2004-08-19  0:29 UTC (permalink / raw)


duggar@mit.edu (Keith H Duggar) wrote in news:b47de02.0408181427.25d82fe1
@posting.google.com:

> I'm simply asking four things.
> 
> First, is it correct to say that Ada access types ore more
> similar to C++ references (T&) than they are to C/C++
> pointers (T*) ?

Not really. C++ references are always implemented as const
pointers. Ada access types are assignable, just like C/C++
pointers.

> 
> Second, does Ada provide any facilities for direct and raw
> memory access by memory address and pointer arithmetic?

Yes, but not directly through access types. The package
System.Storage_Elements provides the ability to perform
integer arithmetic on addresses.

Note that the package contains functions for converting between
addresses and Integer_Address. This allows Ada to work correctly
on systems without linear addressing schemes, such as the old




^ permalink raw reply	[relevance 4%]

* Re: Ada access vs C/C++ pointers and references
  @ 2004-08-19  0:21  3% ` Nick Roberts
  2004-08-19  0:29  4% ` Jim Rogers
  2004-08-19  7:59  1% ` Ole-Hjalmar Kristensen
  2 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 3%]

* Stack overflow using Xml/Ada
@ 2004-07-20 21:25  4% Jano
  0 siblings, 0 replies; 200+ results
From: Jano @ 2004-07-20 21:25 UTC (permalink / raw)


Hi,

I'm using the excellent Xml/Ada library to parse a file (incidentally, 
created too with Xml/Ada). The problem is when I try to parse it back 
into memory, since I get a stack overflow when calling the

Input_Sources.File.Open

procedure.

I've tracked it a bit and the problem seems to be this declaration in 
input_sources-file.adb/Fast_Read

type Fixed_String is new String (Buf'Range);
package Dir_Fast is new Ada.Direct_IO (Fixed_String);

Where Buf'Range is the file size.

Further inspecting the Direct_IO gnat implementation, it seems that 
inside the instance a buffer it's declared in the stack, of 
Fixed_String'Size:

Zeroes : System.Storage_Elements.Storage_Array := 
   (1 .. System.Storage_Elements.Storage_Offset (Bytes) => 0);
-- Buffer used to fill out partial records.

Since my file is some 3MB in size, and the stack I've allocated is 2MB, 
it fails.

I find too restrictive that the file to parse has to be below stack 
size, so I'm not considering the possibility of increasing stack size as 
a solution (furthermore I've never succeed to get over 2MB stack size in 
linux).

Has anyone faced this problem? If so, how did you solved it?

Thanks in advance,

Alex.

P.s: BTW, is there some mailing list related to this library?



^ permalink raw reply	[relevance 4%]

* Re: Manifesto against Vector
  @ 2004-05-06  9:41  3%               ` Vinzent 'Gadget' Hoefler
  0 siblings, 0 replies; 200+ results
From: Vinzent 'Gadget' Hoefler @ 2004-05-06  9:41 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

>On Thu, 6 May 2004 09:03:54 +0200, "Jean-Pierre Rosen"
><rosen@adalog.fr> wrote:
>
>>Since you asked for it... (but I'll try to have reasonable objections).
>>Note that I am known for being strongly *in favor* of the use clause.
>>
>>I would strongly oppose this proposal for a very simple reason: it
>>defeats the main goal of having separated with from use.
>>With is a library level clause; it tells: "this unit, somewhere needs
>>that unit".
>
>Why that should be told? I'd say that "with" is superfluous.

No! If at all then it is "use" which is superfluous. ;-)

>Maybe, but it should be placed at the beginning of the context. So it
>is just one line difference. Not a big issue, IMO.

It is more than a single line. Consider this:

|with Interfaces;
 ^^^^
|
|package body Timer is
|
[...]
|   function Hi_Byte (Value : in Interfaces.Unsigned_16)
|     return Interfaces.Unsigned_8 is
|      use type Interfaces.Unsigned_16;
       ^^^
|   begin
|      return Interfaces.Unsigned_8 (
|          Interfaces.Shift_Right (Value, 8) and 16#FF#);
|   end Hi_Byte;

>This might work with bodies, but it does not with specifications.

Well, most of it does.

The only part where I used "use" yet was in the private part of a
package spec, and this was just because I am lazy and wanted to have
"System.Storage_Elements.To_Address" visible there as the simpler
"To_Address". I could have used "renames" instead, I guess.

>with Foo;
>procedure P (<something here needs visibility of Foo>);

Simple: Use the full name there. If it's too long for you, I'd say
rename it.

>>Allowing with/use would simply encourage a style that should be
>>discouraged altogether. QED.
>
>Oh, Use is Use, and With is With, and never the twain shall meet, ...
>(:-))

It's much more simple: Never use "use". :)


Vinzent.



^ permalink raw reply	[relevance 3%]

* Re: Pass by reference
  2004-04-15  9:43  0%               ` Vinzent 'Gadget' Hoefler
@ 2004-04-17  7:59  0%                 ` Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2004-04-17  7:59 UTC (permalink / raw)


Vinzent 'Gadget' Hoefler <nntp-2004-04@t-domaingrabbing.de> writes:

> Simon Wright wrote:

> >I'm not 100% sure on this, but this code
> >
> >   with Interfaces;
> >   with System.Machine_Code;
> >   with System.Storage_Elements;
> >
> >   procedure Access_Memory_Mapped_Register is
> [...]
> >   #APP
> >           movl #01000000, -65536
> >           movl #00000000, -65536
> >   #NO_APP
> 
> (Despite the fact that this code is not valid, i386 can't load two
> constants in one instruction, your intention is clear and would
> work).

Yes, more work needed (and next time, Simon, go the whole way and
don't just stop with a -S compilation). I too will only use asm when
it's _necessary_, so it's a new learning experience each time ...

> That's why I declared the procedure to take an access parameter
> instead of "in out" and now everything is working fine as
> expected. It is just the fact that I now use access types in the
> interface (IMO: unnecessarily from the point of logic) that bugs me
> a little bit.

Another possibility would be to pass System.Address. On the whole,
access is a lot safer I would have thought -- especially if you can
encapsulate this low-level stuff (including the calls to your wrapper
procedure) to a restricted area of the code.

> Eventually I should try to switch to use limited types instead to
> circumvent this problem?

I had a play with this, and for GNAT 3.15p (and 3.16a1, 5.02a) this

   package Wrapper is
      type Register is limited private;
      procedure Write (Value : Interfaces.Unsigned_16; To : in out Register);
   private
      type Actual_Register is mod 256;
      for Actual_Register'Size use 8;
      pragma Volatile (Actual_Register);
      type Register is limited record
         Actual : Actual_Register;
      end record;
      for Register'Size use 8;
   end Wrapper;

used pass-by-reference.

The asm for 5.02a (-gnatp -O2) is

	.type	access_memory_mapped_register__wrapper__write.0,@function
access_memory_mapped_register__wrapper__write.0:
.LFB1:
	pushl	%ebp
.LCFI0:
	movl	%esp, %ebp
.LCFI1:
	subl	$4, %esp
.LCFI2:
	movzwl	8(%ebp), %eax
	movl	12(%ebp), %edx
	movb	%al, (%edx)
	shrl	$8, %eax
	movb	%al, (%edx)
	movl	%ebp, %esp
	popl	%ebp
	ret

which looks as though it at least stands a chance; I don't understand
the 3.15p code,

	.type	 access_memory_mapped_register__wrapper__write.0,@function
access_memory_mapped_register__wrapper__write.0:
	pushl %ebp
	movl %esp,%ebp
	subl $4,%esp
	movl %ecx,-4(%ebp)
	movl 12(%ebp),%edx
	movzbw 9(%ebp),%ax
	movb %al,(%edx)
	movl %ebp,%esp
	popl %ebp
	ret

-- 
Simon Wright                               100% Ada, no bugs.



^ permalink raw reply	[relevance 0%]

* Re: Pass by reference
  2004-04-14 17:27  5%             ` Simon Wright
@ 2004-04-15  9:43  0%               ` Vinzent 'Gadget' Hoefler
  2004-04-17  7:59  0%                 ` Simon Wright
  0 siblings, 1 reply; 200+ results
From: Vinzent 'Gadget' Hoefler @ 2004-04-15  9:43 UTC (permalink / raw)


Simon Wright wrote:

>Vinzent 'Gadget' Hoefler <nntp-2004-04@t-domaingrabbing.de> writes:
>
>> Simon Wright wrote:
>> 
>> >Vinzent 'Gadget' Hoefler <nntp-2004-04@t-domaingrabbing.de> writes:
>> >
>> >> Pat Rogers wrote:
>> >> 
>> >> >If you made the type volatile that would also force by-reference.
>> >
>> >C.6(18): If a type is atomic or volatile and it is not a by-copy type,
>>                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> 
>> Yes, but if I understand that part correctly, this is the point. The
>> register-type is just a simple Integer-type:
>
>Sorry, that's what _I_ was trying to say too!

Ok. Got it. :)

[...]
>> >I think you need to use inline assembler to be sure.
>> 
[...]
>> 
>> >And to be really sure you may need to use Volatile => True on the
>> >call, I had to (this was GNAT/PowerPC, by the way).
>> 
>> I'm not sure if I understand... can I actually apply that pragma to
>> a call? Or am I missing something else?
>
>I was talking about your "optimizes the sequence of assignment which I
>need for this register" problem.

Oh.

Well, from what I was trying to understand by looking at the
ASM-output I figured the volatile-"property" of the type just got
lost, *because* it was passed by copy.

>I don't know whether it's available in GCC C inline assembler, but for
>GNAT, System.Machine_Code.Asm looks like
>
>   procedure Asm (
>     Template : String;
>     Outputs  : Asm_Output_Operand_List;
>     Inputs   : Asm_Input_Operand_List;
>     Clobber  : String  := "";
>     Volatile : Boolean := False);
>
>(plus other variants).

Duh. _Now_ I understand. I've never looked at System.Machine_Code.
(IMO inline assembler can considered to be evil in most cases).

>I'm not 100% sure on this, but this code
>
>   with Interfaces;
>   with System.Machine_Code;
>   with System.Storage_Elements;
>
>   procedure Access_Memory_Mapped_Register is
[...]
>   #APP
>           movl #01000000, -65536
>           movl #00000000, -65536
>   #NO_APP

(Despite the fact that this code is not valid, i386 can't load two
constants in one instruction, your intention is clear and would work).

>which looks good .. no 'Access anywhere ..

Yes. Probably I wasn't expressing myself too clear, so I'm trying to
switch to verbose mode. :)

Firstly, if I assign the values to the variable directly the compiled
code is just perfect. No problem here, no inline-assembler needed. Ada
behaves as I expect it to. Fine.

But what I am trying to do is to abstract away some (nasty) behaviour
of the registers (yes, there is more than one, in fact: up to
twenty-four): If I write a new timer value I have to write two byte
values (low-, high-byte) in succession instead of just assigning the
(16-bit) value directly (the 8254 timer only has an 8-bit-data-port).
To make this part a little bit more safe (if you forget to write a
value then - *poof* - everything will screw up) I declared the
"Timer.Write"-procedure that should take one of the
memory-mapped-registers and the value-to-be-written as parameters and
do the nasty stuff with converting the value and extracting high- and
low-byte at this only one place.

Probably a neat idea, but now RM C.6(18) strikes back and passes the
_value_ at the memory address of the register to the procedure
(by-copy) instead of the _address_ of the register (by-reference), I
assign the stuff inside the procedure (means: the compiler is
perfectly allowed to optimize anything away, because it is just
working with a local copy and can't "return" more than 8 bits anyway)
and get the result back that would then be written to the register.

Well, this might be perfectly justified by the mentioned paragraph of
the RM - but is just plain wrong for the real world. Switching to
inline assembler wouldn't help here either, because *at this point* it
is already too late, all I'd get as input would be the value of the
register, not the register (read: pointer to) "itself".

That's why I declared the procedure to take an access parameter
instead of "in out" and now everything is working fine as expected. It
is just the fact that I now use access types in the interface (IMO:
unnecessarily from the point of logic) that bugs me a little bit.

Eventually I should try to switch to use limited types instead to
circumvent this problem?


Vinzent.



^ permalink raw reply	[relevance 0%]

* Re: Pass by reference
  @ 2004-04-14 17:27  5%             ` Simon Wright
  2004-04-15  9:43  0%               ` Vinzent 'Gadget' Hoefler
  0 siblings, 1 reply; 200+ results
From: Simon Wright @ 2004-04-14 17:27 UTC (permalink / raw)


Vinzent 'Gadget' Hoefler <nntp-2004-04@t-domaingrabbing.de> writes:

> Simon Wright wrote:
> 
> >Vinzent 'Gadget' Hoefler <nntp-2004-04@t-domaingrabbing.de> writes:
> >
> >> Pat Rogers wrote:
> >> 
> >> >If you made the type volatile that would also force by-reference.
> >
> >C.6(18): If a type is atomic or volatile and it is not a by-copy type,
>                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 
> Yes, but if I understand that part correctly, this is the point. The
> register-type is just a simple Integer-type:

Sorry, that's what _I_ was trying to say too!

> >> Are you sure? I'm just looking at the assembly ouput of GNAT for a
> >> procedure that takes a volatile type (memory mapped register) and it
> >> does't seem so. Even worse, it optimizes the sequence of assignment
> >> which I need for this register. If you have any idea how can I avoid
> >> using access types to make it right, I'd be glad to hear it.
> >
> >I think you need to use inline assembler to be sure.
> 
> You must be kidding me, I'm just getting away from using assembler. :)
> The old system was a 16-bit-CPU programmed entirely in assembly
> language, now I am having MaRTE and Ada and you say, I should use
> inline assembler instead? ;-)
> 
> Well, there is no general problem in here for me, but even with inline
> assembler the fact remains that the procedure would need the _address_
> of the register, and *not* its contents. So using inline assembler
> wouldn't help in avoiding access types and if it doesn't, I won't need
> it, because in that case the compiler generated code is just fine.
> 
> >And to be really sure you may need to use Volatile => True on the
> >call, I had to (this was GNAT/PowerPC, by the way).
> 
> I'm not sure if I understand... can I actually apply that pragma to
> a call? Or am I missing something else?

I was talking about your "optimizes the sequence of assignment which I
need for this register" problem.

I don't know whether it's available in GCC C inline assembler, but for
GNAT, System.Machine_Code.Asm looks like

   procedure Asm (
     Template : String;
     Outputs  : Asm_Output_Operand_List;
     Inputs   : Asm_Input_Operand_List;
     Clobber  : String  := "";
     Volatile : Boolean := False);

(plus other variants).

From http://gcc.gnu.org/onlinedocs/gnat_ug_unx/The-Volatile-Parameter.html#The%20Volatile%20Parameter

Compiler optimizations in the presence of Inline Assembler may
sometimes have unwanted effects. For example, when an Asm invocation
with an input variable is inside a loop, the compiler might move the
loading of the input variable outside the loop, regarding it as a
one-time initialization.

If this effect is not desired, you can disable such optimizations by
setting the Volatile parameter to True; for example:

     Asm ("movl %0, %%ebx" & LF & HT &
          "movl %%ebx, %1",
          Inputs   => Unsigned_32'Asm_Input  ("g", Var_In),
          Outputs  => Unsigned_32'Asm_Output ("=g", Var_Out),
          Clobber  => "ebx",
          Volatile => True);
     
I'm not 100% sure on this, but this code

   with Interfaces;
   with System.Machine_Code;
   with System.Storage_Elements;

   procedure Access_Memory_Mapped_Register is

      R : Interfaces.Unsigned_32;
      for R'Address use System.Storage_Elements.To_Address (16#ffff0000#);

   begin

      System.Machine_Code.Asm
        ("movl #01000000, %0",
         Outputs => Interfaces.Unsigned_32'Asm_Output ("=m", R),
         Volatile => True);

      System.Machine_Code.Asm
        ("movl #00000000, %0",
         Outputs => Interfaces.Unsigned_32'Asm_Output ("=m", R),
         Volatile => True);

   end Access_Memory_Mapped_Register;

generates this i86 assembler

           .file	"vinzent.adb"
           .version	"01.01"
   gcc2_compiled.:
   .section	.rodata
   .LC0:
           .string	"vinzent.adb"
   .text
           .align 4
   .globl _ada_access_memory_mapped_register
           .type	 _ada_access_memory_mapped_register,@function
   _ada_access_memory_mapped_register:
           pushl %ebp
           movl %esp,%ebp
   #APP
           movl #01000000, -65536
           movl #00000000, -65536
   #NO_APP
           movl %ebp,%esp
           popl %ebp
           ret
   .Lfe1:
           .size	 _ada_access_memory_mapped_register,.Lfe1-_ada_access_memory_mapped_register
           .ident	"GCC: (GNU) 2.8.1"

which looks good .. no 'Access anywhere ..

-- 
Simon Wright                               100% Ada, no bugs.



^ permalink raw reply	[relevance 5%]

* Re: In-Out Parameters for functions
  2004-02-28 17:34  3%                                   ` Robert I. Eachus
@ 2004-02-29  3:51  0%                                     ` Hyman Rosen
  0 siblings, 0 replies; 200+ results
From: Hyman Rosen @ 2004-02-29  3:51 UTC (permalink / raw)


Robert I. Eachus wrote:
>  It is that you will find lots of places in the standard where
> order independent SEMANTICS occurs, for example in 13.7.1(7).  In those 
> cases the usual implementation (in this case of package 
> System.Storage_Elements) will simplify things by using parameter 
> flipping and pragma Inline.  If we were to change the semantics of Ada 
> to require left-to-right evaluation, what should be done with these 
> functions, especially when they are in-lined?  A workable rule probably 
> could be written, but it is the sort of thing you have to look at with a 
> proposal like yours.

The section to which you refer defines a pair of "+" operations.
I don't see how they cause any issues for l-to-r. And pragma Inline
does not affect the semantics of a program, so again I don't see what
the relevance is. I do agree that there seem to be unholy complexities
lurking in the trade-offs between checking requirements and allowing
optimization which could be exacerbated by requiring l-to-r.



^ permalink raw reply	[relevance 0%]

* Re: In-Out Parameters for functions
  @ 2004-02-28 17:34  3%                                   ` Robert I. Eachus
  2004-02-29  3:51  0%                                     ` Hyman Rosen
  0 siblings, 1 reply; 200+ results
From: Robert I. Eachus @ 2004-02-28 17:34 UTC (permalink / raw)


Hyman Rosen wrote:

> Robert I. Eachus wrote:
> 
>> Hyman Rosen wrote:
>>
>>> In any case, when I
>>> said that a + b becomes "+"(a, b) and not "+"(b, a)
>>> I was not "absolutely wrong" but "absolutely right".
>>
>>
>> No, you were absolutely wrong as usual.  The order of evaluation of 
>> the parameters to "+" is undefined whether the "+" is user defined or 
>> language defined.
> 
> 
> Where did I say that the order of evaluation of the operands was
> defined? V'G'H argued that the philosophy of Ada was that a + b
> and b + a are the same. I pointed out that for user-defined "+",
> when you write a + b, the function is called with a as the Left
> operand and b as the Right, never the reverse.
> 
>  > I should stop wrestling with pigs.
> 
> You are so eager to believe I am wrong about everything I say that
> you are not reading what I say. Stop it. You're just going to annoy
> the pig :-)

No, it is trying to teach a pig to sing that annoys the pig.  When you 
wrestle with pigs, you just get dirty, and the pig enjoys it.  (Of 
course, if the pig is a pet and kept clean, the person doing the 
wrestling may stay clean and actually want the pig to enjoy it.)  But 
this is not a discussion of ENGLISH semantics ;-)

MY point, which apparently you missed, was not that Ada compilers are 
allowed to ignore the order of parameters (except of course with named 
notation). It is that you will find lots of places in the standard where 
order independent SEMANTICS occurs, for example in 13.7.1(7).  In those 
cases the usual implementation (in this case of package 
System.Storage_Elements) will simplify things by using parameter 
flipping and pragma Inline.  If we were to change the semantics of Ada 
to require left-to-right evaluation, what should be done with these 
functions, especially when they are in-lined?  A workable rule probably 
could be written, but it is the sort of thing you have to look at with a 
proposal like yours.

-- 
                                           Robert I. Eachus

"The only thing necessary for the triumph of evil is for good men to do 
nothing." --Edmund Burke




^ permalink raw reply	[relevance 3%]

* Re: Certified C compilers for safety-critical embedded systems
  @ 2004-01-06 13:33  3%                         ` Georg Bauhaus
  0 siblings, 0 replies; 200+ results
From: Georg Bauhaus @ 2004-01-06 13:33 UTC (permalink / raw)


In comp.arch.embedded Dave Hansen <iddw@hotmail.com> wrote:
: On Wed, 31 Dec 2003 14:27:08 +0000 (UTC), Georg Bauhaus
: <sb463ba@l1-hrz.uni-duisburg.de> wrote:
: 
:>In comp.lang.ada Dave Hansen <iddw@hotmail.com> wrote:
: 
: Note: I'm reading from comp.arch.embedded.  Just so you know where I'm
: coming from...

Sorry. I need to adjust my reader software.

: Is the "'access" tag (or whatever you call it)

It's an attribute, like 'address, 'size, 'range, etc.

: Is the "'access" tag (or whatever you call it) _required_ on the call
: if a function is going to modify the parameter?  I like it even better
: if that's true.

Yes, as Stephen has explained. Let me add that if you want a variable
to be modifiably through some pointer you will have to say so.
You declare the variable aliased (using the "aliased" keyword
in the declaration), and point to it using 'access values.

There is also an 'unchecked_access attribute which allows pointers to
aliased local objects to be passed around. The intention is to remind
the programmer/maintainer of the pointer validity check that cannot
in general be done by the compiler as in the following example:

   type Reg16_Ptr is access all Interfaces.Unsigned_16;
   --  pointer to a 16 bit register


   function trig_reg return Reg16_Ptr is
      
      v: aliased Interfaces.Unsigned_16;
      --  16 bits from the toaster's eject trigger, v is local to function
      
      pragma Import(Ada, v);
      --  do not initialise v
      
      for v'address use System.Storage_Elements.To_Address(16#A022#);
      --  hardware address
   begin
      return v'unchecked_access;
      --  points to local v which is really a register, not a value on the
      -- stack
   end trig_reg;


-- Georg



^ permalink raw reply	[relevance 3%]

* Re: [No_Elaboration_Code] GNAT still generating rep_to_pos, why?
  @ 2004-01-04 12:26  4%             ` Simon Wright
  0 siblings, 0 replies; 200+ results
From: Simon Wright @ 2004-01-04 12:26 UTC (permalink / raw)


"Luke A. Guest" <laguest@n_o_p_o_r_k_a_n_d_h_a_m.abyss2.demon.co.uk> writes:

> > I'm not familiar with System'To_Address .. neater than the
> > Storage_Elements version, but more difficult to grep for in the
> > source!
> 
> Well, the difference is that System.Storage_Elements.To_Address is a
> function call and System'To_Address isn't. So with the latter, you
> get a nice static initialisation, which is what is really required
> in this case.

This is a GNAT attribute, I see.

   The System'To_Address (System is the only permissible prefix)
   denotes a function identical to System.Storage_Elements.To_Address
   except that it is a static attribute. This means that if its
   argument is a static expression, then the result of the attribute
   is a static expression. The result is that such an expression can
   be used in contexts (e.g. preelaborable packages) which require a
   static expression and where the function call could not be used
   (since the function call is always non-static, even if its argument
   is static).

> As for grepping, this works for me: grep -r System\'To\_Address *

No, I meant that you can't grep system.ads, so if you are thinking to
yourself "I know there's a To_Address function somewhere ..." you have
a long search ahead of you!

-- 
Simon Wright                               100% Ada, no bugs.



^ permalink raw reply	[relevance 4%]

Results 1-200 of ~390   | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2004-01-02 11:59     [No_Elaboration_Code] GNAT still generating rep_to_pos, why? Luke A. Guest
2004-01-02 17:51     ` Stephen Leake
2004-01-02 18:14       ` Luke A. Guest
2004-01-03  1:12         ` Robert I. Eachus
2004-01-03  8:41           ` Luke A. Guest
2004-01-03 11:53             ` Simon Wright
2004-01-03 12:20               ` Luke A. Guest
2004-01-04 12:26  4%             ` Simon Wright
     [not found]     <3fe00b82.90228601@News.CIS.DFN.DE>
2003-12-26 18:42     ` Certified C compilers for safety-critical embedded systems Hyman Rosen
2003-12-27 13:26       ` Martin Krischik
2003-12-28 16:33         ` Chris Hills
2003-12-29 17:46           ` Dave Hansen
2003-12-30 10:18             ` Martin Krischik
2003-12-30 14:48               ` Dave Hansen
2003-12-30 17:08                 ` Martin Krischik
2003-12-30 19:20                   ` Dave Hansen
2003-12-30 21:15                     ` CBFalconer
2003-12-31  0:03                       ` Dave Hansen
2003-12-31 14:27                         ` Georg Bauhaus
2004-01-05 22:08                           ` Dave Hansen
2004-01-06 13:33  3%                         ` Georg Bauhaus
2004-02-04 10:28     In-Out Parameters for functions Stuart Palin
2004-02-04 15:07     ` Hyman Rosen
2004-02-05 12:11       ` Stuart Palin
2004-02-05 13:22         ` Hyman Rosen
2004-02-06 10:27           ` Stuart Palin
2004-02-24  1:55             ` Hyman Rosen
2004-02-24  2:16               ` David Starner
2004-02-24 14:51                 ` Hyman Rosen
2004-02-24 23:55                   ` David Starner
2004-02-25  0:44                     ` Stephen Leake
2004-02-25  9:33                       ` David Starner
2004-02-25 14:21                         ` Hyman Rosen
2004-02-25 14:34                           ` Vinzent 'Gadget' Hoefler
2004-02-25 15:02                             ` Hyman Rosen
2004-02-25 16:10                               ` Robert I. Eachus
2004-02-25 16:50                                 ` Hyman Rosen
2004-02-26 13:41                                   ` Robert I. Eachus
2004-02-26 15:44                                     ` Hyman Rosen
2004-02-28 17:34  3%                                   ` Robert I. Eachus
2004-02-29  3:51  0%                                     ` Hyman Rosen
2004-04-08 14:52     Pass by reference Dan McLeran
2004-04-09  4:03     ` Steve
2004-04-09 14:50       ` Simon Wright
2004-04-09 17:12         ` Pat Rogers
2004-04-09 19:33           ` Vinzent 'Gadget' Hoefler
2004-04-10  6:33             ` Simon Wright
2004-04-13 10:26               ` Vinzent 'Gadget' Hoefler
2004-04-14 17:27  5%             ` Simon Wright
2004-04-15  9:43  0%               ` Vinzent 'Gadget' Hoefler
2004-04-17  7:59  0%                 ` Simon Wright
2004-05-04  3:20     Manifesto against Vector Alexander E. Kopilovich
2004-05-04 17:16     ` Jeffrey Carter
2004-05-04 18:24       ` Marius Amado Alves
2004-05-05  5:28         ` Russ
2004-05-05 17:37           ` Martin Dowie
2004-05-06  3:42             ` Russ
2004-05-06  7:03               ` Jean-Pierre Rosen
2004-05-06  9:29                 ` Dmitry A. Kazakov
2004-05-06  9:41  3%               ` Vinzent 'Gadget' Hoefler
2004-07-20 21:25  4% Stack overflow using Xml/Ada Jano
2004-08-18 22:27     Ada access vs C/C++ pointers and references Keith H Duggar
2004-08-19  0:21  3% ` Nick Roberts
2004-08-19  0:29  4% ` Jim Rogers
2004-08-19  7:59  1% ` Ole-Hjalmar Kristensen
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  3%             ` Brian May
2004-12-13 21:48     Efficiently setting up large quantities of constant data Michael Mounteney
2004-12-16 12:36     ` Dr. Adrian Wrigley
2004-12-16 14:24       ` Vinzent 'Gadget' Hoefler
2004-12-17 13:53  4%     ` Dr. Adrian Wrigley
2004-12-30 11:29  5% Pointer address Bj?rn
2004-12-30 12:18  0% ` Martin Krischik
2004-12-30 12:23  5% ` Vinzent 'Gadget' Hoefler
2005-01-29 15:58  3% POSIX.Memory_Mapping.Map_Memory Adrian Hoe
2005-01-29 16:20  0% ` POSIX.Memory_Mapping.Map_Memory Mark Lorenzen
2005-01-29 16:31  0%   ` POSIX.Memory_Mapping.Map_Memory Adrian Hoe
2005-01-29 18:44  0%     ` POSIX.Memory_Mapping.Map_Memory Mark Lorenzen
2005-03-01  9:30     Advanced file manipulation (multiple question) Steph-ADA
2005-03-02  2:42     ` Steve
2005-03-02 16:56  5%   ` Jeffrey Carter
2005-03-09 18:03     Easy Question - Printing Out An Address Bryan.Berns
2005-03-09 18:34  4% ` Dmitry A. Kazakov
2005-03-09 21:09       ` Bryan.Berns
2005-03-09 21:22  5%     ` Mark Lorenzen
2005-04-13 12:46     Large arrays (again), problem case for GNAT Dr. Adrian Wrigley
2005-04-13 19:54  6% ` Randy Brukardt
2005-06-13 20:18     Hashing on System.Address Duncan Sands
2005-06-13 21:57  4% ` Matthew Heaney
2005-06-13 23:41  0%   ` Robert A Duff
2005-06-14  2:22  0%     ` Matthew Heaney
2005-06-14  8:44  0%       ` Larry Kilgallen
2005-06-14  8:42  0%     ` Larry Kilgallen
2005-06-14  7:18  0%   ` Duncan Sands
2005-06-14 15:18  0%     ` Matthew Heaney
2005-06-15 15:39  2% Interrupt handler seems not to be called in GNAT 3.15p Thorsten
2005-06-16  6:52  0% ` David C. Hoos, Sr.
2005-07-04 11:01     GCC 4.0 Ada.Containers Cursor danger Dmitriy Anisimkov
2005-07-05 14:51     ` Matthew Heaney
2005-07-05 17:11       ` 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  3%                                   ` Matthew Heaney
2005-07-24 18:15     ++ of C in ada nicolas.b
2005-07-25 20:15  4% ` Robert A Duff
2005-10-11 15:58     hashed_maps Lucretia
2005-10-11 17:45     ` hashed_maps Jeffrey R. Carter
2005-10-12 17:04       ` hashed_maps Lucretia
2005-10-13  5:17         ` hashed_maps Matthew Heaney
2005-10-13 14:45           ` hashed_maps Lucretia
2005-10-13 14:55             ` hashed_maps Matthew Heaney
2005-10-13 15:25               ` hashed_maps Lucretia
2005-10-14  4:41  4%             ` hashed_maps Matthew Heaney
2005-10-13 20:55     ` hashed_maps Björn Persson
2005-10-13 21:27       ` hashed_maps Robert A Duff
2005-10-14  4:49  4%     ` hashed_maps Matthew Heaney
2005-10-29 21:19     Re-exporting primitive operations of a private type (like "-", and 'min) Anonymous Coward
2005-10-30  9:18     ` Jeffrey R. Carter
2005-10-31  4:15       ` Anonymous Coward
2005-10-31  8:27  3%     ` Niklas Holsti
2005-11-15 16:03     Request for comments on simple Ada program Maciej Sobczak
2005-11-15 19:33     ` tmoran
2005-11-16  3:10       ` Ada Quality and Style book discussion Anonymous Coward
2005-11-16  5:49         ` Simon Wright
2005-11-16  7:03           ` Martin Dowie
2005-11-17  4:49             ` Anonymous Coward
2005-11-17 11:45               ` Georg Bauhaus
2005-11-17 12:37                 ` Stephen Leake
2005-11-17 13:24                   ` Georg Bauhaus
2005-11-17 23:15                     ` Stephen Leake
2005-11-19 20:28                       ` Don't use the "use" clause Anonymous Coward
2005-11-19 21:48                         ` Dmitry A. Kazakov
2005-11-19 22:33  4%                       ` Simon Wright
2006-05-04 13:35     Separate type for byte arrays Florian Weimer
2006-05-04 18:15  4% ` Jeffrey R. Carter
2006-07-28 11:06     How to pass two dimensional arrays to C Jerry
2006-07-28 20:46     ` Jerry
2006-07-28 22:54       ` Björn Persson
2006-07-29  1:14         ` Jeffrey R. Carter
2006-07-29  7:11           ` Simon Wright
2006-07-29 22:12             ` Jeffrey R. Carter
2006-07-30 11:18  5%           ` Simon Wright
2006-08-12  8:05  4% "User-Defined Assignment" question Yves Bailly
2006-08-24 16:33  3% call procedure in Linux-Ada-module from "normal" program Frank
2006-09-19 13:30  3% A novel design of linked lists (was: Address of an object) Dmitry A. Kazakov
2007-01-30 15:51     Reading Float Data from a binary file into ada frikk
2007-01-31  3:54     ` Steve
2007-01-31 14:12       ` frikk
2007-01-31 18:38         ` frikk
2007-02-01  0:05  4%       ` Jeffrey R. Carter
2007-02-21 18:09     Text Processing in Ada 95 Rob Norris
2007-02-23  7:53  3% ` Jacob Sparre Andersen
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-05 13:07             ` Robert A Duff
2007-04-05 18:02               ` Stefan Bellon
2007-04-06  1:31                 ` Randy Brukardt
2007-04-06  8:10                   ` Stefan Bellon
2007-04-06 17:17  5%                 ` Simon Wright
2007-04-06 12:38  6%         ` Stephen Leake
2007-04-28  5:03     Reading and writing a big file in Ada (GNAT) on Windows XP Fionn Mac Cumhaill
2007-05-02  7:46     ` george
2007-05-03  6:31       ` Fionn Mac Cumhaill
2007-05-03 20:00         ` Simon Wright
2007-05-04  6:53  5%       ` Alternative Index implementation? (Was: Reading and writing a big file in Ada (GNAT) on Windows XP) Jacob Sparre Andersen
2007-07-25 22:04     Does 3.9.3(10) apply to untagged private whose full view is tagged? Adam Beneschan
2007-07-26  8:58  3% ` anon
2007-08-02 19:21     Byte streams shaunpatterson
2007-08-03  5:34  5% ` Jeffrey R. Carter
2007-09-03  8:59     copying data between memory locations jef.mangelschots
2007-09-03 10:38     ` Martin Krischik
2007-09-04 15:57  3%   ` Adam Beneschan
2007-09-03 11:09  3% ` Niklas Holsti
2007-11-17 21:22     Direct Quote from the RM anon
2007-11-18  7:07     ` Simon Wright
2007-11-18  9:43       ` anon
2007-11-19  0:16         ` Georg Bauhaus
2007-11-20 13:43  4%       ` anon
2007-11-20 15:10  4%         ` parallel translation (was: Direct Quote from the RM) Georg Bauhaus
2007-11-20 17:07  0%         ` Direct Quote from the RM Vadim Godunko
2007-11-21  6:44  0%           ` anon
2007-11-30 19:32  5% Access to fixed memory location Tomas Cernaj
2008-01-27 19:20     Default array base index Scott Burson
2008-01-28 17:02  2% ` Adam Beneschan
2008-01-28 13:49     Allocators and memory reclamation Maciej Sobczak
2008-01-28 15:15     ` Dmitry A. Kazakov
2008-01-28 22:27  5%   ` Maciej Sobczak
2008-01-28 23:54  0%     ` Adam Beneschan
2008-08-08 13:24     Problems with Ada.Streams.Read (blocking) Dennis Hoppe
2008-08-08 13:56     ` Dmitry A. Kazakov
2008-08-08 18:00  4%   ` Dennis Hoppe
2008-09-12  8:35     Adding offset to 'Address Kim Rostgaard Christensen
2008-09-12  9:47     ` Georg Bauhaus
2008-09-12 10:17       ` Kim Rostgaard Christensen
2008-09-12 11:18  4%     ` petter_fryklund
2008-09-12 15:23  6% ` Adam Beneschan
     [not found]     <83d19cd8-71ca-43c1-a3eb-05832290e565@r36g2000prf.googlegroups.com>
2009-01-16 12:18     ` Restarting Tread: Why isn't this program working with Unchecked_Converstion Stuart
2009-01-16 23:14  6%   ` sjw
2009-01-24 20:47     How do I go about creating a minimal GNAT runtime? Lucretia
2009-02-10  2:34  4% ` Exceptions (was Re: How do I go about creating a minimal GNAT runtime?) anon
2009-01-27 14:21  4% cannot generate code for file a-excach.adb (subunit) Lucretia
2009-01-27 14:38  0% ` xavier grave
2009-02-16 20:36     C getchar() functionality in Ada Thomas Locke
2009-02-16 21:43  4% ` Jeffrey R. Carter
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  4%   ` anon
2009-05-03  9:42  0%     ` Martin
2009-06-26 14:41     addr2line i mingw gcc 4.4.0 björn lundin
2009-06-26 20:56     ` sjw
2009-06-26 21:28       ` björn lundin
2009-06-27  0:00         ` Ludovic Brenta
2009-06-27 11:28           ` Stephen Leake
2009-06-27 12:29  3%         ` Dmitry A. Kazakov
2009-06-27 13:05  0%           ` Ludovic Brenta
2009-08-18 22:26     put of access type Rob Solomon
2009-08-18 23:17  4% ` Jeffrey R. Carter
2009-08-19  3:36  0%   ` Rob Solomon
2009-08-19  7:21  6% ` Dmitry A. Kazakov
2009-08-19 19:00  0%   ` Rob Solomon
2009-08-19 19:44  0%     ` sjw
2009-08-20  1:54  0%       ` Rob Solomon
2009-08-20  2:06  0%         ` Rob Solomon
2009-09-24  0:47     Table of pointers question Rob Solomon
     [not found]     ` <3cadnZif2YjGbyfXnZ2dnUVZ_tmdnZ2d@earthlink.com>
2009-09-26 13:36       ` Rob Solomon
     [not found]         ` <3YSdnY7SXPNd_yPXnZ2dnUVZ_sydnZ2d@earthlink.com>
2009-09-26 21:00  4%       ` Georg Bauhaus
2010-04-21 16:43     How to access this package written in C? resander
2010-04-22 21:12     ` Keith Thompson
2010-04-23 12:58       ` resander
2010-04-23 14:15  4%     ` Dmitry A. Kazakov
2010-04-23 14:44         ` John B. Matthews
2010-04-23 15:39  5%       ` John B. Matthews
2010-08-01 12:17     S-expression I/O in Ada Natacha Kerensikova
2010-08-01 16:01  5% ` Ludovic Brenta
2010-08-09 18:49  0%   ` Ludovic Brenta
2010-08-01 18:25  4% ` Jeffrey Carter
2010-10-03 11:27     Does mmap gives a right result?! Francesco PIRANEO GIULIANO
2010-10-04  8:05  6% ` Ludovic Brenta
2010-10-16 17:35     Interfacing C type, unconstrained array with record Ron Wills
2010-10-16 18:36  5% ` Dmitry A. Kazakov
2010-10-16 19:19  0%   ` Ron Wills
2010-10-16 21:41  0%   ` Robert A Duff
2010-10-30 12:03  5% Life-time of temporaries Florian Weimer
2010-10-31 22:00     Beginners question: Compound types, how-to? Mart van de Wege
2010-11-01  3:55     ` Jeffrey Carter
2010-11-01  7:12       ` Mart van de Wege
2010-11-01 15:04         ` Shark8
2010-11-01 17:06           ` Mart van de Wege
2010-11-01 19:19             ` Jeffrey Carter
2010-11-01 19:41  4%           ` Yannick Duchêne (Hibou57)
2010-11-01 20:56  0%             ` Jeffrey Carter
2010-11-03 16:56  0%             ` Warren
2010-11-03 17:01  0%               ` Georg Bauhaus
2010-11-03 17:42  0%                 ` Vinzent Hoefler
2010-11-04  5:23  0%                   ` Stephen Leake
2010-11-03 20:38  0%                 ` Warren
2010-11-03 22:32  0%                   ` Georg Bauhaus
2010-11-03 20:44  0%                 ` Yannick Duchêne (Hibou57)
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  5:52     How do I write directly to a memory address? Syntax Issues
2011-02-12  4:47     ` Edward Fish
2011-02-12  8:02  6%   ` Niklas Holsti
2011-02-03  8:08     mockturtle
2011-02-03 18:07  4% ` Jeffrey Carter
2011-06-07 15:32  6% using `use' : what is the best practice ? milouz
2011-06-07 15:59  3% ` Simon Wright
2011-06-07 19:32  0% ` Anders Wirzenius
2011-06-08  6:06  4% ` stefan-lucks
2011-06-15  2:25  5% ` Adrian Hoe
2011-08-29 15:46     Address and bit mask milouz
2011-08-29 16:06  4% ` Martin
2011-08-29 16:33  0%   ` milouz
2011-08-29 17:47  4%     ` Dmitry A. Kazakov
2011-08-29 17:54  0%     ` Martin
2011-08-29 18:46  4%     ` tmoran
2011-08-29 19:41     ` Ludovic Brenta
2011-08-29 19:54  4%   ` Adam Beneschan
2011-08-30  9:14  4%     ` milouz
2011-08-30 10:34  6%       ` Ludovic Brenta
2011-08-30 14:52  4%         ` Adam Beneschan
2011-08-30 10:40  6%       ` Simon Wright
2011-08-30 12:35  3%       ` Georg Bauhaus
2011-08-30 15:14  2%       ` Adam Beneschan
2011-08-30 15:59  4%         ` Adam Beneschan
2011-08-29 17:14  6% Some idea could be: Per Sandberg
2011-08-29 19:17  0% ` Dmitry A. Kazakov
2012-03-25 14:28     xor Michael Moeller
2012-03-25 14:01     ` xor Niklas Holsti
2012-03-25 15:16       ` xor Michael Moeller
2012-03-25 19:26         ` xor Niklas Holsti
2012-03-27 20:09           ` xor Michael Moeller
2012-03-27 20:13  4%         ` xor Jeffrey Carter
2012-05-11  3:49     understanding runtime support Patrick
2012-05-15 14:48  3% ` Lucretia
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  2%     ` 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  4%                                   ` 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  6%     ` Georg Bauhaus
2012-07-22 16:21     ` Florian Weimer
2012-07-22 17:34       ` Niklas Holsti
2012-07-24 16:00         ` robin.vowels
2012-07-25  7:09           ` Niklas Holsti
2012-07-25  9:03             ` Keean Schupke
2012-07-26  0:15               ` Randy Brukardt
2012-07-26  8:38                 ` Keean Schupke
2012-07-26 10:10                   ` Brian Drummond
2012-07-26 12:32                     ` Keean Schupke
2012-07-27  8:21                       ` Keean Schupke
2013-02-25 21:18  5%                     ` Eryndlia Mavourneen
2013-01-14 17:43     GNAT 4.4.5 Record Bit_Order Endian issues awdorrin
2013-01-15 22:24     ` Stephen Leake
2013-01-16 10:44       ` Simon Wright
2013-01-17  3:49         ` Stephen Leake
2013-01-17 15:32           ` awdorrin
2013-01-18  9:49             ` Stephen Leake
2013-01-18 13:04               ` Robert A Duff
2013-01-19  1:43                 ` Stephen Leake
2013-01-19 12:48  4%               ` AdaMagica
2013-01-22  0:14  0%                 ` Randy Brukardt
2013-05-26 23:34  4% Unchecked_Conversion vs Address-overlaying Shark8
2013-05-27  4:37  0% ` Per Sandberg
2013-11-12 11:09     Increasing GNAT's heap Dmitry A. Kazakov
2013-11-12 13:26     ` Georg Bauhaus
2013-11-12 14:00       ` Dmitry A. Kazakov
2013-11-12 19:30  4%     ` Georg Bauhaus
2014-02-27  5:19     subtype of System.Address type ashwath30jul77
2014-02-27 16:06  6% ` adambeneschan
2014-04-19 14:31     OpenSSL development (Heartbleed) Alan Browne
2014-04-19 15:36     ` Georg Bauhaus
2014-04-19 16:00       ` Yannick Duchêne (Hibou57)
2014-04-19 16:34         ` Georg Bauhaus
2014-04-21 23:51           ` Randy Brukardt
2014-04-22 15:20             ` G.B.
2014-04-22 16:33               ` Dmitry A. Kazakov
2014-04-22 16:57                 ` Simon Clubley
2014-04-22 19:53                   ` Dmitry A. Kazakov
2014-04-23  5:38                     ` Natasha Kerensikova
2014-04-23  7:30                       ` Dmitry A. Kazakov
2014-04-23  8:06  5%                     ` Georg Bauhaus
2014-07-06 15:19     Ada's ranking of popularity at IEEE Spectrum Dan'l Miller
2014-07-06 16:25     ` gautier_niouzes
2014-07-06 17:18       ` Dan'l Miller
2014-07-06 22:15         ` Brad Moore
2014-07-07 13:14           ` Peter Chapin
2014-07-09 15:01             ` Brad Moore
2014-07-10  7:42               ` Maciej Sobczak
2014-07-10 18:18                 ` Nasser M. Abbasi
2014-07-10 18:30                   ` Nasser M. Abbasi
2014-07-11 11:56  4%                 ` G.B.
2014-08-12  6:54     A simple question about the "new" allocator NiGHTS
2014-08-12  7:35     ` Dmitry A. Kazakov
2014-08-12 13:38  6%   ` G.B.
2015-01-05 14:49     X'Alignment and System.Address without a "mod" operator? Jacob Sparre Andersen
2015-01-05 16:47  4% ` Jeffrey Carter
2015-01-05 20:07  0%   ` Jacob Sparre Andersen
2015-07-06 16:17     Arduino Due vs Mac Simon Wright
2015-07-06 20:34     ` Maciej Sobczak
2015-07-06 21:29       ` Simon Wright
2015-07-07 11:08  4%     ` Simon Wright
2015-07-10 11:48  4% Q: setting an address with pure? Simon Wright
2015-07-10 12:03  0% ` G.B.
2015-07-10 14:38  0%   ` Simon Wright
2015-07-10 22:37  4% ` Randy Brukardt
2015-07-11  7:47  3%   ` Simon Wright
2015-07-13 19:10  0%     ` Randy Brukardt
2015-07-11 10:35  0% ` Q: " Brian Drummond
2015-07-11 13:30       ` Simon Wright
2015-07-11 14:03         ` AdaMagica
2015-07-11 14:27           ` Simon Wright
2015-07-13 18:53  5%         ` Randy Brukardt
2015-07-13 19:50  0%           ` Simon Wright
2016-01-11  1:37     Why is the destructor called multiple times after I declare an object? Andrew Shvets
2016-01-11  2:18     ` Jeffrey R. Carter
2016-01-11 16:29       ` Brian Drummond
2016-01-11 18:17         ` Bob Duff
2016-01-11 21:10           ` Dmitry A. Kazakov
2016-01-11 23:44             ` Randy Brukardt
2016-01-12  9:33               ` Dmitry A. Kazakov
2016-01-12 20:21                 ` Randy Brukardt
2016-01-12 21:05  4%               ` Dmitry A. Kazakov
2016-01-13  0:02  0%                 ` Robert A Duff
2016-02-07 22:45  4% ANN: Cortex GNAT RTS 20160207 Simon Wright
2016-03-14 17:42  4% ANN: Cortex GNAT RTS 20160314 Simon Wright
2016-05-22 14:20  3% 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  3%             ` 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  4%                         ` Warren
2016-06-21  5:52  0%                           ` Niklas Holsti
2016-06-21 10:31  0%                             ` Warren
2016-06-21 21:38  0%                               ` Niklas Holsti
2016-11-16 18:01  3% s-stoele.ads:62:69: error: cannot convert to a pointer type Lucretia
2017-01-24 13:12     Dynamic type system for Ada Victor Porton
2017-01-24 13:44     ` Dmitry A. Kazakov
2017-01-24 13:58       ` Victor Porton
2017-01-24 18:07  4%     ` Jeffrey R. Carter
2017-04-24 16:06     avoiding builtin memset Jere
2017-04-24 16:56  5% ` Shark8
2017-04-25  1:21  0%   ` Anh Vo
2017-04-25  2:57  0%     ` Luke A. Guest
2017-04-27  0:22  0%   ` Jere
2017-05-24 15:08  5% ` Frédéric PRACA
2017-11-01 18:44     some trivial questions? tclwarrior
2017-11-02  1:19     ` tclwarrior
2017-11-02  8:27       ` Dmitry A. Kazakov
2017-11-02 13:21  3%     ` Simon Wright
2017-11-02 13:34  0%       ` Dmitry A. Kazakov
2017-11-06 22:58  4%         ` Robert A Duff
2018-05-29 19:41     Memory pools John Perry
2018-05-31 19:28  5% ` gorgelo
2018-05-31 19:33  4% ` gorgelo
2018-07-14  2:36     Ada: A beginners experience blakemichael073
2018-07-14  2:53     ` Dan'l Miller
2018-07-14  3:53       ` blakemichael073
2018-07-14 14:57         ` Jere
2018-07-16 21:38           ` Maciej Sobczak
2018-07-20 12:00  4%         ` Jere
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  4%   ` Niklas Holsti
2019-02-16 19:40  6% Alignment issue Simon Wright
2019-07-19 21:41     How to make Ada popular. Get rid of ";" at end of statement Nasser M. Abbasi
2019-07-23 21:58     ` Ingo M.
2019-07-24 14:06       ` John Perry
2019-07-25  7:26         ` Maciej Sobczak
2019-07-27  1:27           ` Lucretia
2019-07-27  1:34             ` Keith Thompson
2019-07-27  3:11  3%           ` Randy Brukardt
2019-07-27  4:06  0%             ` Keith Thompson
2019-08-11 14:19  3% Proper way to license a ZFP runtime Jere
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  5%     ` joakimds
2020-01-23 15:02  5%       ` joakimds
2020-01-23 20:15  0%       ` Optikos
2020-04-14  7:15     Put the access value ldries46
2020-04-14  7:42  4% ` J-P. Rosen
2020-04-18 15:08  0%   ` Oliver Kellogg
2020-04-20 23:02  0%   ` Robert A Duff
2021-01-09  9:30     Record initialisation question DrPi
2021-01-09 15:44     ` Niklas Holsti
2021-01-10 16:53       ` DrPi
2021-01-10 19:30         ` Niklas Holsti
2021-01-10 21:27           ` DrPi
2021-01-10 22:14             ` Niklas Holsti
2021-01-11 17:46               ` DrPi
2021-01-11 20:58                 ` Niklas Holsti
2021-01-14 13:07                   ` DrPi
2021-01-14 14:27  3%                 ` Niklas Holsti
2021-01-15  7:49  4%                   ` DrPi
2021-03-04 15:59  3% converting pointer to value Björn Lundin
2021-03-04 16:55  0% ` Shark8
2021-03-04 17:35  0%   ` Dmitry A. Kazakov
2021-03-04 19:38  4%     ` Shark8
2021-03-04 21:27  0%       ` Dmitry A. Kazakov
2021-03-05  8:58  0%         ` Björn Lundin
2021-03-05 11:02  0%     ` Björn Lundin
2021-03-05 11:57           ` Björn Lundin
2021-03-05 14:00  4%         ` Dmitry A. Kazakov
2021-03-09 12:07  3%     ` [SOLVED] " Björn Lundin
     [not found]     <609a5eaf$0$20558$e4fe514c@news.kpn.nl>
2021-05-11 12:41  5% ` Printing the address Niklas Holsti

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