OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [ada/] [s-valuns.adb] - Blame information for rev 706

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 706 jeremybenn
------------------------------------------------------------------------------
2
--                                                                          --
3
--                         GNAT COMPILER COMPONENTS                         --
4
--                                                                          --
5
--                       S Y S T E M . V A L _ U N S                        --
6
--                                                                          --
7
--                                 B o d y                                  --
8
--                                                                          --
9
--          Copyright (C) 1992-2009, 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 3,  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.                                     --
17
--                                                                          --
18
-- As a special exception under Section 7 of GPL version 3, you are granted --
19
-- additional permissions described in the GCC Runtime Library Exception,   --
20
-- version 3.1, as published by the Free Software Foundation.               --
21
--                                                                          --
22
-- You should have received a copy of the GNU General Public License and    --
23
-- a copy of the GCC Runtime Library Exception along with this program;     --
24
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
25
-- <http://www.gnu.org/licenses/>.                                          --
26
--                                                                          --
27
-- GNAT was originally developed  by the GNAT team at  New York University. --
28
-- Extensive contributions were provided by Ada Core Technologies Inc.      --
29
--                                                                          --
30
------------------------------------------------------------------------------
31
 
32
with System.Unsigned_Types; use System.Unsigned_Types;
33
with System.Val_Util;       use System.Val_Util;
34
 
35
package body System.Val_Uns is
36
 
37
   -----------------------
38
   -- Scan_Raw_Unsigned --
39
   -----------------------
40
 
41
   function Scan_Raw_Unsigned
42
     (Str : String;
43
      Ptr : not null access Integer;
44
      Max : Integer) return Unsigned
45
   is
46
      P : Integer;
47
      --  Local copy of the pointer
48
 
49
      Uval : Unsigned;
50
      --  Accumulated unsigned integer result
51
 
52
      Expon : Integer;
53
      --  Exponent value
54
 
55
      Overflow : Boolean := False;
56
      --  Set True if overflow is detected at any point
57
 
58
      Base_Char : Character;
59
      --  Base character (# or :) in based case
60
 
61
      Base : Unsigned := 10;
62
      --  Base value (reset in based case)
63
 
64
      Digit : Unsigned;
65
      --  Digit value
66
 
67
   begin
68
      P := Ptr.all;
69
      Uval := Character'Pos (Str (P)) - Character'Pos ('0');
70
      P := P + 1;
71
 
72
      --  Scan out digits of what is either the number or the base.
73
      --  In either case, we are definitely scanning out in base 10.
74
 
75
      declare
76
         Umax : constant := (Unsigned'Last - 9) / 10;
77
         --  Max value which cannot overflow on accumulating next digit
78
 
79
         Umax10 : constant := Unsigned'Last / 10;
80
         --  Numbers bigger than Umax10 overflow if multiplied by 10
81
 
82
      begin
83
         --  Loop through decimal digits
84
         loop
85
            exit when P > Max;
86
 
87
            Digit := Character'Pos (Str (P)) - Character'Pos ('0');
88
 
89
            --  Non-digit encountered
90
 
91
            if Digit > 9 then
92
               if Str (P) = '_' then
93
                  Scan_Underscore (Str, P, Ptr, Max, False);
94
               else
95
                  exit;
96
               end if;
97
 
98
            --  Accumulate result, checking for overflow
99
 
100
            else
101
               if Uval <= Umax then
102
                  Uval := 10 * Uval + Digit;
103
 
104
               elsif Uval > Umax10 then
105
                  Overflow := True;
106
 
107
               else
108
                  Uval := 10 * Uval + Digit;
109
 
110
                  if Uval < Umax10 then
111
                     Overflow := True;
112
                  end if;
113
               end if;
114
 
115
               P := P + 1;
116
            end if;
117
         end loop;
118
      end;
119
 
120
      Ptr.all := P;
121
 
122
      --  Deal with based case
123
 
124
      if P < Max and then (Str (P) = ':' or else Str (P) = '#') then
125
         Base_Char := Str (P);
126
         P := P + 1;
127
         Base := Uval;
128
         Uval := 0;
129
 
130
         --  Check base value. Overflow is set True if we find a bad base, or
131
         --  a digit that is out of range of the base. That way, we scan out
132
         --  the numeral that is still syntactically correct, though illegal.
133
         --  We use a safe base of 16 for this scan, to avoid zero divide.
134
 
135
         if Base not in 2 .. 16 then
136
            Overflow := True;
137
            Base :=  16;
138
         end if;
139
 
140
         --  Scan out based integer
141
 
142
         declare
143
            Umax : constant Unsigned := (Unsigned'Last - Base + 1) / Base;
144
            --  Max value which cannot overflow on accumulating next digit
145
 
146
            UmaxB : constant Unsigned := Unsigned'Last / Base;
147
            --  Numbers bigger than UmaxB overflow if multiplied by base
148
 
149
         begin
150
            --  Loop to scan out based integer value
151
 
152
            loop
153
               --  We require a digit at this stage
154
 
155
               if Str (P) in '0' .. '9' then
156
                  Digit := Character'Pos (Str (P)) - Character'Pos ('0');
157
 
158
               elsif Str (P) in 'A' .. 'F' then
159
                  Digit :=
160
                    Character'Pos (Str (P)) - (Character'Pos ('A') - 10);
161
 
162
               elsif Str (P) in 'a' .. 'f' then
163
                  Digit :=
164
                    Character'Pos (Str (P)) - (Character'Pos ('a') - 10);
165
 
166
               --  If we don't have a digit, then this is not a based number
167
               --  after all, so we use the value we scanned out as the base
168
               --  (now in Base), and the pointer to the base character was
169
               --  already stored in Ptr.all.
170
 
171
               else
172
                  Uval := Base;
173
                  exit;
174
               end if;
175
 
176
               --  If digit is too large, just signal overflow and continue.
177
               --  The idea here is to keep scanning as long as the input is
178
               --  syntactically valid, even if we have detected overflow
179
 
180
               if Digit >= Base then
181
                  Overflow := True;
182
 
183
               --  Here we accumulate the value, checking overflow
184
 
185
               elsif Uval <= Umax then
186
                  Uval := Base * Uval + Digit;
187
 
188
               elsif Uval > UmaxB then
189
                  Overflow := True;
190
 
191
               else
192
                  Uval := Base * Uval + Digit;
193
 
194
                  if Uval < UmaxB then
195
                     Overflow := True;
196
                  end if;
197
               end if;
198
 
199
               --  If at end of string with no base char, not a based number
200
               --  but we signal Constraint_Error and set the pointer past
201
               --  the end of the field, since this is what the ACVC tests
202
               --  seem to require, see CE3704N, line 204.
203
 
204
               P := P + 1;
205
 
206
               if P > Max then
207
                  Ptr.all := P;
208
                  raise Constraint_Error;
209
               end if;
210
 
211
               --  If terminating base character, we are done with loop
212
 
213
               if Str (P) = Base_Char then
214
                  Ptr.all := P + 1;
215
                  exit;
216
 
217
               --  Deal with underscore
218
 
219
               elsif Str (P) = '_' then
220
                  Scan_Underscore (Str, P, Ptr, Max, True);
221
               end if;
222
 
223
            end loop;
224
         end;
225
      end if;
226
 
227
      --  Come here with scanned unsigned value in Uval. The only remaining
228
      --  required step is to deal with exponent if one is present.
229
 
230
      Expon := Scan_Exponent (Str, Ptr, Max);
231
 
232
      if Expon /= 0 and then Uval /= 0 then
233
 
234
         --  For non-zero value, scale by exponent value. No need to do this
235
         --  efficiently, since use of exponent in integer literals is rare,
236
         --  and in any case the exponent cannot be very large.
237
 
238
         declare
239
            UmaxB : constant Unsigned := Unsigned'Last / Base;
240
            --  Numbers bigger than UmaxB overflow if multiplied by base
241
 
242
         begin
243
            for J in 1 .. Expon loop
244
               if Uval > UmaxB then
245
                  Overflow := True;
246
                  exit;
247
               end if;
248
 
249
               Uval := Uval * Base;
250
            end loop;
251
         end;
252
      end if;
253
 
254
      --  Return result, dealing with sign and overflow
255
 
256
      if Overflow then
257
         raise Constraint_Error;
258
      else
259
         return Uval;
260
      end if;
261
   end Scan_Raw_Unsigned;
262
 
263
   -------------------
264
   -- Scan_Unsigned --
265
   -------------------
266
 
267
   function Scan_Unsigned
268
     (Str : String;
269
      Ptr : not null access Integer;
270
      Max : Integer) return Unsigned
271
   is
272
      Start : Positive;
273
      --  Save location of first non-blank character
274
 
275
   begin
276
      Scan_Plus_Sign (Str, Ptr, Max, Start);
277
 
278
      if Str (Ptr.all) not in '0' .. '9' then
279
         Ptr.all := Start;
280
         raise Constraint_Error;
281
      end if;
282
 
283
      return Scan_Raw_Unsigned (Str, Ptr, Max);
284
   end Scan_Unsigned;
285
 
286
   --------------------
287
   -- Value_Unsigned --
288
   --------------------
289
 
290
   function Value_Unsigned (Str : String) return Unsigned is
291
      V : Unsigned;
292
      P : aliased Integer := Str'First;
293
   begin
294
      V := Scan_Unsigned (Str, P'Access, Str'Last);
295
      Scan_Trailing_Blanks (Str, P);
296
      return V;
297
   end Value_Unsigned;
298
 
299
end System.Val_Uns;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.