address representation in ada - ada

I have pasted a code below which is in Ada language.I need some clarification on some implementations.
C : character;
Char : character;
type Myarr_Type is array (character range 'A'..'K') of character;
Myarr : Myarr_Type := ('A','B','C','D','E','F','G','H','I','J','K');
Next_Address := Myarr'address --'
Last_Address := Next_Address + Storage_Offset'(40); --'
return P2 + Storage_Offset'(4); --'
Last_Address := Next_Address + Storage_Offset'(4); --'
Now my doubt is 1) what does P2 + Storage_Offset'(4) actually mean.Does that mean that its returning the address of the next element in the array which is 'B'.Storage_Offset'(4) in Ada --does this mean 4 bits or 4 bytes of memory. 2) If i assume that Last_Address points to last element of the array which is 'K', how does the arithmentic Storage_Offset'(40) satisfies the actual implementation?
Please get back to me if u need any more clarifications.
Please assume that the function does not exist.
As a matter of fact,i have some ada file and my job is to convert them to C files.Since i am a beginner in ada,i faced a lot of issues with that.Please pardon in case of any confusion
Thanks
Maddy

Storage_Offset is a special integeral type in package System.Storage_Elements that can be added to objects of type System.Address. What exactly the units of Address and Storage_Offset are is implementation defined, but probably just about every implementation in existence uses bytes. So Next_Address + Storage_Offset'(4) means "the address four bytes past whatever Next_Address refers to."
You talked a bit about Ada porting. In 99% of cases, that is a very stupid idea (the %1 being when you need to port to a platform that has no Ada compiler). I'd say the same thing no matter what language you are porting. It's a fool's game. The best outcome you can hope for when porting code is that after a ton of effort it works as well as it did before. With coding the best case never happens.
Ada can interface to C just fine, so it would be far smarter to keep unchanged code in Ada and only "port" stuff you need to change.
If you come across any tasking code, protected types, or custom streams you will be in a world of hurt. Those things don't really have easy C analogs.
If your bosses really have a boner for C or something, I'd suggest looking into Sofcheck's AdaMagic, which provides a service to transform Ada code to ANSI C. Back in the day (two owners prior) they used to claim that it produced maintainable C code. Either way, it will probably be far cheaper than having an inexperienced (in Ada) developer try to do it all by hand.

my_func(int P1,int P2)
{
return P2 + Storage_Offset'(4);
}
Well, this is a C function whose body is written in Ada. There is no "+" operator taking an Integer and a Storage_Offset; perhaps you're looking for
function "+"(Left : Address; Right : Storage_Offset)
return Address;
and perhaps you meant to call my_func(something, Next_Address)?
In that case, the expression will return the address of whatever is 4 Storage_Elements, ie bytes, after Myarr('A').
Myarr_Type is an array of Character, which with any normal compiler on any common architecture is going to be a standard 8-bit byte. So Myarr_Type objects will be 11 bytes long, not 44, and Myarr('A')'Address + 4 will be the address of Myarr('E').
If you want the address of the last element of Myarr, try
Myarr (Myarr'Last)'Address

Related

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.

Ada83 Unchecked Conversion of Record in Declaration

I want to declare a constant as a 16 bit integer of type Word and assign a value to it. To support portability between Big and Little Endian platforms, I can't safely use an assignment like this one:
Special_Value : Constant Word := 16#1234#;
because the byte order might be misinterpreted.
So I use a record like this:
Type Double_Byte Is Record
Byte_1 : Byte; -- most significant byte
Byte_0 : Byte; -- least significant byte
End Record;
For Double_Byte Use Record
Byte_1 At 0 Range 0..7;
Byte_0 At 0 Range 8..15;
End Record;
However, in some cases, I have a large number of pre-configuration assignments that look like this:
Value_1 : Constant Word := 15#1234#;
This is very readable by a person, but endian issues cause it to be misunderstood a number of ways (including in the debugger, for example).
Because I have many lines where I do this, I tried the following because it is fairly compact as source code. It is working, but I'm not sure why, or what part of the Ada Reference Manual covers this concept:
Value_1 : Constant Word := DByte_To_Word((Byte_1 => 16#12#,
Byte_0 => 16#34#));
where DByte_To_Word is defined as
Function DByte_To_Word Is New Unchecked_Conversion(Double_Byte, Word);
I think I have seen something in the ARM that allows me to do this, but not the way I described above. I can't find it and I don't know what I would be searching for.
There’s nothing unusual about your call to DByte_To_Word; (Byte_1 => 16#12#, Byte_0 => 16#34#) is a perfectly legitimate record aggregate of type Double_Byte, see LRM83 4.3.1.
But! But! it’s true that, on a big-endian machine, the first (lowest-addressed) byte of your Word will contain 16#12#, whereas on a little-endian machine it will contain 16#34#. The CPU takes care of all of that; if you print the value of Special_Value you will get 16#1234# (or 0x1234) no matter which endianness the computer implements.
The only time you’ll encounter endianness issues is when you’re copying binary data from one endianness to another, via the network, or a file.
If your debugger gets confused about this, you need a better debugger!

I don't understand the result of this little program

i've made this little program to test a little part of a bigger program.
int main()
{
char c[]="ddddddddddddd";
char *g= malloc(4*sizeof(char));
*g=NULL;
strcpy (g,c);
printf("Hello world %s!\n",g);
return 0;
}
I expected that the function would return "Hello World dddd" ,since the length of g is 4*sizeof(char), but it returns " Hello World ddddddddddddd ".Can you explain me Where I'm wrong ?
Don't do that, it's undefined behaviour.
The strcpy function will happily copy all those characters in c regardless of the size of g.
That's because it copies characters up to the first \0 in c. In this particular case it may corrupt your heap, or it may not, depending on the minimum size of things that get allocated in the heap (many have a "resolution" of sixteen bytes for example).
There are other functions you can use (though they're optional) if you want your code to be more robust, such as strncpy (provided you understand the limitations), or strcpy_s(), as detailed in Appendix K of the ISO C11 standard (and earlier iterations as well).
Or, if you can't use those for some reason, it's up to the developer to ensure they don't break the rules.

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.

Global variable touched by a passed-in parameter becomes unusable

folks!
I pass a struct full of data to my kernel, and I run into the following difficulty using it (very stripped down):
[edit: mac osx / xcode 3.2 on mac book pro; this compile is obviously for cpu]
typedef struct
{
float xoom;
int sizex;
} varholder;
float zX, xd;
__kernel void Harlan( __global varholder * vh )
{
int X = get_global_id(0), Y = get_global_id(1);
zX = ( ( X - vh->sizex/2 ) / vh->xoom + vh->sizex/2 ); // (a)
xd = zX; // (b) BOOM!!
}
after executing line (a), the line marked (b), a simple assignment, gives "LLVM compiler failed to compile a function".
if, however, we do not execute line (a), then line (b) is fine.
So, through my fiddling around a LOT with this, it seems as if it is the assignment statement (a), which uses a passed-in parameter, that messes up the future access of the variable zX. However, of course I need to be able to use the results of calculations further down the line.
I have zX and xd declared at the file level because my helper functions need them.
Any thoughts?
Thanks!
David
p.s. I'm now registered so will be able to upvote and accept answers, which I am sadly unable to do for the last person who helped me (used same username to register, but can't seem to vote on the old post; sorry!).
No, say it ain't so!
I am sincerely hoping that this is not a "correct" answer to my own question. I found on another forum (though not the same question asked!) the following, and I am afraid that it refers to what I'm trying to do:
(quote)
You're doing something the standard prohibits. Section 6.5 says:
'All program scope variables must be declared in the __constant address space.'
In other words, program scope variables cannot be mutable.
(end quote)
... well, tcha!!!! What an astoundingly inconvenient restriction! I'm sure there's reasoning behind it.
[edit: Not At All inconvenient! it was in fact astonishingly easy to work around, given a fresh start the next morning. (And no alcohol.)]
You guys & dolls all knew this, right, and didn't have the heart to tell me?...

Resources