- (1)
- The generic package Interfaces.C.Pointers allows the Ada programmer to perform
C-style operations on pointers. It includes an access type Pointer, Value
functions that dereference a Pointer and deliver the designated array, several
pointer arithmetic operations, and ``copy'' procedures that copy the contents
of a source pointer into the array designated by a destination pointer. As
in C, it treats an object Ptr of type Pointer as a pointer
to the first element of an array, so that for example, adding 1 to Ptr yields
a pointer to the second element of the array.
- (2)
- The generic allows two styles of usage: one in which the array is
terminated by a special terminator element; and another in which the
programmer needs to keep track of the length.
Static Semantics
- (3)
- The generic library package Interfaces.C.Pointers has the following
declaration:
(4)
generic
type Index is (<>);
type Element is private;
type Element_Array is array (Index range <>) of aliased Element;
Default_Terminator : Element;
package Interfaces.C.Pointers is
pragma Preelaborate(Pointers);
(5)
type Pointer is access all Element;
(6)
function Value(Ref : in Pointer;
Terminator : in Element := Default_Terminator)
return Element_Array;
(7)
function Value(Ref : in Pointer;
Length : in ptrdiff_t)
return Element_Array;
(8)
Pointer_Error : exception;
(9)
-- C-style Pointer arithmetic
(10)
function "+" (Left : in Pointer; Right : in ptrdiff_t) return Pointer;
function "+" (Left : in ptrdiff_t; Right : in Pointer) return Pointer;
function "-" (Left : in Pointer; Right : in ptrdiff_t) return Pointer;
function "-" (Left : in Pointer; Right : in Pointer) return ptrdiff_t;
(11)
procedure Increment (Ref : in out Pointer);
procedure Decrement (Ref : in out Pointer);
(12)
pragma Convention (Intrinsic, "+");
pragma Convention (Intrinsic, "-");
pragma Convention (Intrinsic, Increment);
pragma Convention (Intrinsic, Decrement);
(13)
function Virtual_Length (Ref : in Pointer;
Terminator : in Element := Default_Terminator)
return ptrdiff_t;
(14)
procedure Copy_Terminated_Array (Source : in Pointer;
Target : in Pointer;
Limit : in ptrdiff_t := ptrdiff_t'Last;
Terminator : in Element := Default_Terminator);
(15)
procedure Copy_Array (Source : in Pointer;
Target : in Pointer;
Length : in ptrdiff_t);
(16)
end Interfaces.C.Pointers;
- (17)
- The type Pointer is C-compatible and corresponds to one use of C's
``Element *''. An object of type Pointer is interpreted as a pointer to the
initial Element in an Element_Array. Two styles are supported:
- (18)
- Explicit termination of an array value with Default_Terminator (a
special terminator value);
- (19)
- Programmer-managed length, with Default_Terminator treated simply
as a data element.
(20)
function Value(Ref : in Pointer;
Terminator : in Element := Default_Terminator)
return Element_Array;
- (21)
This function returns an Element_Array whose value is the array
pointed to by Ref, up to and including the first Terminator; the
lower bound of the array is Index'First. Interfaces.C.Strings.Dereference_Error is propagated if Ref is null.
(22)
function Value(Ref : in Pointer;
Length : in ptrdiff_t)
return Element_Array;
- (23)
This function returns an Element_Array comprising the first
Length elements pointed to by Ref. The exception Interfaces.C.Strings.Dereference_Error is propagated if Ref is null.
- (24)
- The "+" and "-" functions perform arithmetic on Pointer values, based on
the Size of the array elements. In each of these functions, Pointer_Error is
propagated if a Pointer parameter is null.
(25)
procedure Increment (Ref : in out Pointer);
- (26)
Equivalent to Ref := Ref+1.
(27)
procedure Decrement (Ref : in out Pointer);
- (28)
Equivalent to Ref := Ref-1.
(29)
function Virtual_Length (Ref : in Pointer;
Terminator : in Element := Default_Terminator)
return ptrdiff_t;
- (30)
Returns the number of Elements, up to the one just before the
first Terminator, in Value(Ref, Terminator).
(31)
procedure Copy_Terminated_Array (Source : in Pointer;
Target : in Pointer;
Limit : in ptrdiff_t := ptrdiff_t'Last;
Terminator : in Element := Default_Terminator);
- (32)
This procedure copies Value(Source, Terminator) into the array
pointed to by Target; it stops either after Terminator has been
copied, or the number of elements copied is Limit, whichever occurs
first. Dereference_Error is propagated if either Source or Target is
null.
(33)
procedure Copy_Array (Source : in Pointer;
Target : in Pointer;
Length : in ptrdiff_t);
- (34)
This procedure copies the first Length elements from the array
pointed to by Source, into the array pointed to by Target.
Dereference_Error is propagated if either Source or Target is null.
Erroneous Execution
- (35)
- It is erroneous to dereference a Pointer that does not designate an
aliased Element.
- (36)
- Execution of Value(Ref, Terminator) is erroneous if Ref does not
designate an aliased Element in an Element_Array terminated by Terminator.
- (37)
- Execution of Value(Ref, Length) is erroneous if Ref does not designate
an aliased Element in an Element_Array containing at least Length Elements
between the designated Element and the end of the array, inclusive.
- (38)
- Execution of Virtual_Length(Ref, Terminator) is erroneous if Ref does
not designate an aliased Element in an Element_Array terminated by
Terminator.
- (39)
- Execution of Copy_Terminated_Array(Source, Target, Limit, Terminator) is
erroneous in either of the following situations:
- (40)
- Execution of both Value(Source,Terminator) and
Value(Source,Limit) are erroneous, or
- (41)
- Copying writes past the end of the array containing the Element
designated by Target.
- (42)
- Execution of Copy_Array(Source, Target, Length) is erroneous if either
Value(Source, Length) is erroneous, or copying writes past the end of the
array containing the Element designated by Target.
-
- (43)
(14) To compose a Pointer from an Element_Array, use 'Access on the
first element. For example (assuming appropriate instantiations):
(44)
Some_Array : Element_Array(0..5) ;
Some_Pointer : Pointer := Some_Array(0)'Access;
Examples
- (45)
- Example of Interfaces.C.Pointers:
(46)
with Interfaces.C.Pointers;
with Interfaces.C.Strings;
procedure Test_Pointers is
package C renames Interfaces.C;
package Char_Ptrs is
new C.Pointers (Index => C.size_t,
Element => C.char,
Element_Array => C.char_array,
Default_Terminator => C.nul);
(47)
use type Char_Ptrs.Pointer;
subtype Char_Star is Char_Ptrs.Pointer;
(48)
procedure Strcpy (Target_Ptr, Source_Ptr : Char_Star) is
Target_Temp_Ptr : Char_Star := Target_Ptr;
Source_Temp_Ptr : Char_Star := Source_Ptr;
Element : C.char;
begin
if Target_Temp_Ptr = null or Source_Temp_Ptr = null then
raise C.Strings.Dereference_Error;
end if;
(49)
loop
Element := Source_Temp_Ptr.all;
Target_Temp_Ptr.all := Element;
exit when Element = C.nul;
Char_Ptrs.Increment(Target_Temp_Ptr);
Char_Ptrs.Increment(Source_Temp_Ptr);
end loop;
end Strcpy;
begin
...
end Test_Pointers;
-- Email comments, additions, corrections, gripes, kudos, etc. to:
Magnus Kempe -- Magnus.Kempe@di.epfl.ch
Copyright statement
Page last generated: 95-03-12