OSDN Git Service

2008-03-26 Javier Miranda <miranda@adacore.com>
[pf3gnuchains/gcc-fork.git] / gcc / ada / s-valuti.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                      S Y S T E M . V A L _ U T I L                       --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 1992-2008, 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,  51  Franklin  Street,  Fifth  Floor, --
20 -- Boston, MA 02110-1301, 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 System.Case_Util; use System.Case_Util;
35
36 package body System.Val_Util is
37
38    ----------------------
39    -- Normalize_String --
40    ----------------------
41
42    procedure Normalize_String
43      (S    : in out String;
44       F, L : out Integer)
45    is
46    begin
47       F := S'First;
48       L := S'Last;
49
50       --  Scan for leading spaces
51
52       while F <= L and then S (F) = ' ' loop
53          F := F + 1;
54       end loop;
55
56       --  Check for case when the string contained no characters
57
58       if F > L then
59          raise Constraint_Error;
60       end if;
61
62       --  Scan for trailing spaces
63
64       while S (L) = ' ' loop
65          L := L - 1;
66       end loop;
67
68       --  Except in the case of a character literal, convert to upper case
69
70       if S (F) /= ''' then
71          for J in F .. L loop
72             S (J) := To_Upper (S (J));
73          end loop;
74       end if;
75    end Normalize_String;
76
77    -------------------
78    -- Scan_Exponent --
79    -------------------
80
81    function Scan_Exponent
82      (Str  : String;
83       Ptr  : not null access Integer;
84       Max  : Integer;
85       Real : Boolean := False) return Integer
86    is
87       P : Natural := Ptr.all;
88       M : Boolean;
89       X : Integer;
90
91    begin
92       if P >= Max
93         or else (Str (P) /= 'E' and then Str (P) /= 'e')
94       then
95          return 0;
96       end if;
97
98       --  We have an E/e, see if sign follows
99
100       P := P + 1;
101
102       if Str (P) = '+' then
103          P := P + 1;
104
105          if P > Max then
106             return 0;
107          else
108             M := False;
109          end if;
110
111       elsif Str (P) = '-' then
112          P := P + 1;
113
114          if P > Max or else not Real then
115             return 0;
116          else
117             M := True;
118          end if;
119
120       else
121          M := False;
122       end if;
123
124       if Str (P) not in '0' .. '9' then
125          return 0;
126       end if;
127
128       --  Scan out the exponent value as an unsigned integer. Values larger
129       --  than (Integer'Last / 10) are simply considered large enough here.
130       --  This assumption is correct for all machines we know of (e.g. in
131       --  the case of 16 bit integers it allows exponents up to 3276, which
132       --  is large enough for the largest floating types in base 2.)
133
134       X := 0;
135
136       loop
137          if X < (Integer'Last / 10) then
138             X := X * 10 + (Character'Pos (Str (P)) - Character'Pos ('0'));
139          end if;
140
141          P := P + 1;
142
143          exit when P > Max;
144
145          if Str (P) = '_' then
146             Scan_Underscore (Str, P, Ptr, Max, False);
147          else
148             exit when Str (P) not in '0' .. '9';
149          end if;
150       end loop;
151
152       if M then
153          X := -X;
154       end if;
155
156       Ptr.all := P;
157       return X;
158    end Scan_Exponent;
159
160    --------------------
161    -- Scan_Plus_Sign --
162    --------------------
163
164    procedure Scan_Plus_Sign
165      (Str   : String;
166       Ptr   : not null access Integer;
167       Max   : Integer;
168       Start : out Positive)
169    is
170       P : Natural := Ptr.all;
171
172    begin
173       if P > Max then
174          raise Constraint_Error;
175       end if;
176
177       --  Scan past initial blanks
178
179       while Str (P) = ' ' loop
180          P := P + 1;
181
182          if P > Max then
183             Ptr.all := P;
184             raise Constraint_Error;
185          end if;
186       end loop;
187
188       Start := P;
189
190       --  Skip past an initial plus sign
191
192       if Str (P) = '+' then
193          P := P + 1;
194
195          if P > Max then
196             Ptr.all := Start;
197             raise Constraint_Error;
198          end if;
199       end if;
200
201       Ptr.all := P;
202    end Scan_Plus_Sign;
203
204    ---------------
205    -- Scan_Sign --
206    ---------------
207
208    procedure Scan_Sign
209      (Str   : String;
210       Ptr   : not null access Integer;
211       Max   : Integer;
212       Minus : out Boolean;
213       Start : out Positive)
214    is
215       P : Natural := Ptr.all;
216
217    begin
218       --  Deal with case of null string (all blanks!). As per spec, we
219       --  raise constraint error, with Ptr unchanged, and thus > Max.
220
221       if P > Max then
222          raise Constraint_Error;
223       end if;
224
225       --  Scan past initial blanks
226
227       while Str (P) = ' ' loop
228          P := P + 1;
229
230          if P > Max then
231             Ptr.all := P;
232             raise Constraint_Error;
233          end if;
234       end loop;
235
236       Start := P;
237
238       --  Remember an initial minus sign
239
240       if Str (P) = '-' then
241          Minus := True;
242          P := P + 1;
243
244          if P > Max then
245             Ptr.all := Start;
246             raise Constraint_Error;
247          end if;
248
249       --  Skip past an initial plus sign
250
251       elsif Str (P) = '+' then
252          Minus := False;
253          P := P + 1;
254
255          if P > Max then
256             Ptr.all := Start;
257             raise Constraint_Error;
258          end if;
259
260       else
261          Minus := False;
262       end if;
263
264       Ptr.all := P;
265    end Scan_Sign;
266
267    --------------------------
268    -- Scan_Trailing_Blanks --
269    --------------------------
270
271    procedure Scan_Trailing_Blanks (Str : String; P : Positive) is
272    begin
273       for J in P .. Str'Last loop
274          if Str (J) /= ' ' then
275             raise Constraint_Error;
276          end if;
277       end loop;
278    end Scan_Trailing_Blanks;
279
280    ---------------------
281    -- Scan_Underscore --
282    ---------------------
283
284    procedure Scan_Underscore
285      (Str : String;
286       P   : in out Natural;
287       Ptr : not null access Integer;
288       Max : Integer;
289       Ext : Boolean)
290    is
291       C : Character;
292
293    begin
294       P := P + 1;
295
296       --  If underscore is at the end of string, then this is an error and
297       --  we raise Constraint_Error, leaving the pointer past the undescore.
298       --  This seems a bit strange. It means e,g, that if the field is:
299
300       --    345_
301
302       --  that Constraint_Error is raised. You might think that the RM in
303       --  this case would scan out the 345 as a valid integer, leaving the
304       --  pointer at the underscore, but the ACVC suite clearly requires
305       --  an error in this situation (see for example CE3704M).
306
307       if P > Max then
308          Ptr.all := P;
309          raise Constraint_Error;
310       end if;
311
312       --  Similarly, if no digit follows the underscore raise an error. This
313       --  also catches the case of double underscore which is also an error.
314
315       C := Str (P);
316
317       if C in '0' .. '9'
318         or else
319           (Ext and then (C in 'A' .. 'F' or else C in 'a' .. 'f'))
320       then
321          return;
322       else
323          Ptr.all := P;
324          raise Constraint_Error;
325       end if;
326    end Scan_Underscore;
327
328 end System.Val_Util;