❌ About FreshRSS

Normal view

There are new articles available, click to refresh the page.
Before yesterdayNewest questions tagged ada - Stack Overflow

Using Attribute Scalar_Storage_Order in ada with gcc 6.2.1

I'm currently trying to find a solution to control the storage order for elements within a record in ADA.

I'm using gcc 6.2.1 which doesnt recognize the Scalar_Storage_Order attribute ( even though the attribute is clearly referenced in the gcc 6.2 GNAT reference manual).

type Rec is record

      Data1 : T_Data;
      Data2 : T_Data;

   end record;

for Rec use
      record

         Data1      at 0 range 0 .. 15;
         Data2      at 0 range 0 .. 15;

      end record;

for Rec'Bit_Order use System.High_Order_First;
for Rec'Scalar_Storage_Order use System.High_Order_First;

error: unrecognized attribute "Scalar_Storage_Order"

Is there an alternative that I can use to achieve my goal?

Cannot run Gnat Studio

I'm trying to run Gnat Studio on Ubuntu 22.04 but I get the following error:

/opt/gnatstudio/bin/gnatstudio_exe: error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory

I have installed it via the following steps:

  • Downloaded the "x86 GNU Linux (64 bits)" community edition and ran this
  • Ran /opt/GNAT/2021/doinstall
  • Ran /opt/gnatstudio/bin/gnatstudio and got the above error (sudo-running this yields the same error)

I'm wondering if this is down to 22.04 being a very recent release and some shared libraries are missing from the installation bundle?

Any pointers would be much appreciated.

Thanks

SPARK Ada: Overlays Without Copying

I am trying to create a view of an array object to better utilise SIMD vectors on the x86_64 platform.

Here's the main idea:

   type Char_Set_Index is range 0 .. 7;
   type Char_Set_Element is mod 2 ** 32;
   
   type Character_Set_Vector is array (Char_Set_Index) of Char_Set_Element
     with Alignment => 32,Component_Size => 32, Object_Size => 256, Size => 256;
   
   type Character_Set is array (Character) of Boolean
     with Alignment => 32, Component_Size => 1, Object_Size => 256, Size => 256;

Essentially, some of the operations in Ada.Character.Maps can better be processed using SIMD arithmetic. For instance the "=" operation, perhaps coded as,

   function "="
     (Left, Right : in Character_Set)
      return Boolean
   is
     (for all k in Character_Set'Range =>
         (Left(k) = Right(k)));

.. gives us the following output

.LFB4:
    .cfi_startproc
    movq    %rdi, %r8
    movq    %rsi, %rdi
    xorl    %esi, %esi
    jmp .L6
    .p2align 4,,10
    .p2align 3
.L10:
    addl    $1, %esi
    cmpl    $256, %esi
    je  .L9
.L6:
    movl    %esi, %edx
    movl    %esi, %ecx
    sarl    $3, %edx
    andl    $7, %ecx
    movslq  %edx, %rdx
    movzbl  (%rdi,%rdx), %eax
    xorb    (%r8,%rdx), %al
    shrb    %cl, %al
    testb   $1, %al
    je  .L10
    xorl    %eax, %eax
    ret
.L9:
    movl    $1, %eax
    ret
    .cfi_endproc

Critically, it is comparing each bit, and GCC won't vectorise it. However, if we write,

   function "="
     (Left, Right : in Character_Set)
      return Boolean
   is
      
      u : aliased constant Character_Set_Vector
        with Import, Address => Left'Address;
      
      v : aliased constant Character_Set_Vector
        with Import, Address => Right'Address;
   
      Temp : array (Char_Set_Index) of Integer;
      Sum  : Integer;
   
   begin
   
      for j in Temp'Range loop
         pragma Loop_Optimize (Vector);
         Temp(j) := (if u(j) = v(j) then 0 else 1);
      end loop;
   
      Sum := 0;
      for j in Temp'Range loop
         Sum := Sum + Temp(j);
      end loop;
   
      return Sum = 0;
   
   end "=";

We get the branch-free SIMD instructions that we kind of expect,

    .cfi_startproc
    vmovdqa (%rdi), %ymm1
    vpcmpeqd    (%rsi), %ymm1, %ymm1
    vpandn  .LC0(%rip), %ymm1, %ymm1
    vextracti128    $0x1, %ymm1, %xmm0
    vpaddd  %xmm1, %xmm0, %xmm0
    vpsrldq $8, %xmm0, %xmm1
    vpaddd  %xmm1, %xmm0, %xmm0
    vpsrldq $4, %xmm0, %xmm1
    vpaddd  %xmm1, %xmm0, %xmm0
    vmovd   %xmm0, %eax
    testl   %eax, %eax
    sete    %al
    vzeroupper
    ret
    .cfi_endproc

Which all works rather well. Now, the problem at hand. If you push this code through SPARK Ada, there are a number of complaints regarding alignment, aliasing, and constants, so you have to end up writing,

   function "="
     (Left, Right : in Character_Set)
      return Boolean
   is
      
      Left_Aligned : constant Character_Set := Left
        with Alignment => 32;
      
      Right_Aligned : constant Character_Set := Right
        with Alignment => 32;
      
      u : aliased constant Character_Set_Vector
        with Import, Alignment => 32, Address => Left_Aligned'Address;
      
      v : aliased constant Character_Set_Vector
        with Import, Alignment => 32, Address => Right_Aligned'Address;
   
      Temp : array (Char_Set_Index) of Integer;
      Sum  : Integer;
   
   begin
   
      for j in Temp'Range loop
         pragma Loop_Optimize (Vector);
         Temp(j) := (if u(j) = v(j) then 0 else 1);
      end loop;
   
      Sum := 0;
      for j in Temp'Range loop
         Sum := Sum + Temp(j);
      end loop;
   
      return Sum = 0;
   
   end "=";

which gives us an awful lot of precopying, presumably to ensure that everything is aligned OK - even though the declarations already have the correct alignment,

    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    andq    $-32, %rsp
    vmovdqa (%rdi), %xmm2
    vmovdqa 16(%rdi), %xmm3
    vmovdqa (%rsi), %xmm4
    vmovdqa 16(%rsi), %xmm5
    vmovdqa %xmm2, -64(%rsp)
    vmovdqa %xmm3, -48(%rsp)
    vmovdqa -64(%rsp), %ymm6
    vmovdqa %xmm4, -32(%rsp)
    vmovdqa %xmm5, -16(%rsp)
    vpcmpeqd    -32(%rsp), %ymm6, %ymm1
    vpandn  .LC0(%rip), %ymm1, %ymm1
    vextracti128    $0x1, %ymm1, %xmm0
    vpaddd  %xmm1, %xmm0, %xmm0
    vpsrldq $8, %xmm0, %xmm1
    vpaddd  %xmm1, %xmm0, %xmm0
    vpsrldq $4, %xmm0, %xmm1
    vpaddd  %xmm1, %xmm0, %xmm0
    vmovd   %xmm0, %eax
    testl   %eax, %eax
    sete    %al
    vzeroupper
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc

Obviously, the only reason one would even bother with this is for greater performance, however, the SPARK Ada rules seem too restrictive in this case, hurting performance. So, my question is, is there a better way of doing this that doesn't result in the excessive moving data around, where, as far as I can tell, it's not required.

Incidentally, Ada.Unchecked_Conversion similarly does a lot of moving data around at the beginning, too.

Also, I realise that I can justify the SPARK Ada checks (false-positive) so I can use the Ada version, but I am hoping that I am missing something, here, and that there is an easier way to do this.

Perhaps there is a way of vectorising arrays of Booleans?

EDIT: I am compiling it using

gnatmake -O3 -mavx2 -gnatn -gnatp -S name-of-package.adb

An array of records containing variable-length strings

I would like to have a record with an integer and a variable-length string in it, something like this:

type Entry is
record
    Value: Integer;
    Label: String;
end record;

I ran into the issue that you can't put an unconstrained String in a record type, so following the advice at that link I tried

type Entry(Label_Length : Natural) is
record
    Value: Integer;
    Label: String(1..Label_Length);
end record;

But now the problem is, I want an array of these things:

Entries : Array(1..2) of Entry := (
    (Label_Length => 0, Value => 1, Label => ""),
    (Label_Length => 0, Value => 2, Label => "")
);

and I'm getting told

main.adb:17:28: unconstrained element type in array declaration

I just want to be able to declare a (constant) array of these things and type in the labels and values in an intuitive way (I already wasn't crazy about having to count string lengths and type in Label_Length by hand). How can I do this?

adding -gnatp flag to a file/package in GPS [duplicate]

I use Ada With GPS (GNAT Programming Studio). The flag "-gnatp" when building will ignore among others constraint errors.

I know a way to add the flag to all the files, using Edit->Preferences->Build target.

Is there a way to choose when the builder will this flag, meaning setting the flag to a file or a package?

How can I serialize and deserialize a private type?

I'm working with the GNAT.OS_Lib module to implement a process manager for Linux. I'm using the subprograms in that module to spawn processes and get back PIDs, and now I want to save those PIDs to a file so they can be retrieved later to kill the process, get its status, etc. The problem is, the Process_Id type is private:

type Process_Id is private; -- s-os_lib.ads, line 743

The module provides a Pid_To_Integer function, but not the inverse. How can I serialize and deserialize Process_Ids?

How can I start a process and convert its PID to/from an integer?

I'm writing a process manager in Ada, for Linux. I'm using GNAT.OS_Lib to spawn processes:

Pid := GNAT.OS_Lib.Non_Blocking_Spawn(
    Program_Name => Program,
    Args => Arguments
);

This gets me back the PID as a Process_Id, an OS_Lib private type. I would like to be able to store this PID in a file as an integer, for compatibility with other, non-Ada code, and then re-load it later from that file and use it from within Ada to kill the process, check its status, etc.

OS_Lib provides a Pid_To_Integer function, but not the inverse.

Perhaps I need a different library? As far as I can tell, there are no current Ada POSIX libraries. Should I write one myself? I only need support for like three POSIX calls. I'm open to all suggestions.

Where is the actual character set for Ada program text defined?

I'm trying to make a tree-sitter parser, so that IDEs (in this case, Vim) can parse and do more advanced manipulation of Ada program text, such as extract-subprogram and rename-variable. But there seem to be some problems defining the character set.

In the Ada 2012 Reference Manual, I found a list of vague category descriptions, of the form 'Any character whose General Category is X' which means that for instance, besides the underscore, all of these ( β€Ώ ⁀ ⁔ οΈ³ οΈ΄ ﹍ ﹎ ﹏ οΌΏ) are also allowed in an identifier, which seems absurd, and GNAT rejects with 'illegal character'. The list is prefaced by this statement:

"The actual set of graphic symbols used by an implementation for the visual representation of the text of an Ada program is not specified."

Does that really mean there's no way to know which characters should be accepted?

Two pages on, these examples are explicitly given as valid identifiers, and yet GNAT 2021 rejects them:

procedure Main is
   Πλάτων  : constant := 12;     -- Plato
   Чайковский : constant := 12;  -- Tchaikovsky
   ΞΈ, Ο† : constant := 12;        -- Angles
begin
   null;
end Main;
$ gprbuild
using project file foo.gpr
Compile
   [Ada]          main.adb
main.adb:2:04: error: declaration expected
main.adb:2:05: error: illegal character
main.adb:3:04: error: declaration expected
main.adb:3:05: error: illegal character
main.adb:4:05: error: illegal character
gprbuild: *** compilation phase failed

Where is the actual character set for Ada programs defined? Has GNAT 2021 got it wrong?

An example program using Unicode characters in identifiers is below for your experimentation. Note that the use of wide characters in the literal string is outside the scope of the question.

main.adb:

with Ada.Wide_Text_IO; use Ada.Wide_Text_IO;

procedure Main is
   δΡδομένα_πράμα : constant Wide_String := "Ο Πλάτων ΞΈΞ± ΡνέκρινΡ";
begin
   Put_Line (ΔΡδομένα_πράμα);
end Main;

foo.gpr

project foo is

   for Source_Dirs use (".");
   for Main use ("main.adb");

   package Compiler is
      for Default_Switches ("ada") use ("-gnatW8", "-gnatiw");
   end Compiler;

end foo;

To build & run:

gprbuild
./main

Input masks in Ada

-- Date: 11/06/2022

with Ada.Text_IO; Use Ada.Text_Io;

procedure Masques is
  
    type XX is record
       X1 : character range 'A'..'D';
       X2 : character range 'E'..'H';
       X3 : character range 'I'..'L';
    end record;

begin

    Get_Line (XX);

end Masques;

I'm trying to write some sort of input masks to control the inputs as we do in IT. Of course the above example doesn't compile because Get_Line can't accept a record. Of course we can write an operation to put the characters together to create a string, thru a get or get_immediate.

-But the idea would be to use the language typing to control the input & to trap the errors by an exception by example.

-Some years ago, to the best of my recollection, i remember someone did this, but I'm unable to write it.. Thanks for the help.

Starting Gnat Studio with Alire fails

I have had a try at using Gnat Studio with the Alire package manager. Launching Gnat Studio using the 'alr edit' command is causing Gnat Studio to crash. I have had a look at the log file and there are several .dll files causing exceptions. The file entries are like this:

[PROJECTS.EXCEPTIONS] Unexpected exception: raised CONSTRAINT_ERROR : gnatcoll-projects.adb:5729 index check failed _PROJECTS.EXCEPTIONS_ [C:\GNATSTUDIO\bin\gps.libgnatcoll\libgnatcoll.dll] _PROJECTS.EXCEPTIONS_ 0x7ffc78dcecb8 ??? at ???

Gnat Studio opens in an 'inconsistent state' and crashes.

Regards Mike

gnatcoll-db includes dborm.py, need to understand routines in python

I was using gnatcoll-db, but the limitations made me to rewrite dborm.py in Ada. There are two routines in dborm.py (in python) that I don't understand, specifically compute_table_aliases and fields_count_array.

Any help will be welcome. Of course, the modifications can be shared between all of us.

Edited to complete information:

My project fork is here. I don't want to copy here the complete routines from dborm.py as I don't know exactly the license terms of ACS. dborm.py can be downloaded from https://github.com/AdaCore/gnatcoll-db/tree/master/gnatcoll_db2ada.

The routines that I want to translate to Ada are:

  • compute_table_aliases, lines 2407 to 2448. Really I don't understand the algorithm.
  • fields_count_array and fields_count, lines 2372 to 2397. For these routines I have a translation to Ada but when testing, the result is OK except in a few cases.

Here is my translation to Ada:

Max_Depth : constant := 3; type Counts_Array is array (0 .. Max_Depth) of Integer;

  function Fields_Count_Array (T         : Table_Description;
                               Follow_LJ : Boolean;
                               DepthMax  : Integer;
                               FKStop    : Field := No_Field)
                            return Counts_Array is
     FK_Stop : Boolean; -- to be reset before each call to fields_count_
     Depth   : Integer := 0;
     Temp    : Counts_Array;

     function Fields_Count (T         : Table_Description;
                            Depth     : Integer;
                            Follow_LJ : Boolean;
                            FKStop    : Field := No_Field) return Integer;
     function Fields_Count (T         : Table_Description;
                            Depth     : Integer;
                            Follow_LJ : Boolean;
                            FKStop    : Field := No_Field)
                         return Integer is
        Result : Integer;
        procedure Process_FK (FK : in out Field);
        procedure Process_FK (FK : in out Field) is
        begin
           if FK = FKStop then
              FK_Stop := True;
              return;
           end if;
           if FK_Stop then
              return;
           end if;
           if Follow_LJ or (not FK.Can_Be_Null) then
              Result := Result +
                Fields_Count (Pointed_Table (FK), Depth - 1, Follow_LJ);
           end if;
        end Process_FK;
     begin
        Result := Num_Fields (T);
        if Depth > 0 then
           For_Each_FK (T, Process_FK'Access);
        end if;
        return Result;
     end Fields_Count;

  begin
     while Depth <= DepthMax loop
        FK_Stop := False;
        Temp (Depth) := Fields_Count (T, Depth, Follow_LJ, FKStop);
        Depth := Depth + 1;
     end loop;
     return Temp;
  end Fields_Count_Array;

Note that all type definitions come from gnatcoll-sql.

I understand that this is difficult to follow, perphaps may be better if I send a report on the modifications and the complete new Ada package replacing dborm.py. How?

Get output from array in Ada

I want to print array data user input. But it give me error. I need to get input from user and store in the array. After this i want to print it also count each duplicate word.

with Ada.Text_IO;
use Ada.Text_IO;    

procedure Main is
   type String_Val is array (1 .. 100) of Character;
   type Int_Val is array (1 .. 100) of Integer;
   Data : String_Val;
begin
   Put_Line ("Please enter values (use space as seperator)");
   for I in 1..String_Val'Length loop
      Data(I) := Character'Value(Get_Line);
   end loop;
   for I in String_Val'Range loop
      Put (String_Val (Data));
   end loop;
end Main;

Defining a package with its sub units in Package Name?

I have run across code in Ncurses which defines packages with dot, "." subunits in the name, like this: Package body example.subunit1.subunit1 is .... .... end example;

Would I not just name the package "example" only and then later with example.subunit1; use example.subunit1;

OR does older Ada code (as found in Ncurses) have syntax to put a package's subunits in the package name?

No language defined for the project: Ada GNAT GPS

I've been having this issue where I've installed the GNAT (x86 windows 2017) on my other machine, and I suddenly have these errors, Error: no native compiler found for language 'ada', default runtime and no languages defined for this project. All of this is under the .gpr file of my project. This never happened to me on the other PC.

Maximum line length Ada.Text_IO.Put_Line

I'm using GNATColl-sql to create SQL queries. I was thinking to perform a visual inspection of the generated SQL code using the "To_String" method, but when I call Ada.Text_IO.Put_Line or Ada.Text_IO.Put to see the SQL string, a carriage return is being added to the output.

For example, I cannot share the real query, if I expect:

SELECT orders.order_id, customers.last_name FROM orders INNER JOIN customers ON orders.customer_id = customers.customer_id WHERE orders.order_id <> 1 ORDER BY orders.order_id;

What I'm getting after Put_Line/Put instead (notice the line break at customers.cust CRLF omer_id):

SELECT orders.order_id, customers.last_name FROM orders INNER JOIN customers ON orders.customer_id = customers.cust
omer_id WHERE orders.order_id <> 1 ORDER BY orders.order_id;

I first suspected that carriage return was due to a GNATColl-sql bug, but now I suspect the procedure Ada.Text_IO.Put_Line has a maximum line length to print. Am I right?

I tried the procedure "Ada.Text_IO.Set_Line_Length" with a huge count value, greater than the position where the carriage return is added, but it is printed at the same place.

How can I print a large string on a line instead of several lines?

New suspicion:

I was running my main on GNATStudio, but if I directly run the main.exe on a cmd I can see the SQL on a line now. GNATStudio may be configuring a maximum line length for printing.

How do I define and statically initialize a vector index by an enumeration?

I'm unable to define a vector using an enumeration as an index.

First I define my record:

type contact_name is record
    first    : unbounded_string;
    last     : unbounded_string;
end record;

I define my enumeration:

type profession is (plumber, doctor, lawyer, ombudsman, dealer);

I declare my vector of contact_name using professional as the index type:

package Pro_Vector is new Ada.Containers.Vectors (Index_Type => Profession, Element_Type => contact_name);

Finally, I build my table:

Pro_Table : Pro_Vector.Vector := (plumber, ("Bob","daPlumah")) & 
(doctor, "Felix", "FeelGood"))

When I try to compile it says expect signed integer type of Index_Type. It also claims Pro_Vector is undefined. I substituted profession for natural and it compiled, but my static initialization has errors.

Why won't it accept my enum as an index. I was under the impression that Ada is super safe. By using an unconstrained type like Natural, doesn't it compromise safety. Also, how do I statically initialize my vector?

How to use different fix point types in mathematical operations in Ada?

For the program at the end I get the following error messages from gnat:

test2.adb:23:61: error: invalid operand types for operator "-"
test2.adb:23:61: error: left operand has type "Gain_Type" defined at line 11
test2.adb:23:61: error: right operand has type "Offset_Type" defined at line 12

Unfortunately I did not find a good example how to resolve this in a way resulting in speed optimized code for rather small embedded targets.

Always casting everything to the biggest type does not make that much sense I feel. What is the best way to do that/ isn't there a good reference existing how to efficiently use fixed point for a bit more complicated mathematical problems?

procedure Test2 is
   Adc_Width   : constant Positive := 10;
   Adc_Delta   : constant Float    := 2.0**(-Adc_Width);
   Adc_Mod   : constant    := 2**Adc_Width;
   Error_Delta : constant          := 2.0**(-1);
   Gain_Min    : constant Float    := 1.0 - 2.0 * Adc_Delta;
   Gain_Max    : constant Float    := 1.0 + 2.0 * Adc_Delta;
   Offset_Min  : constant Float    := -0.5 * Adc_Delta;
   Offset_Max  : constant Float    := 2.0 * Adc_Delta;
   type Gain_Type is delta Adc_Delta * Error_Delta range Gain_Min .. Gain_Max;
   type Offset_Type is
      delta Adc_Delta * Error_Delta range Offset_Min .. Offset_Max;
   type Adc_Encoded_Type is mod Adc_Mod with
      Size => 16;
   subtype Adc_Value_Type is natural range 0 .. Adc_Encoded_Type'Modulus - 1;
   type Adc_Delta_Type is delta Adc_Delta range 0.0 .. 1.0 - Adc_Delta;
   function Compensate
    (Adc : in Adc_Encoded_Type; Gain : in Gain_Type; Offset : in Offset_Type)
     return Adc_Delta_Type
   is
   begin
      return Adc_Delta_Type (((Adc_Value_Type (Adc) * Gain) - Offset) / Adc_Mod);
   end Compensate;
begin
end Test2;
❌
❌