annotate gcc/ada/libgnat/i-cstrin.adb @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 ------------------------------------------------------------------------------
kono
parents:
diff changeset
2 -- --
kono
parents:
diff changeset
3 -- GNAT COMPILER COMPONENTS --
kono
parents:
diff changeset
4 -- --
kono
parents:
diff changeset
5 -- I N T E R F A C E S . C . S T R I N G S --
kono
parents:
diff changeset
6 -- --
kono
parents:
diff changeset
7 -- B o d y --
kono
parents:
diff changeset
8 -- --
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
9 -- Copyright (C) 1992-2019, Free Software Foundation, Inc. --
111
kono
parents:
diff changeset
10 -- --
kono
parents:
diff changeset
11 -- GNAT is free software; you can redistribute it and/or modify it under --
kono
parents:
diff changeset
12 -- terms of the GNU General Public License as published by the Free Soft- --
kono
parents:
diff changeset
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
kono
parents:
diff changeset
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
kono
parents:
diff changeset
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
kono
parents:
diff changeset
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
kono
parents:
diff changeset
17 -- --
kono
parents:
diff changeset
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
kono
parents:
diff changeset
19 -- additional permissions described in the GCC Runtime Library Exception, --
kono
parents:
diff changeset
20 -- version 3.1, as published by the Free Software Foundation. --
kono
parents:
diff changeset
21 -- --
kono
parents:
diff changeset
22 -- You should have received a copy of the GNU General Public License and --
kono
parents:
diff changeset
23 -- a copy of the GCC Runtime Library Exception along with this program; --
kono
parents:
diff changeset
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
kono
parents:
diff changeset
25 -- <http://www.gnu.org/licenses/>. --
kono
parents:
diff changeset
26 -- --
kono
parents:
diff changeset
27 -- GNAT was originally developed by the GNAT team at New York University. --
kono
parents:
diff changeset
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
kono
parents:
diff changeset
29 -- --
kono
parents:
diff changeset
30 ------------------------------------------------------------------------------
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 with System; use System;
kono
parents:
diff changeset
33 with System.Storage_Elements; use System.Storage_Elements;
kono
parents:
diff changeset
34
kono
parents:
diff changeset
35 with Ada.Unchecked_Conversion;
kono
parents:
diff changeset
36
kono
parents:
diff changeset
37 package body Interfaces.C.Strings is
kono
parents:
diff changeset
38
kono
parents:
diff changeset
39 -- Note that the type chars_ptr has a pragma No_Strict_Aliasing in the
kono
parents:
diff changeset
40 -- spec, to prevent any assumptions about aliasing for values of this type,
kono
parents:
diff changeset
41 -- since arbitrary addresses can be converted, and it is quite likely that
kono
parents:
diff changeset
42 -- this type will in fact be used for aliasing values of other types.
kono
parents:
diff changeset
43
kono
parents:
diff changeset
44 function To_chars_ptr is
kono
parents:
diff changeset
45 new Ada.Unchecked_Conversion (System.Parameters.C_Address, chars_ptr);
kono
parents:
diff changeset
46
kono
parents:
diff changeset
47 function To_Address is
kono
parents:
diff changeset
48 new Ada.Unchecked_Conversion (chars_ptr, System.Parameters.C_Address);
kono
parents:
diff changeset
49
kono
parents:
diff changeset
50 -----------------------
kono
parents:
diff changeset
51 -- Local Subprograms --
kono
parents:
diff changeset
52 -----------------------
kono
parents:
diff changeset
53
kono
parents:
diff changeset
54 function Peek (From : chars_ptr) return char;
kono
parents:
diff changeset
55 pragma Inline (Peek);
kono
parents:
diff changeset
56 -- Given a chars_ptr value, obtain referenced character
kono
parents:
diff changeset
57
kono
parents:
diff changeset
58 procedure Poke (Value : char; Into : chars_ptr);
kono
parents:
diff changeset
59 pragma Inline (Poke);
kono
parents:
diff changeset
60 -- Given a chars_ptr, modify referenced Character value
kono
parents:
diff changeset
61
kono
parents:
diff changeset
62 function "+" (Left : chars_ptr; Right : size_t) return chars_ptr;
kono
parents:
diff changeset
63 pragma Inline ("+");
kono
parents:
diff changeset
64 -- Address arithmetic on chars_ptr value
kono
parents:
diff changeset
65
kono
parents:
diff changeset
66 function Position_Of_Nul (Into : char_array) return size_t;
kono
parents:
diff changeset
67 -- Returns position of the first Nul in Into or Into'Last + 1 if none
kono
parents:
diff changeset
68
kono
parents:
diff changeset
69 -- We can't use directly System.Memory because the categorization is not
kono
parents:
diff changeset
70 -- compatible, so we directly import here the malloc and free routines.
kono
parents:
diff changeset
71
kono
parents:
diff changeset
72 function Memory_Alloc (Size : size_t) return chars_ptr;
kono
parents:
diff changeset
73 pragma Import (C, Memory_Alloc, System.Parameters.C_Malloc_Linkname);
kono
parents:
diff changeset
74
kono
parents:
diff changeset
75 procedure Memory_Free (Address : chars_ptr);
kono
parents:
diff changeset
76 pragma Import (C, Memory_Free, "__gnat_free");
kono
parents:
diff changeset
77
kono
parents:
diff changeset
78 ---------
kono
parents:
diff changeset
79 -- "+" --
kono
parents:
diff changeset
80 ---------
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 function "+" (Left : chars_ptr; Right : size_t) return chars_ptr is
kono
parents:
diff changeset
83 begin
kono
parents:
diff changeset
84 return To_chars_ptr (To_Address (Left) + Storage_Offset (Right));
kono
parents:
diff changeset
85 end "+";
kono
parents:
diff changeset
86
kono
parents:
diff changeset
87 ----------
kono
parents:
diff changeset
88 -- Free --
kono
parents:
diff changeset
89 ----------
kono
parents:
diff changeset
90
kono
parents:
diff changeset
91 procedure Free (Item : in out chars_ptr) is
kono
parents:
diff changeset
92 begin
kono
parents:
diff changeset
93 if Item = Null_Ptr then
kono
parents:
diff changeset
94 return;
kono
parents:
diff changeset
95 end if;
kono
parents:
diff changeset
96
kono
parents:
diff changeset
97 Memory_Free (Item);
kono
parents:
diff changeset
98 Item := Null_Ptr;
kono
parents:
diff changeset
99 end Free;
kono
parents:
diff changeset
100
kono
parents:
diff changeset
101 --------------------
kono
parents:
diff changeset
102 -- New_Char_Array --
kono
parents:
diff changeset
103 --------------------
kono
parents:
diff changeset
104
kono
parents:
diff changeset
105 function New_Char_Array (Chars : char_array) return chars_ptr is
kono
parents:
diff changeset
106 Index : size_t;
kono
parents:
diff changeset
107 Pointer : chars_ptr;
kono
parents:
diff changeset
108
kono
parents:
diff changeset
109 begin
kono
parents:
diff changeset
110 -- Get index of position of null. If Index > Chars'Last,
kono
parents:
diff changeset
111 -- nul is absent and must be added explicitly.
kono
parents:
diff changeset
112
kono
parents:
diff changeset
113 Index := Position_Of_Nul (Into => Chars);
kono
parents:
diff changeset
114 Pointer := Memory_Alloc ((Index - Chars'First + 1));
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116 -- If nul is present, transfer string up to and including nul
kono
parents:
diff changeset
117
kono
parents:
diff changeset
118 if Index <= Chars'Last then
kono
parents:
diff changeset
119 Update (Item => Pointer,
kono
parents:
diff changeset
120 Offset => 0,
kono
parents:
diff changeset
121 Chars => Chars (Chars'First .. Index),
kono
parents:
diff changeset
122 Check => False);
kono
parents:
diff changeset
123 else
kono
parents:
diff changeset
124 -- If original string has no nul, transfer whole string and add
kono
parents:
diff changeset
125 -- terminator explicitly.
kono
parents:
diff changeset
126
kono
parents:
diff changeset
127 Update (Item => Pointer,
kono
parents:
diff changeset
128 Offset => 0,
kono
parents:
diff changeset
129 Chars => Chars,
kono
parents:
diff changeset
130 Check => False);
kono
parents:
diff changeset
131 Poke (nul, Into => Pointer + size_t'(Chars'Length));
kono
parents:
diff changeset
132 end if;
kono
parents:
diff changeset
133
kono
parents:
diff changeset
134 return Pointer;
kono
parents:
diff changeset
135 end New_Char_Array;
kono
parents:
diff changeset
136
kono
parents:
diff changeset
137 ----------------
kono
parents:
diff changeset
138 -- New_String --
kono
parents:
diff changeset
139 ----------------
kono
parents:
diff changeset
140
kono
parents:
diff changeset
141 function New_String (Str : String) return chars_ptr is
kono
parents:
diff changeset
142
kono
parents:
diff changeset
143 -- It's important that this subprogram uses the heap directly to compute
kono
parents:
diff changeset
144 -- the result, and doesn't copy the string on the stack, otherwise its
kono
parents:
diff changeset
145 -- use is limited when used from tasks on large strings.
kono
parents:
diff changeset
146
kono
parents:
diff changeset
147 Result : constant chars_ptr := Memory_Alloc (Str'Length + 1);
kono
parents:
diff changeset
148
kono
parents:
diff changeset
149 Result_Array : char_array (1 .. Str'Length + 1);
kono
parents:
diff changeset
150 for Result_Array'Address use To_Address (Result);
kono
parents:
diff changeset
151 pragma Import (Ada, Result_Array);
kono
parents:
diff changeset
152
kono
parents:
diff changeset
153 Count : size_t;
kono
parents:
diff changeset
154
kono
parents:
diff changeset
155 begin
kono
parents:
diff changeset
156 To_C
kono
parents:
diff changeset
157 (Item => Str,
kono
parents:
diff changeset
158 Target => Result_Array,
kono
parents:
diff changeset
159 Count => Count,
kono
parents:
diff changeset
160 Append_Nul => True);
kono
parents:
diff changeset
161 return Result;
kono
parents:
diff changeset
162 end New_String;
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164 ----------
kono
parents:
diff changeset
165 -- Peek --
kono
parents:
diff changeset
166 ----------
kono
parents:
diff changeset
167
kono
parents:
diff changeset
168 function Peek (From : chars_ptr) return char is
kono
parents:
diff changeset
169 begin
kono
parents:
diff changeset
170 return char (From.all);
kono
parents:
diff changeset
171 end Peek;
kono
parents:
diff changeset
172
kono
parents:
diff changeset
173 ----------
kono
parents:
diff changeset
174 -- Poke --
kono
parents:
diff changeset
175 ----------
kono
parents:
diff changeset
176
kono
parents:
diff changeset
177 procedure Poke (Value : char; Into : chars_ptr) is
kono
parents:
diff changeset
178 begin
kono
parents:
diff changeset
179 Into.all := Character (Value);
kono
parents:
diff changeset
180 end Poke;
kono
parents:
diff changeset
181
kono
parents:
diff changeset
182 ---------------------
kono
parents:
diff changeset
183 -- Position_Of_Nul --
kono
parents:
diff changeset
184 ---------------------
kono
parents:
diff changeset
185
kono
parents:
diff changeset
186 function Position_Of_Nul (Into : char_array) return size_t is
kono
parents:
diff changeset
187 begin
kono
parents:
diff changeset
188 for J in Into'Range loop
kono
parents:
diff changeset
189 if Into (J) = nul then
kono
parents:
diff changeset
190 return J;
kono
parents:
diff changeset
191 end if;
kono
parents:
diff changeset
192 end loop;
kono
parents:
diff changeset
193
kono
parents:
diff changeset
194 return Into'Last + 1;
kono
parents:
diff changeset
195 end Position_Of_Nul;
kono
parents:
diff changeset
196
kono
parents:
diff changeset
197 ------------
kono
parents:
diff changeset
198 -- Strlen --
kono
parents:
diff changeset
199 ------------
kono
parents:
diff changeset
200
kono
parents:
diff changeset
201 function Strlen (Item : chars_ptr) return size_t is
kono
parents:
diff changeset
202 Item_Index : size_t := 0;
kono
parents:
diff changeset
203
kono
parents:
diff changeset
204 begin
kono
parents:
diff changeset
205 if Item = Null_Ptr then
kono
parents:
diff changeset
206 raise Dereference_Error;
kono
parents:
diff changeset
207 end if;
kono
parents:
diff changeset
208
kono
parents:
diff changeset
209 loop
kono
parents:
diff changeset
210 if Peek (Item + Item_Index) = nul then
kono
parents:
diff changeset
211 return Item_Index;
kono
parents:
diff changeset
212 end if;
kono
parents:
diff changeset
213
kono
parents:
diff changeset
214 Item_Index := Item_Index + 1;
kono
parents:
diff changeset
215 end loop;
kono
parents:
diff changeset
216 end Strlen;
kono
parents:
diff changeset
217
kono
parents:
diff changeset
218 ------------------
kono
parents:
diff changeset
219 -- To_Chars_Ptr --
kono
parents:
diff changeset
220 ------------------
kono
parents:
diff changeset
221
kono
parents:
diff changeset
222 function To_Chars_Ptr
kono
parents:
diff changeset
223 (Item : char_array_access;
kono
parents:
diff changeset
224 Nul_Check : Boolean := False) return chars_ptr
kono
parents:
diff changeset
225 is
kono
parents:
diff changeset
226 begin
kono
parents:
diff changeset
227 if Item = null then
kono
parents:
diff changeset
228 return Null_Ptr;
kono
parents:
diff changeset
229 elsif Nul_Check
kono
parents:
diff changeset
230 and then Position_Of_Nul (Into => Item.all) > Item'Last
kono
parents:
diff changeset
231 then
kono
parents:
diff changeset
232 raise Terminator_Error;
kono
parents:
diff changeset
233 else
kono
parents:
diff changeset
234 return To_chars_ptr (Item (Item'First)'Address);
kono
parents:
diff changeset
235 end if;
kono
parents:
diff changeset
236 end To_Chars_Ptr;
kono
parents:
diff changeset
237
kono
parents:
diff changeset
238 ------------
kono
parents:
diff changeset
239 -- Update --
kono
parents:
diff changeset
240 ------------
kono
parents:
diff changeset
241
kono
parents:
diff changeset
242 procedure Update
kono
parents:
diff changeset
243 (Item : chars_ptr;
kono
parents:
diff changeset
244 Offset : size_t;
kono
parents:
diff changeset
245 Chars : char_array;
kono
parents:
diff changeset
246 Check : Boolean := True)
kono
parents:
diff changeset
247 is
kono
parents:
diff changeset
248 Index : chars_ptr := Item + Offset;
kono
parents:
diff changeset
249
kono
parents:
diff changeset
250 begin
kono
parents:
diff changeset
251 if Check and then Offset + Chars'Length > Strlen (Item) then
kono
parents:
diff changeset
252 raise Update_Error;
kono
parents:
diff changeset
253 end if;
kono
parents:
diff changeset
254
kono
parents:
diff changeset
255 for J in Chars'Range loop
kono
parents:
diff changeset
256 Poke (Chars (J), Into => Index);
kono
parents:
diff changeset
257 Index := Index + size_t'(1);
kono
parents:
diff changeset
258 end loop;
kono
parents:
diff changeset
259 end Update;
kono
parents:
diff changeset
260
kono
parents:
diff changeset
261 procedure Update
kono
parents:
diff changeset
262 (Item : chars_ptr;
kono
parents:
diff changeset
263 Offset : size_t;
kono
parents:
diff changeset
264 Str : String;
kono
parents:
diff changeset
265 Check : Boolean := True)
kono
parents:
diff changeset
266 is
kono
parents:
diff changeset
267 begin
kono
parents:
diff changeset
268 -- Note: in RM 95, the Append_Nul => False parameter is omitted. But
kono
parents:
diff changeset
269 -- this has the unintended consequence of truncating the string after
kono
parents:
diff changeset
270 -- an update. As discussed in Ada 2005 AI-242, this was unintended,
kono
parents:
diff changeset
271 -- and should be corrected. Since this is a clear error, it seems
kono
parents:
diff changeset
272 -- appropriate to apply the correction in Ada 95 mode as well.
kono
parents:
diff changeset
273
kono
parents:
diff changeset
274 Update (Item, Offset, To_C (Str, Append_Nul => False), Check);
kono
parents:
diff changeset
275 end Update;
kono
parents:
diff changeset
276
kono
parents:
diff changeset
277 -----------
kono
parents:
diff changeset
278 -- Value --
kono
parents:
diff changeset
279 -----------
kono
parents:
diff changeset
280
kono
parents:
diff changeset
281 function Value (Item : chars_ptr) return char_array is
kono
parents:
diff changeset
282 Result : char_array (0 .. Strlen (Item));
kono
parents:
diff changeset
283
kono
parents:
diff changeset
284 begin
kono
parents:
diff changeset
285 if Item = Null_Ptr then
kono
parents:
diff changeset
286 raise Dereference_Error;
kono
parents:
diff changeset
287 end if;
kono
parents:
diff changeset
288
kono
parents:
diff changeset
289 -- Note that the following loop will also copy the terminating Nul
kono
parents:
diff changeset
290
kono
parents:
diff changeset
291 for J in Result'Range loop
kono
parents:
diff changeset
292 Result (J) := Peek (Item + J);
kono
parents:
diff changeset
293 end loop;
kono
parents:
diff changeset
294
kono
parents:
diff changeset
295 return Result;
kono
parents:
diff changeset
296 end Value;
kono
parents:
diff changeset
297
kono
parents:
diff changeset
298 function Value
kono
parents:
diff changeset
299 (Item : chars_ptr;
kono
parents:
diff changeset
300 Length : size_t) return char_array
kono
parents:
diff changeset
301 is
kono
parents:
diff changeset
302 begin
kono
parents:
diff changeset
303 if Item = Null_Ptr then
kono
parents:
diff changeset
304 raise Dereference_Error;
kono
parents:
diff changeset
305 end if;
kono
parents:
diff changeset
306
kono
parents:
diff changeset
307 -- ACATS cxb3010 checks that Constraint_Error gets raised when Length
kono
parents:
diff changeset
308 -- is 0. Seems better to check that Length is not null before declaring
kono
parents:
diff changeset
309 -- an array with size_t bounds of 0 .. Length - 1 anyway.
kono
parents:
diff changeset
310
kono
parents:
diff changeset
311 if Length = 0 then
kono
parents:
diff changeset
312 raise Constraint_Error;
kono
parents:
diff changeset
313 end if;
kono
parents:
diff changeset
314
kono
parents:
diff changeset
315 declare
kono
parents:
diff changeset
316 Result : char_array (0 .. Length - 1);
kono
parents:
diff changeset
317
kono
parents:
diff changeset
318 begin
kono
parents:
diff changeset
319 for J in Result'Range loop
kono
parents:
diff changeset
320 Result (J) := Peek (Item + J);
kono
parents:
diff changeset
321
kono
parents:
diff changeset
322 if Result (J) = nul then
kono
parents:
diff changeset
323 return Result (0 .. J);
kono
parents:
diff changeset
324 end if;
kono
parents:
diff changeset
325 end loop;
kono
parents:
diff changeset
326
kono
parents:
diff changeset
327 return Result;
kono
parents:
diff changeset
328 end;
kono
parents:
diff changeset
329 end Value;
kono
parents:
diff changeset
330
kono
parents:
diff changeset
331 function Value (Item : chars_ptr) return String is
kono
parents:
diff changeset
332 begin
kono
parents:
diff changeset
333 return To_Ada (Value (Item));
kono
parents:
diff changeset
334 end Value;
kono
parents:
diff changeset
335
kono
parents:
diff changeset
336 function Value (Item : chars_ptr; Length : size_t) return String is
kono
parents:
diff changeset
337 Result : char_array (0 .. Length);
kono
parents:
diff changeset
338
kono
parents:
diff changeset
339 begin
kono
parents:
diff changeset
340 -- As per AI-00177, this is equivalent to:
kono
parents:
diff changeset
341
kono
parents:
diff changeset
342 -- To_Ada (Value (Item, Length) & nul);
kono
parents:
diff changeset
343
kono
parents:
diff changeset
344 if Item = Null_Ptr then
kono
parents:
diff changeset
345 raise Dereference_Error;
kono
parents:
diff changeset
346 end if;
kono
parents:
diff changeset
347
kono
parents:
diff changeset
348 for J in 0 .. Length - 1 loop
kono
parents:
diff changeset
349 Result (J) := Peek (Item + J);
kono
parents:
diff changeset
350
kono
parents:
diff changeset
351 if Result (J) = nul then
kono
parents:
diff changeset
352 return To_Ada (Result (0 .. J));
kono
parents:
diff changeset
353 end if;
kono
parents:
diff changeset
354 end loop;
kono
parents:
diff changeset
355
kono
parents:
diff changeset
356 Result (Length) := nul;
kono
parents:
diff changeset
357 return To_Ada (Result);
kono
parents:
diff changeset
358 end Value;
kono
parents:
diff changeset
359
kono
parents:
diff changeset
360 end Interfaces.C.Strings;