OSDN Git Service

PR bootstrap/11932
[pf3gnuchains/gcc-fork.git] / gcc / ada / i-cpoint.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                I N T E R F A C E S . C . P O I N T E R S                 --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
10 --                                                                          --
11 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
12 -- terms of the  GNU General Public License as published  by the Free Soft- --
13 -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
14 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
17 -- for  more details.  You should have  received  a copy of the GNU General --
18 -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
19 -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
20 -- MA 02111-1307, USA.                                                      --
21 --                                                                          --
22 -- As a special exception,  if other files  instantiate  generics from this --
23 -- unit, or you link  this unit with other files  to produce an executable, --
24 -- this  unit  does not  by itself cause  the resulting  executable  to  be --
25 -- covered  by the  GNU  General  Public  License.  This exception does not --
26 -- however invalidate  any other reasons why  the executable file  might be --
27 -- covered by the  GNU Public License.                                      --
28 --                                                                          --
29 -- GNAT was originally developed  by the GNAT team at  New York University. --
30 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
31 --                                                                          --
32 ------------------------------------------------------------------------------
33
34 with Interfaces.C.Strings; use Interfaces.C.Strings;
35 with System;               use System;
36
37 with Unchecked_Conversion;
38
39 package body Interfaces.C.Pointers is
40
41    type Addr is mod Memory_Size;
42
43    function To_Pointer is new Unchecked_Conversion (Addr,      Pointer);
44    function To_Addr    is new Unchecked_Conversion (Pointer,   Addr);
45    function To_Addr    is new Unchecked_Conversion (ptrdiff_t, Addr);
46    function To_Ptrdiff is new Unchecked_Conversion (Addr,      ptrdiff_t);
47
48    Elmt_Size : constant ptrdiff_t :=
49                  (Element_Array'Component_Size
50                    + Storage_Unit - 1) / Storage_Unit;
51
52    subtype Index_Base is Index'Base;
53
54    ---------
55    -- "+" --
56    ---------
57
58    function "+" (Left : in Pointer;   Right : in ptrdiff_t) return Pointer is
59    begin
60       if Left = null then
61          raise Pointer_Error;
62       end if;
63
64       return To_Pointer (To_Addr (Left) + To_Addr (Elmt_Size * Right));
65    end "+";
66
67    function "+" (Left : in ptrdiff_t; Right : in Pointer) return Pointer is
68    begin
69       if Right = null then
70          raise Pointer_Error;
71       end if;
72
73       return To_Pointer (To_Addr (Elmt_Size * Left) + To_Addr (Right));
74    end "+";
75
76    ---------
77    -- "-" --
78    ---------
79
80    function "-" (Left : in Pointer; Right : in ptrdiff_t) return Pointer is
81    begin
82       if Left = null then
83          raise Pointer_Error;
84       end if;
85
86       return To_Pointer (To_Addr (Left) - To_Addr (Right * Elmt_Size));
87    end "-";
88
89    function "-" (Left : in Pointer; Right : in Pointer) return ptrdiff_t is
90    begin
91       if Left = null or else Right = null then
92          raise Pointer_Error;
93       end if;
94
95       return To_Ptrdiff (To_Addr (Left) - To_Addr (Right)) / Elmt_Size;
96    end "-";
97
98    ----------------
99    -- Copy_Array --
100    ----------------
101
102    procedure Copy_Array
103      (Source  : in Pointer;
104       Target  : in Pointer;
105       Length  : in ptrdiff_t)
106    is
107       T : Pointer := Target;
108       S : Pointer := Source;
109
110    begin
111       if S = null or else T = null then
112          raise Dereference_Error;
113
114       else
115          for J in 1 .. Length loop
116             T.all := S.all;
117             Increment (T);
118             Increment (S);
119          end loop;
120       end if;
121    end Copy_Array;
122
123    ---------------------------
124    -- Copy_Terminated_Array --
125    ---------------------------
126
127    procedure Copy_Terminated_Array
128      (Source     : in Pointer;
129       Target     : in Pointer;
130       Limit      : in ptrdiff_t := ptrdiff_t'Last;
131       Terminator : in Element := Default_Terminator)
132    is
133       S : Pointer   := Source;
134       T : Pointer   := Target;
135       L : ptrdiff_t := Limit;
136
137    begin
138       if S = null or else T = null then
139          raise Dereference_Error;
140
141       else
142          while L > 0 loop
143             T.all := S.all;
144             exit when T.all = Terminator;
145             Increment (T);
146             Increment (S);
147             L := L - 1;
148          end loop;
149       end if;
150    end Copy_Terminated_Array;
151
152    ---------------
153    -- Decrement --
154    ---------------
155
156    procedure Decrement (Ref : in out Pointer) is
157    begin
158       Ref := Ref - 1;
159    end Decrement;
160
161    ---------------
162    -- Increment --
163    ---------------
164
165    procedure Increment (Ref : in out Pointer) is
166    begin
167       Ref := Ref + 1;
168    end Increment;
169
170    -----------
171    -- Value --
172    -----------
173
174    function Value
175      (Ref        : in Pointer;
176       Terminator : in Element := Default_Terminator)
177       return       Element_Array
178    is
179       P : Pointer;
180       L : constant Index_Base := Index'First;
181       H : Index_Base;
182
183    begin
184       if Ref = null then
185          raise Dereference_Error;
186
187       else
188          H := L;
189          P := Ref;
190
191          loop
192             exit when P.all = Terminator;
193             H := Index_Base'Succ (H);
194             Increment (P);
195          end loop;
196
197          declare
198             subtype A is Element_Array (L .. H);
199
200             type PA is access A;
201             function To_PA is new Unchecked_Conversion (Pointer, PA);
202
203          begin
204             return To_PA (Ref).all;
205          end;
206       end if;
207    end Value;
208
209    function Value
210      (Ref    : in Pointer;
211       Length : in ptrdiff_t)
212       return   Element_Array
213    is
214       L : Index_Base;
215       H : Index_Base;
216
217    begin
218       if Ref = null then
219          raise Dereference_Error;
220
221       --  For length zero, we need to return a null slice, but we can't make
222       --  the bounds of this slice Index'First, since this could cause a
223       --  Constraint_Error if Index'First = Index'Base'First.
224
225       elsif Length <= 0 then
226          declare
227             pragma Warnings (Off); -- kill warnings since X not assigned
228             X : Element_Array (Index'Succ (Index'First) .. Index'First);
229             pragma Warnings (On);
230
231          begin
232             return X;
233          end;
234
235       --  Normal case (length non-zero)
236
237       else
238          L := Index'First;
239          H := Index'Val (Index'Pos (Index'First) + Length - 1);
240
241          declare
242             subtype A is Element_Array (L .. H);
243
244             type PA is access A;
245             function To_PA is new Unchecked_Conversion (Pointer, PA);
246
247          begin
248             return To_PA (Ref).all;
249          end;
250       end if;
251    end Value;
252
253    --------------------
254    -- Virtual_Length --
255    --------------------
256
257    function Virtual_Length
258      (Ref        : in Pointer;
259       Terminator : in Element := Default_Terminator)
260       return       ptrdiff_t
261    is
262       P : Pointer;
263       C : ptrdiff_t;
264
265    begin
266       if Ref = null then
267          raise Dereference_Error;
268
269       else
270          C := 0;
271          P := Ref;
272
273          while P.all /= Terminator loop
274             C := C + 1;
275             Increment (P);
276          end loop;
277
278          return C;
279       end if;
280    end Virtual_Length;
281
282 end Interfaces.C.Pointers;