Ada object declarations "Unsigned Not Declared in System" - ada

In some code that I inherited, I get the compile error "Unsigned" not declared in "System".
I'm trying to compile this using GNAT, but ultimately the code must compile with the original tools, which I don't have ready access to. So I'd like to understand how to resolve this from within the development environment (including the project file), and not modify the existing code.
I checked the file system.ads, and Unsigned is not defined there. Am I referring to the wrong libraries? How would I resolve this with the self imposed constraint mentioned above (to compile in the original environment)?

unsigned is the name of a predefined type in C. If what you need it an Ada type that matches the C type, what you need is Interfaces.C.unsigned. An older Ada implementation (before Interfaces.C was introduced by the 1995 standard) might have defined System.Unsigned for this purpose.
It would help to know what Ada implementation the code was originally written for.
You should examine the code to see whether it uses that type to interface to C code. If not (i.e., if it's just being used as a general unsigned integer type), you might instead consider defining your own modular type.
If I understand correctly, you need the code to compile both in the original environment and with GNAT. That might be difficult. One approach would be to define a new package with two different versions, one for the original environment and one for GNAT (or, ideally, for any modern Ada implementation). For example:
-- version for original environment
with System;
package Foo is
subtype Unsigned is System.Unsigned;
end foo;
and:
-- version for GNAT
with Interfaces.C;
package Foo is
subtype Unsigned is Interfaces.C.Unsigned;
end Foo;
Picking a better name than Foo is left as an exercise, as is determining automatically which version to use.

You could rebuild the GNAT runtime system (RTS) with a slightly modified system.ads.
There’s a Makefile.adalib in the system RTS (well, there is in GNAT GPL 2014) which lets you do this. It’s at the last directory indicated in the “Object Search Path” section of the output of gnatls -v.
The RTS source is similarly indicated in the “Source Search Path” section.
Create a directory say unsigned with subdirectories adainclude, adalib.
Copy the RTS source into unsigned/adainclude, and edit system.ads to include
type Unsigned is mod 2 ** 32;
(I’m guessing a bit, but this is probably what you want!)
Then, in unsigned/adalib,
make -f Makefile.adalib ADA_INCLUDE_PATH=../adainclude ROOT=/opt/gnat-gpl-2014
(ROOT is where you have the compiler installed; it will be different on your system, it’s one above the bin directory in which gnatls and friends are installed).
There will be several errors during this, all caused (when I tried it) by units that use System.Unsigned_Types;. Work round this by inserting this immediately after the package body in the .adb:
subtype Unsigned is System.Unsigned_Types.Unsigned;
The files I had to change were
s-expmod.adb
s-expuns.adb
s-imgbiu.adb
s-imgrea.adb
s-imguns.adb
s-imgwiu.adb
s-valint.adb
s-valuns.adb
s-vercon.adb
It may be best at this stage to remove all the .ali and .a files from unsigned/adalib and repeat, to get a clean build.
Now, you should be able to use System.Unsigned by
gnatmake --RTS=/location/of/unsigned t.adb
In my case, t.adb contained
with System;
with Ada.Text_IO; use Ada.Text_IO;
procedure T is
begin
Put_Line ("first: " & System.Unsigned'First'Img);
Put_Line ("last: " & System.Unsigned'Last'Img);
Put_Line ("42: " & System.Unsigned'Value ("42")'Img);
Put_Line ("16#42#:" & System.Unsigned'Value ("16#42#")'Img);
end T;
and the output was
$ ./t
first: 0
last: 4294967295
42: 42
16#42#: 66

Related

What is the Ada equivalent of #define in C++?

I'm new to Ada and as far as I could explore on the internet, I was unable to find an analog to this C++ concept.
Say I have package_name.data_member (multiple variables in various packages). I'm hoping to shorten that to a more reader-friendly manner like below (without using the Use keyword) because those variables will be used multiple times in the same file -
#define A package_name.data_member
#define B package_name.data_member
...
Is there a way I can do the above in Ada?
In this case you need an object renaming declaration (ARM 8.5.1):
A : Data_Member_Type renames Package_Name.Data_Member;
If you’re using GNAT, it includes a tool gnatprep; the major differences from cpp are that
symbols to be substituted have to be marked in the source text, e.g.$foo($ isn’t in the Ada source character set),
substitutions can only be defined in a separate definitions file (or e.g -Dfoo=bar on the command line).
There is no exact analogue of #define (or any pre-processing) in standard Ada (although you could use a macro preprocessor if you need that), but for this use a renaming declaration should suit:
A : Atype renames package_name.data_memberA;
B : Btype renames package_name.data_memberB;
This has the advantage, over #define, that the tokens A and B are not mistakenly replaced by their #defines in unintended places.

Deep copy of function arguments for polymorphic types

I use an object based on a base package roughly defined as:
package Base is
type T_Base is abstract tagged null record;
-- This performs a deep copy. Shallow copies may lead to STORAGE_ERROR.
-- This shall be implemented by every derived type.
function Copy (From : in T_Base) return T_Base'Class is abstract;
end package Base;
This package is derived by several packages which are further derived
package Foo is
type T_Foo is new T_Base with record
A_Data : Natural; -- Of course, in the real code, these are types by far more complex.
end record;
procedure do_something (Foo_Object : in T_Foo);
-- This implements the deep copy
function Copy (From : in T_Foo) return T_Base'Class is abstract;
end package Foo;
On calling the procedure do_something, I do get a storage_error:
procedure handle_received_foo (Foo_In: in Foo.T_Foo) is
begin
Foo.do_something (Foo_Object => Foo_In); -- The storage error does happen here.
end main;
When running the code with gdb, I get a segfault on entering the function and I get:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 39 (LWP 39)]
0x033c9828 in foo.do_something (foo_object=...) at ./foo.adb:67
67 procedure do_something (Foo_Object : in T_Foo);
(gdb) p foo_object
$1 (null)
So I guess I get a storage_error when doing the shallow copy of the argument Foo_Object.
I am aware that this is no MWE and that there might be a mistake in one of the types present used in the derived types.
I can't find any good option:
Making T_Foo a Controlled type to call Copy in Adjust seems not to be possible without greatly changing its definition as I can't derive T_Foo both from T_Base and Ada.Finalization.Controlled since none of them is an interface types
Defining T_Base as
type T_Base is abstract new Ada.Finalization.Controlled with null record;
and override Adjust here seems to induce a hell lot too much modifications on the existing code base as gnat yields in multiple places
type of aggregate has private ancestor "Controlled" must use extension aggregate.
So I'm low on solutions to either investigate the problem further or to solve it with a hammer.
The problem was not in the Copy function. The comments I saw in the code base were misleading.
The fact that introducing new variables changed the location of the exception made me consider some stack overflow problems.
Indeed the Storage_Size allocated for the task was not sufficient. Increasing the pragma Storage_Size(<value>) solved the problem.
Since the code base is compiled with -fstack-check, this led to the aforementioned STORAGE_ERROR.
More infos on Adacore's documentation.
This could probably have been seen with Gem #95: Dynamic Stack Analysis in GNAT but I am not currently able to see any result with the binding option suggested therein.

Ada Source code modifications using ASIS(Ada Semantics interface specifications)

i am developing a tool for finding sub type range overflow problems in Ada source code.for this purpose i am using ASIS for finding assignment statements in Ada source code and finding type of the variables on the right side of the assignment
expression.now i want to replace the variables(not of record type) of the assignment expression with 'first, 'last values of the variable type in the assignment statement so that i will get compilation error if any range overflow happens.below is an example what i am trying to convey.
procedure Example is
subtype A_Type is integer 1 .. 10;
subtype B_Type is integer -5 .. 5;
subtype C_Type is integer 1 .. 12;
A : A_Type;
B : B_Type;
C : C_Type;
begin
C := A + B;
end Example;
I want modify C := A + B; with C := A_Type'Last + B_Type'Last in the source code. C := A_Type'Last + B_Type'Last assignment statement will get warning at compile time or Constraint error during run time.
Is it possible do above modifications with ASIS?
For your purpose, you shouldn't rewrite the source text you are processing. You should rather write a new program, which only contains exactly the required declarations and assignments.
So the output should be something like:
with Type_Declarations;
procedure Test_Driver is
begin
declare
C : Type_Declarations.C_Type;
begin
C := Type_Declarations."+" (Type_Declarations.A_Type'First, Type_Declarations.B_Type'First);
C := Type_Declarations."+" (Type_Declarations.A_Type'First, Type_Declarations.B_Type'Last);
C := Type_Declarations."+" (Type_Declarations.A_Type'Last, Type_Declarations.B_Type'First);
C := Type_Declarations."+" (Type_Declarations.A_Type'Last, Type_Declarations.B_Type'Last);
end;
end Test_Driver;
ASIS was not designed to make modifications like that. You can, however take a look at libadalang from AdaCore, which supports this (and works on partial sources, so you won't have to precompile your sources)
GNAT includes utilities gnat2xml and xml2gnat; gnat2xml generates a representation of the source based on ASIS, and xml2gnat converts it back to Ada. You could maybe modify the XML output of the first and feed it back to the second.
Not that I’m recommending this; the XML schema isn’t documented, and is complicated.
If you want a tool that can apply modifications to Ada source code, you might be interested in our DMS Software Reengineering Toolkit with its Ada front end.
DMS parses source code to ASTs, and makes those ASTs available for modification using DMS's Abstract Syntax Tree procedural interface (direct hacking at the tree nodes) and/or DMS's rewrite rules (source-to-source transformations "if you see this replace it by that" written in [Ada] language surface syntax, that directly manipulates the trees. After your changes are made, DMS can prettyprint the source to regenerate valid Ada source code, even preserving comments and formatting in those places that have not been modified.

Linking IVF compiled DLL to Qt

This is my first attempt at library assembly, so please have mercy!
I am trying to link an external library (written in .f90 and compiled with IVF on VS2012) to my Qt application (32bit based on Qt 5.5.0- MinGW 4.9.2).
I have a few questions:
1) Is this futile? Some of the research I have found suggests that IVF and MinGW are ABI incompatible. I really want to stay with the MinGW compiler in Qt because basically everything else we are doing with the software uses this.
2) It would be of advantage to be able to load the library only when called upon (which would only represent a fraction of cases). For this reason I have been attempting to use QLibrary but keep getting Segmentation faults when I try to call SUBROUTINES defined in my DLL (with resolve("my_function")):
I have defined my external subroutine as (just a simple test at this stage, not actually important for what I wanted to do!)
Although the actual code I need to access is much more complicated (baby steps!), I wrote a simple subroutine to return the square of an integer:
SUBROUTINE SQ(a,asquare)
!DEC$ ATTRIBUTES C, REFERENCE, MIXED_STR_LEN_ARG, DLLEXPORT, ALIAS:"SQ" :: SQ
integer, intent(in) :: a ! input
integer, intent(out) :: asquare ! output
asquare = a**2
END SUBROUTINE SQ
I import the library and call it within Qt with:
typedef int (*MyPrototype)(int i);
MyPrototype Square = (MyPrototype) FAST.resolve("SQ");
int K = 4;
int J = Square(K);
This results in a segregation error
3) Is there any way to check if the library has, in fact, loaded? Of course calling a subroutine would accomplish this, but that isn't working, and when I import the library DLLname.load() returns a positive result. and resolve.("sub_name") has a memoryaddress allocated to it. Does this suggest a type fault? Ie. passing the wrong identifier in to the fortran code.
Once again, thanks for reading and please feel free to take apart any flaws in logic I have, I'm not a programmer!

Pointer to pointer and NewHandle function in (Think) Pascal

What is a purpose in Pascal to declare variable that is pointer to a pointer? I have a code in Mac Think Pascal. Here is some parts from the code that I don't understand:
type
my_array = array[1..100] of integer;
my_array_pointer = ^my_array;
my_array_handle = ^my_array_pointer;
...
var
xx : my_array_handle;
...
begin
xx:= my_array_handle(NewHandle( sizeof(my_array)) );
As you see, the last line is an assignment of a type my_array_handle to variable xx. What does it mean? What does NewHandle function do? (This is an internal function of Think Pascal). Actually, I need to convert a Think Pascal program to Windows Pascal. However I cannot find the description of NewHandle function, and don't know how to implement this function using the standard (New(), GetMem() etc) pointer functions.
This is a classic macos feature, not typically something of Pascal.
I don't know exactly, but it had something to do with relocatability of the loaded program in a non PM environment.
Note that the indirect pointer is allocated via an OS function, which probably means that it is allocated in some table that is maintained by the OS. (so that the OS can move/relocate the program?)
In modern Mac (and other) programming this whole principle is alien. Just clean it up.
(added)
If you want to keep these redirections, you could try your luck with something like:
function newhandle( nrbytes:integer):ppointer;
var xx : ppointer;
begin
new(xx);
getmem(xx^,nrbytes);
newhandle:=xx;
end;
I didn't add this originally, but I recommend you simply clean up these anachronistic indirect references and use my_array_pointer based pointers and getmem or new directly.
The meaning of these indirect references has no use on non m68k Classic Mac OS systems, though afaik later PPC versions still somewhat support them. (PPC is always protected mode)
If you really want the gritty details, you probably want to subscribe to the mac-pascal list.

Resources