OSDN Git Service

2005-03-29 Robert Dewar <dewar@adacore.com>
[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-2004 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 : Pointer; Right : 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 : ptrdiff_t; Right : 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 : Pointer; Right : 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 : Pointer; Right : 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  : Pointer;
104       Target  : Pointer;
105       Length  : 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     : Pointer;
129       Target     : Pointer;
130       Limit      : ptrdiff_t := ptrdiff_t'Last;
131       Terminator : 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        : Pointer;
176       Terminator : Element := Default_Terminator) return Element_Array
177    is
178       P : Pointer;
179       L : constant Index_Base := Index'First;
180       H : Index_Base;
181
182    begin
183       if Ref = null then
184          raise Dereference_Error;
185
186       else
187          H := L;
188          P := Ref;
189
190          loop
191             exit when P.all = Terminator;
192             H := Index_Base'Succ (H);
193             Increment (P);
194          end loop;
195
196          declare
197             subtype A is Element_Array (L .. H);
198
199             type PA is access A;
200             function To_PA is new Unchecked_Conversion (Pointer, PA);
201
202          begin
203             return To_PA (Ref).all;
204          end;
205       end if;
206    end Value;
207
208    function Value
209      (Ref    : Pointer;
210       Length : ptrdiff_t) return Element_Array
211    is
212       L : Index_Base;
213       H : Index_Base;
214
215    begin
216       if Ref = null then
217          raise Dereference_Error;
218
219       --  For length zero, we need to return a null slice, but we can't make
220       --  the bounds of this slice Index'First, since this could cause a
221       --  Constraint_Error if Index'First = Index'Base'First.
222
223       elsif Length <= 0 then
224          declare
225             pragma Warnings (Off); -- kill warnings since X not assigned
226             X : Element_Array (Index'Succ (Index'First) .. Index'First);
227             pragma Warnings (On);
228
229          begin
230             return X;
231          end;
232
233       --  Normal case (length non-zero)
234
235       else
236          L := Index'First;
237          H := Index'Val (Index'Pos (Index'First) + Length - 1);
238
239          declare
240             subtype A is Element_Array (L .. H);
241
242             type PA is access A;
243             function To_PA is new Unchecked_Conversion (Pointer, PA);
244
245          begin
246             return To_PA (Ref).all;
247          end;
248       end if;
249    end Value;
250
251    --------------------
252    -- Virtual_Length --
253    --------------------
254
255    function Virtual_Length
256      (Ref        : Pointer;
257       Terminator : Element := Default_Terminator) return ptrdiff_t
258    is
259       P : Pointer;
260       C : ptrdiff_t;
261
262    begin
263       if Ref = null then
264          raise Dereference_Error;
265
266       else
267          C := 0;
268          P := Ref;
269
270          while P.all /= Terminator loop
271             C := C + 1;
272             Increment (P);
273          end loop;
274
275          return C;
276       end if;
277    end Virtual_Length;
278
279 end Interfaces.C.Pointers;