blob: 2023b753dfd6a6b9d091c5e151f109cf98018e91 [file] [log] [blame]
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- I N T E R F A C E S . C --
-- --
-- S p e c --
-- --
-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. In accordance with the copyright of that document, you can freely --
-- copy and modify this specification, provided that if you redistribute a --
-- modified version, any changes that you have made are clearly indicated. --
-- --
------------------------------------------------------------------------------
-- Preconditions in this unit are meant for analysis only, not for run-time
-- checking, so that the expected exceptions are raised. This is enforced by
-- setting the corresponding assertion policy to Ignore. Postconditions and
-- contract cases should not be executed at runtime as well, in order not to
-- slow down the execution of these functions.
pragma Assertion_Policy (Pre => Ignore,
Post => Ignore,
Contract_Cases => Ignore,
Ghost => Ignore);
with System.Parameters;
package Interfaces.C
with SPARK_Mode, Pure
is
-- Each of the types declared in Interfaces.C is C-compatible.
-- The types int, short, long, unsigned, ptrdiff_t, size_t, double,
-- char, wchar_t, char16_t, and char32_t correspond respectively to the
-- C types having the same names. The types signed_char, unsigned_short,
-- unsigned_long, unsigned_char, C_bool, C_float, and long_double
-- correspond respectively to the C types signed char, unsigned
-- short, unsigned long, unsigned char, bool, float, and long double.
-- Declaration's based on C's <limits.h>
CHAR_BIT : constant := 8;
SCHAR_MIN : constant := -128;
SCHAR_MAX : constant := 127;
UCHAR_MAX : constant := 255;
-- Signed and Unsigned Integers. Note that in GNAT, we have ensured that
-- the standard predefined Ada types correspond to the standard C types
-- Note: the Integer qualifications used in the declaration of type long
-- avoid ambiguities when compiling in the presence of s-auxdec.ads and
-- a non-private system.address type.
type int is new Integer;
type short is new Short_Integer;
type long is range -(2 ** (System.Parameters.long_bits - Integer'(1)))
.. +(2 ** (System.Parameters.long_bits - Integer'(1))) - 1;
type long_long is new Long_Long_Integer;
type signed_char is range SCHAR_MIN .. SCHAR_MAX;
for signed_char'Size use CHAR_BIT;
type unsigned is mod 2 ** int'Size;
type unsigned_short is mod 2 ** short'Size;
type unsigned_long is mod 2 ** long'Size;
type unsigned_long_long is mod 2 ** long_long'Size;
type unsigned_char is mod (UCHAR_MAX + 1);
for unsigned_char'Size use CHAR_BIT;
-- Note: Ada RM states that the type of the subtype plain_char is either
-- signed_char or unsigned_char, depending on the C implementation. GNAT
-- instead choses unsigned_char always.
subtype plain_char is unsigned_char;
-- Note: the Integer qualifications used in the declaration of ptrdiff_t
-- avoid ambiguities when compiling in the presence of s-auxdec.ads and
-- a non-private system.address type.
type ptrdiff_t is
range -(2 ** (System.Parameters.ptr_bits - Integer'(1))) ..
+(2 ** (System.Parameters.ptr_bits - Integer'(1)) - 1);
type size_t is mod 2 ** System.Parameters.ptr_bits;
-- Boolean type
type C_bool is new Boolean;
pragma Convention (C, C_bool);
-- Floating-Point
type C_float is new Float;
type double is new Standard.Long_Float;
type long_double is new Standard.Long_Long_Float;
----------------------------
-- Characters and Strings --
----------------------------
type char is new Character;
nul : constant char := char'First;
-- The functions To_C and To_Ada map between the Ada type Character and the
-- C type char.
function To_C (Item : Character) return char
with
Post => To_C'Result = char'Val (Character'Pos (Item));
function To_Ada (Item : char) return Character
with
Post => To_Ada'Result = Character'Val (char'Pos (Item));
type char_array is array (size_t range <>) of aliased char;
for char_array'Component_Size use CHAR_BIT;
function Is_Nul_Terminated (Item : char_array) return Boolean
with
Post => Is_Nul_Terminated'Result = (for some C of Item => C = nul);
-- The result of Is_Nul_Terminated is True if Item contains nul, and is
-- False otherwise.
function C_Length_Ghost (Item : char_array) return size_t
with
Ghost,
Pre => Is_Nul_Terminated (Item),
Post => C_Length_Ghost'Result <= Item'Last - Item'First
and then Item (Item'First + C_Length_Ghost'Result) = nul
and then (for all J in Item'First .. Item'First + C_Length_Ghost'Result
when J /= Item'First + C_Length_Ghost'Result =>
Item (J) /= nul);
-- Ghost function to compute the length of a char_array up to the first nul
-- character.
function To_C
(Item : String;
Append_Nul : Boolean := True) return char_array
with
Pre => not (Append_Nul = False and then Item'Length = 0),
Post => To_C'Result'First = 0
and then To_C'Result'Length =
(if Append_Nul then Item'Length + 1 else Item'Length)
and then (for all J in Item'Range =>
To_C'Result (size_t (J - Item'First)) = To_C (Item (J)))
and then (if Append_Nul then To_C'Result (To_C'Result'Last) = nul);
-- The result of To_C is a char_array value of length Item'Length (if
-- Append_Nul is False) or Item'Length+1 (if Append_Nul is True). The lower
-- bound is 0. For each component Item(I), the corresponding component
-- in the result is To_C applied to Item(I). The value nul is appended if
-- Append_Nul is True. If Append_Nul is False and Item'Length is 0, then
-- To_C propagates Constraint_Error.
function To_Ada
(Item : char_array;
Trim_Nul : Boolean := True) return String
with
Pre => (if Trim_Nul then
Is_Nul_Terminated (Item)
and then C_Length_Ghost (Item) <= size_t (Natural'Last)
else
Item'Last - Item'First < size_t (Natural'Last)),
Post => To_Ada'Result'First = 1
and then To_Ada'Result'Length =
(if Trim_Nul then C_Length_Ghost (Item) else Item'Length)
and then (for all J in To_Ada'Result'Range =>
To_Ada'Result (J) =
To_Ada (Item (size_t (J) - 1 + Item'First)));
-- The result of To_Ada is a String whose length is Item'Length (if
-- Trim_Nul is False) or the length of the slice of Item preceding the
-- first nul (if Trim_Nul is True). The lower bound of the result is 1.
-- If Trim_Nul is False, then for each component Item(I) the corresponding
-- component in the result is To_Ada applied to Item(I). If Trim_Nul
-- is True, then for each component Item(I) before the first nul the
-- corresponding component in the result is To_Ada applied to Item(I). The
-- function propagates Terminator_Error if Trim_Nul is True and Item does
-- not contain nul.
procedure To_C
(Item : String;
Target : out char_array;
Count : out size_t;
Append_Nul : Boolean := True)
with
Relaxed_Initialization => Target,
Pre => Target'Length >=
(if Append_Nul then Item'Length + 1 else Item'Length),
Post => Count = (if Append_Nul then Item'Length + 1 else Item'Length)
and then
(if Count /= 0 then
Target (Target'First .. Target'First + (Count - 1))'Initialized)
and then
(for all J in Item'Range =>
Target (Target'First + size_t (J - Item'First)) = To_C (Item (J)))
and then
(if Append_Nul then Target (Target'First + (Count - 1)) = nul);
-- For procedure To_C, each element of Item is converted (via the To_C
-- function) to a char, which is assigned to the corresponding element of
-- Target. If Append_Nul is True, nul is then assigned to the next element
-- of Target. In either case, Count is set to the number of Target elements
-- assigned. If Target is not long enough, Constraint_Error is propagated.
procedure To_Ada
(Item : char_array;
Target : out String;
Count : out Natural;
Trim_Nul : Boolean := True)
with
Relaxed_Initialization => Target,
Pre => (if Trim_Nul then
Is_Nul_Terminated (Item)
and then C_Length_Ghost (Item) <= size_t (Target'Length)
else
Item'Last - Item'First < size_t (Target'Length)),
Post => Count =
(if Trim_Nul then Natural (C_Length_Ghost (Item)) else Item'Length)
and then
(if Count /= 0 then
Target (Target'First .. Target'First + (Count - 1))'Initialized)
and then
(for all J in Target'First .. Target'First + (Count - 1) =>
Target (J) =
To_Ada (Item (size_t (J - Target'First) + Item'First)));
-- For procedure To_Ada, each element of Item (if Trim_Nul is False) or
-- each element of Item preceding the first nul (if Trim_Nul is True) is
-- converted (via the To_Ada function) to a Character, which is assigned
-- to the corresponding element of Target. Count is set to the number of
-- Target elements assigned. If Target is not long enough, Constraint_Error
-- is propagated. If Trim_Nul is True and Item does not contain nul, then
-- Terminator_Error is propagated.
------------------------------------
-- Wide Character and Wide String --
------------------------------------
type wchar_t is new Wide_Character;
for wchar_t'Size use Standard'Wchar_T_Size;
wide_nul : constant wchar_t := wchar_t'First;
-- To_C and To_Ada provide the mappings between the Ada and C wide
-- character types.
function To_C (Item : Wide_Character) return wchar_t
with
Post => To_C'Result = wchar_t (Item);
function To_Ada (Item : wchar_t) return Wide_Character
with
Post => To_Ada'Result = Wide_Character (Item);
type wchar_array is array (size_t range <>) of aliased wchar_t;
function Is_Nul_Terminated (Item : wchar_array) return Boolean
with
Post => Is_Nul_Terminated'Result = (for some C of Item => C = wide_nul);
-- The result of Is_Nul_Terminated is True if Item contains wide_nul, and
-- is False otherwise.
-- The To_C and To_Ada subprograms that convert between Wide_String and
-- wchar_array have analogous effects to the To_C and To_Ada subprograms
-- that convert between String and char_array, except that wide_nul is
-- used instead of nul.
function C_Length_Ghost (Item : wchar_array) return size_t
with
Ghost,
Pre => Is_Nul_Terminated (Item),
Post => C_Length_Ghost'Result <= Item'Last - Item'First
and then Item (Item'First + C_Length_Ghost'Result) = wide_nul
and then (for all J in Item'First .. Item'First + C_Length_Ghost'Result
when J /= Item'First + C_Length_Ghost'Result =>
Item (J) /= wide_nul);
-- Ghost function to compute the length of a wchar_array up to the first
-- wide_nul character.
function To_C
(Item : Wide_String;
Append_Nul : Boolean := True) return wchar_array
with
Pre => not (Append_Nul = False and then Item'Length = 0),
Post => To_C'Result'First = 0
and then To_C'Result'Length =
(if Append_Nul then Item'Length + 1 else Item'Length)
and then (for all J in Item'Range =>
To_C'Result (size_t (J - Item'First)) = To_C (Item (J)))
and then (if Append_Nul then To_C'Result (To_C'Result'Last) = wide_nul);
function To_Ada
(Item : wchar_array;
Trim_Nul : Boolean := True) return Wide_String
with
Pre => (if Trim_Nul then
Is_Nul_Terminated (Item)
and then C_Length_Ghost (Item) <= size_t (Natural'Last)
else
Item'Last - Item'First < size_t (Natural'Last)),
Post => To_Ada'Result'First = 1
and then To_Ada'Result'Length =
(if Trim_Nul then C_Length_Ghost (Item) else Item'Length)
and then (for all J in To_Ada'Result'Range =>
To_Ada'Result (J) =
To_Ada (Item (size_t (J) - 1 + Item'First)));
procedure To_C
(Item : Wide_String;
Target : out wchar_array;
Count : out size_t;
Append_Nul : Boolean := True)
with
Relaxed_Initialization => Target,
Pre => Target'Length >=
(if Append_Nul then Item'Length + 1 else Item'Length),
Post => Count = (if Append_Nul then Item'Length + 1 else Item'Length)
and then
(if Count /= 0 then
Target (Target'First .. Target'First + (Count - 1))'Initialized)
and then
(for all J in Item'Range =>
Target (Target'First + size_t (J - Item'First)) = To_C (Item (J)))
and then
(if Append_Nul then Target (Target'First + (Count - 1)) = wide_nul);
procedure To_Ada
(Item : wchar_array;
Target : out Wide_String;
Count : out Natural;
Trim_Nul : Boolean := True)
with
Relaxed_Initialization => Target,
Pre => (if Trim_Nul then
Is_Nul_Terminated (Item)
and then C_Length_Ghost (Item) <= size_t (Target'Length)
else
Item'Last - Item'First < size_t (Target'Length)),
Post => Count =
(if Trim_Nul then Natural (C_Length_Ghost (Item)) else Item'Length)
and then
(if Count /= 0 then
Target (Target'First .. Target'First + (Count - 1))'Initialized)
and then
(for all J in Target'First .. Target'First + (Count - 1) =>
Target (J) =
To_Ada (Item (size_t (J - Target'First) + Item'First)));
Terminator_Error : exception;
-- The remaining declarations are for Ada 2005 (AI-285)
-- ISO/IEC 10646:2003 compatible types defined by SC22/WG14 document N1010
type char16_t is new Wide_Character;
pragma Ada_05 (char16_t);
char16_nul : constant char16_t := char16_t'Val (0);
pragma Ada_05 (char16_nul);
-- To_C and To_Ada provide mappings between the Ada and C 16-bit character
-- types.
function To_C (Item : Wide_Character) return char16_t
with
Post => To_C'Result = char16_t (Item);
pragma Ada_05 (To_C);
function To_Ada (Item : char16_t) return Wide_Character
with
Post => To_Ada'Result = Wide_Character (Item);
pragma Ada_05 (To_Ada);
type char16_array is array (size_t range <>) of aliased char16_t;
pragma Ada_05 (char16_array);
function Is_Nul_Terminated (Item : char16_array) return Boolean
with
Post => Is_Nul_Terminated'Result = (for some C of Item => C = char16_nul);
pragma Ada_05 (Is_Nul_Terminated);
-- The result of Is_Nul_Terminated is True if Item contains char16_nul, and
-- is False otherwise.
-- The To_C and To_Ada subprograms that convert between Wide_String and
-- char16_array have analogous effects to the To_C and To_Ada subprograms
-- that convert between String and char_array, except that char16_nul is
-- used instead of nul.
function C_Length_Ghost (Item : char16_array) return size_t
with
Ghost,
Pre => Is_Nul_Terminated (Item),
Post => C_Length_Ghost'Result <= Item'Last - Item'First
and then Item (Item'First + C_Length_Ghost'Result) = char16_nul
and then (for all J in Item'First .. Item'First + C_Length_Ghost'Result
when J /= Item'First + C_Length_Ghost'Result =>
Item (J) /= char16_nul);
-- Ghost function to compute the length of a char16_array up to the first
-- char16_nul character.
function To_C
(Item : Wide_String;
Append_Nul : Boolean := True) return char16_array
with
Pre => not (Append_Nul = False and then Item'Length = 0),
Post => To_C'Result'First = 0
and then To_C'Result'Length =
(if Append_Nul then Item'Length + 1 else Item'Length)
and then (for all J in Item'Range =>
To_C'Result (size_t (J - Item'First)) = To_C (Item (J)))
and then
(if Append_Nul then To_C'Result (To_C'Result'Last) = char16_nul);
pragma Ada_05 (To_C);
function To_Ada
(Item : char16_array;
Trim_Nul : Boolean := True) return Wide_String
with
Pre => (if Trim_Nul then
Is_Nul_Terminated (Item)
and then C_Length_Ghost (Item) <= size_t (Natural'Last)
else
Item'Last - Item'First < size_t (Natural'Last)),
Post => To_Ada'Result'First = 1
and then To_Ada'Result'Length =
(if Trim_Nul then C_Length_Ghost (Item) else Item'Length)
and then (for all J in To_Ada'Result'Range =>
To_Ada'Result (J) =
To_Ada (Item (size_t (J) - 1 + Item'First)));
pragma Ada_05 (To_Ada);
procedure To_C
(Item : Wide_String;
Target : out char16_array;
Count : out size_t;
Append_Nul : Boolean := True)
with
Relaxed_Initialization => Target,
Pre => Target'Length >=
(if Append_Nul then Item'Length + 1 else Item'Length),
Post => Count = (if Append_Nul then Item'Length + 1 else Item'Length)
and then
(if Count /= 0 then
Target (Target'First .. Target'First + (Count - 1))'Initialized)
and then
(for all J in Item'Range =>
Target (Target'First + size_t (J - Item'First)) = To_C (Item (J)))
and then
(if Append_Nul then Target (Target'First + (Count - 1)) = char16_nul);
pragma Ada_05 (To_C);
procedure To_Ada
(Item : char16_array;
Target : out Wide_String;
Count : out Natural;
Trim_Nul : Boolean := True)
with
Relaxed_Initialization => Target,
Pre => (if Trim_Nul then
Is_Nul_Terminated (Item)
and then C_Length_Ghost (Item) <= size_t (Target'Length)
else
Item'Last - Item'First < size_t (Target'Length)),
Post => Count =
(if Trim_Nul then Natural (C_Length_Ghost (Item)) else Item'Length)
and then
(if Count /= 0 then
Target (Target'First .. Target'First + (Count - 1))'Initialized)
and then
(for all J in Target'First .. Target'First + (Count - 1) =>
Target (J) =
To_Ada (Item (size_t (J - Target'First) + Item'First)));
pragma Ada_05 (To_Ada);
type char32_t is new Wide_Wide_Character;
pragma Ada_05 (char32_t);
char32_nul : constant char32_t := char32_t'Val (0);
pragma Ada_05 (char32_nul);
-- To_C and To_Ada provide mappings between the Ada and C 32-bit character
-- types.
function To_C (Item : Wide_Wide_Character) return char32_t
with
Post => To_C'Result = char32_t (Item);
pragma Ada_05 (To_C);
function To_Ada (Item : char32_t) return Wide_Wide_Character
with
Post => To_Ada'Result = Wide_Wide_Character (Item);
pragma Ada_05 (To_Ada);
type char32_array is array (size_t range <>) of aliased char32_t;
pragma Ada_05 (char32_array);
function Is_Nul_Terminated (Item : char32_array) return Boolean
with
Post => Is_Nul_Terminated'Result = (for some C of Item => C = char32_nul);
pragma Ada_05 (Is_Nul_Terminated);
-- The result of Is_Nul_Terminated is True if Item contains char32_nul, and
-- is False otherwise.
function C_Length_Ghost (Item : char32_array) return size_t
with
Ghost,
Pre => Is_Nul_Terminated (Item),
Post => C_Length_Ghost'Result <= Item'Last - Item'First
and then Item (Item'First + C_Length_Ghost'Result) = char32_nul
and then (for all J in Item'First .. Item'First + C_Length_Ghost'Result
when J /= Item'First + C_Length_Ghost'Result =>
Item (J) /= char32_nul);
-- Ghost function to compute the length of a char32_array up to the first
-- char32_nul character.
-- The To_C and To_Ada subprograms that convert between Wide_Wide_String
-- and char32_array have analogous effects to the To_C and To_Ada
-- subprograms that convert between String and char_array, except
-- that char32_nul is used instead of nul.
function To_C
(Item : Wide_Wide_String;
Append_Nul : Boolean := True) return char32_array
with
Pre => not (Append_Nul = False and then Item'Length = 0),
Post => To_C'Result'First = 0
and then To_C'Result'Length =
(if Append_Nul then Item'Length + 1 else Item'Length)
and then (for all J in Item'Range =>
To_C'Result (size_t (J - Item'First)) = To_C (Item (J)))
and then
(if Append_Nul then To_C'Result (To_C'Result'Last) = char32_nul);
pragma Ada_05 (To_C);
function To_Ada
(Item : char32_array;
Trim_Nul : Boolean := True) return Wide_Wide_String
with
Pre => (if Trim_Nul then
Is_Nul_Terminated (Item)
and then C_Length_Ghost (Item) <= size_t (Natural'Last)
else
Item'Last - Item'First < size_t (Natural'Last)),
Post => To_Ada'Result'First = 1
and then To_Ada'Result'Length =
(if Trim_Nul then C_Length_Ghost (Item) else Item'Length)
and then (for all J in To_Ada'Result'Range =>
To_Ada'Result (J) =
To_Ada (Item (size_t (J) - 1 + Item'First)));
pragma Ada_05 (To_Ada);
procedure To_C
(Item : Wide_Wide_String;
Target : out char32_array;
Count : out size_t;
Append_Nul : Boolean := True)
with
Relaxed_Initialization => Target,
Pre => Target'Length >=
(if Append_Nul then Item'Length + 1 else Item'Length),
Post => Count = (if Append_Nul then Item'Length + 1 else Item'Length)
and then
(if Count /= 0 then
Target (Target'First .. Target'First + (Count - 1))'Initialized)
and then
(for all J in Item'Range =>
Target (Target'First + size_t (J - Item'First)) = To_C (Item (J)))
and then
(if Append_Nul then Target (Target'First + (Count - 1)) = char32_nul);
pragma Ada_05 (To_C);
procedure To_Ada
(Item : char32_array;
Target : out Wide_Wide_String;
Count : out Natural;
Trim_Nul : Boolean := True)
with
Relaxed_Initialization => Target,
Pre => (if Trim_Nul then
Is_Nul_Terminated (Item)
and then C_Length_Ghost (Item) <= size_t (Target'Length)
else
Item'Last - Item'First < size_t (Target'Length)),
Post => Count =
(if Trim_Nul then Natural (C_Length_Ghost (Item)) else Item'Length)
and then
(if Count /= 0 then
Target (Target'First .. Target'First + (Count - 1))'Initialized)
and then
(for all J in Target'First .. Target'First + (Count - 1) =>
Target (J) =
To_Ada (Item (size_t (J - Target'First) + Item'First)));
pragma Ada_05 (To_Ada);
end Interfaces.C;