/src/binutils-gdb/gas/atof-generic.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* atof_generic.c - turn a string of digits into a Flonum |
2 | | Copyright (C) 1987-2025 Free Software Foundation, Inc. |
3 | | |
4 | | This file is part of GAS, the GNU Assembler. |
5 | | |
6 | | GAS is free software; you can redistribute it and/or modify |
7 | | it under the terms of the GNU General Public License as published by |
8 | | the Free Software Foundation; either version 3, or (at your option) |
9 | | any later version. |
10 | | |
11 | | GAS is distributed in the hope that it will be useful, but WITHOUT |
12 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
13 | | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public |
14 | | License for more details. |
15 | | |
16 | | You should have received a copy of the GNU General Public License |
17 | | along with GAS; see the file COPYING. If not, write to the Free |
18 | | Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA |
19 | | 02110-1301, USA. */ |
20 | | |
21 | | #include "as.h" |
22 | | #include "safe-ctype.h" |
23 | | #include <limits.h> |
24 | | |
25 | | #ifdef TRACE |
26 | | static void flonum_print (const FLONUM_TYPE *); |
27 | | #endif |
28 | | |
29 | | #define ASSUME_DECIMAL_MARK_IS_DOT |
30 | | |
31 | | /***********************************************************************\ |
32 | | * * |
33 | | * Given a string of decimal digits , with optional decimal * |
34 | | * mark and optional decimal exponent (place value) of the * |
35 | | * lowest_order decimal digit: produce a floating point * |
36 | | * number. The number is 'generic' floating point: our * |
37 | | * caller will encode it for a specific machine architecture. * |
38 | | * * |
39 | | * Assumptions * |
40 | | * uses base (radix) 2 * |
41 | | * this machine uses 2's complement binary integers * |
42 | | * target flonums use " " " " * |
43 | | * target flonums exponents fit in a long * |
44 | | * * |
45 | | \***********************************************************************/ |
46 | | |
47 | | /* |
48 | | |
49 | | Syntax: |
50 | | |
51 | | <flonum> ::= <optional-sign> <decimal-number> <optional-exponent> |
52 | | <optional-sign> ::= '+' | '-' | {empty} |
53 | | <decimal-number> ::= <integer> |
54 | | | <integer> <radix-character> |
55 | | | <integer> <radix-character> <integer> |
56 | | | <radix-character> <integer> |
57 | | |
58 | | <optional-exponent> ::= {empty} |
59 | | | <exponent-character> <optional-sign> <integer> |
60 | | |
61 | | <integer> ::= <digit> | <digit> <integer> |
62 | | <digit> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' |
63 | | <exponent-character> ::= {one character from "string_of_decimal_exponent_marks"} |
64 | | <radix-character> ::= {one character from "string_of_decimal_marks"} |
65 | | |
66 | | */ |
67 | | |
68 | | int |
69 | | atof_generic (/* return pointer to just AFTER number we read. */ |
70 | | char **address_of_string_pointer, |
71 | | /* At most one per number. */ |
72 | | const char *string_of_decimal_marks, |
73 | | const char *string_of_decimal_exponent_marks, |
74 | | FLONUM_TYPE *address_of_generic_floating_point_number) |
75 | 9.39k | { |
76 | 9.39k | int return_value = 0; /* 0 means OK. */ |
77 | 9.39k | char *first_digit; |
78 | 9.39k | unsigned int number_of_digits_before_decimal; |
79 | 9.39k | unsigned int number_of_digits_after_decimal; |
80 | 9.39k | unsigned long decimal_exponent; |
81 | 9.39k | unsigned int number_of_digits_available; |
82 | 9.39k | char digits_sign_char; |
83 | | |
84 | | /* |
85 | | * Scan the input string, abstracting (1)digits (2)decimal mark (3) exponent. |
86 | | * It would be simpler to modify the string, but we don't; just to be nice |
87 | | * to caller. |
88 | | * We need to know how many digits we have, so we can allocate space for |
89 | | * the digits' value. |
90 | | */ |
91 | | |
92 | 9.39k | char *p; |
93 | 9.39k | char c; |
94 | 9.39k | int seen_significant_digit; |
95 | | |
96 | 9.39k | #ifdef ASSUME_DECIMAL_MARK_IS_DOT |
97 | 9.39k | gas_assert (string_of_decimal_marks[0] == '.' |
98 | 9.39k | && string_of_decimal_marks[1] == 0); |
99 | 23.5k | #define IS_DECIMAL_MARK(c) ((c) == '.') |
100 | | #else |
101 | | #define IS_DECIMAL_MARK(c) (0 != strchr (string_of_decimal_marks, (c))) |
102 | | #endif |
103 | | |
104 | 9.39k | first_digit = *address_of_string_pointer; |
105 | 9.39k | c = *first_digit; |
106 | | |
107 | 9.39k | if (c == '-' || c == '+') |
108 | 70 | { |
109 | 70 | digits_sign_char = c; |
110 | 70 | first_digit++; |
111 | 70 | } |
112 | 9.32k | else |
113 | 9.32k | digits_sign_char = '+'; |
114 | | |
115 | 9.39k | switch (first_digit[0]) |
116 | 9.39k | { |
117 | 0 | case 's': |
118 | 85 | case 'S': |
119 | 103 | case 'q': |
120 | 103 | case 'Q': |
121 | 103 | if (!strncasecmp ("nan", first_digit + 1, 3)) |
122 | 0 | { |
123 | 0 | address_of_generic_floating_point_number->sign = |
124 | 0 | digits_sign_char == '+' ? TOUPPER (first_digit[0]) |
125 | 0 | : TOLOWER (first_digit[0]); |
126 | 0 | address_of_generic_floating_point_number->exponent = 0; |
127 | 0 | address_of_generic_floating_point_number->leader = |
128 | 0 | address_of_generic_floating_point_number->low; |
129 | 0 | *address_of_string_pointer = first_digit + 4; |
130 | 0 | return 0; |
131 | 0 | } |
132 | 103 | break; |
133 | | |
134 | 103 | case 'n': |
135 | 5 | case 'N': |
136 | 5 | if (!strncasecmp ("nan", first_digit, 3)) |
137 | 0 | { |
138 | 0 | address_of_generic_floating_point_number->sign = |
139 | 0 | digits_sign_char == '+' ? 0 : 'q'; |
140 | 0 | address_of_generic_floating_point_number->exponent = 0; |
141 | 0 | address_of_generic_floating_point_number->leader = |
142 | 0 | address_of_generic_floating_point_number->low; |
143 | 0 | *address_of_string_pointer = first_digit + 3; |
144 | 0 | return 0; |
145 | 0 | } |
146 | 5 | break; |
147 | | |
148 | 5 | case 'i': |
149 | 0 | case 'I': |
150 | 0 | if (!strncasecmp ("inf", first_digit, 3)) |
151 | 0 | { |
152 | 0 | address_of_generic_floating_point_number->sign = |
153 | 0 | digits_sign_char == '+' ? 'P' : 'N'; |
154 | 0 | address_of_generic_floating_point_number->exponent = 0; |
155 | 0 | address_of_generic_floating_point_number->leader = |
156 | 0 | address_of_generic_floating_point_number->low; |
157 | |
|
158 | 0 | first_digit += 3; |
159 | 0 | if (!strncasecmp ("inity", first_digit, 5)) |
160 | 0 | first_digit += 5; |
161 | |
|
162 | 0 | *address_of_string_pointer = first_digit; |
163 | |
|
164 | 0 | return 0; |
165 | 0 | } |
166 | 0 | break; |
167 | 9.39k | } |
168 | | |
169 | 9.39k | number_of_digits_before_decimal = 0; |
170 | 9.39k | number_of_digits_after_decimal = 0; |
171 | 9.39k | decimal_exponent = 0; |
172 | 9.39k | seen_significant_digit = 0; |
173 | 9.39k | for (p = first_digit; |
174 | 14.1k | (((c = *p) != '\0') |
175 | 14.1k | && (!c || !IS_DECIMAL_MARK (c)) |
176 | 14.1k | && (!c || !strchr (string_of_decimal_exponent_marks, c))); |
177 | 9.39k | p++) |
178 | 8.64k | { |
179 | 8.64k | if (ISDIGIT (c)) |
180 | 4.73k | { |
181 | 4.73k | if (seen_significant_digit || c > '0') |
182 | 4.66k | { |
183 | 4.66k | ++number_of_digits_before_decimal; |
184 | 4.66k | seen_significant_digit = 1; |
185 | 4.66k | } |
186 | 75 | else |
187 | 75 | { |
188 | 75 | first_digit++; |
189 | 75 | } |
190 | 4.73k | } |
191 | 3.90k | else |
192 | 3.90k | { |
193 | 3.90k | break; /* p -> char after pre-decimal digits. */ |
194 | 3.90k | } |
195 | 8.64k | } /* For each digit before decimal mark. */ |
196 | | |
197 | 9.39k | #ifndef OLD_FLOAT_READS |
198 | | /* Ignore trailing 0's after the decimal point. The original code here |
199 | | (ifdef'd out) does not do this, and numbers like |
200 | | 4.29496729600000000000e+09 (2**31) |
201 | | come out inexact for some reason related to length of the digit |
202 | | string. */ |
203 | | |
204 | | /* The case number_of_digits_before_decimal = 0 is handled for |
205 | | deleting zeros after decimal. In this case the decimal mark and |
206 | | the first zero digits after decimal mark are skipped. */ |
207 | 9.39k | seen_significant_digit = 0; |
208 | 9.39k | unsigned long subtract_decimal_exponent = 0; |
209 | | |
210 | 9.39k | if (c && IS_DECIMAL_MARK (c)) |
211 | 5.47k | { |
212 | 5.47k | unsigned int zeros = 0; /* Length of current string of zeros. */ |
213 | | |
214 | 5.47k | if (number_of_digits_before_decimal == 0) |
215 | | /* Skip decimal mark. */ |
216 | 5.35k | first_digit++; |
217 | | |
218 | 46.0k | for (p++; (c = *p) && ISDIGIT (c); p++) |
219 | 40.5k | { |
220 | 40.5k | if (c == '0') |
221 | 31.1k | { |
222 | 31.1k | if (number_of_digits_before_decimal == 0 |
223 | 31.1k | && !seen_significant_digit) |
224 | 27.9k | { |
225 | | /* Skip '0' and the decimal mark. */ |
226 | 27.9k | first_digit++; |
227 | 27.9k | subtract_decimal_exponent--; |
228 | 27.9k | } |
229 | 3.22k | else |
230 | 3.22k | zeros++; |
231 | 31.1k | } |
232 | 9.38k | else |
233 | 9.38k | { |
234 | 9.38k | seen_significant_digit = 1; |
235 | 9.38k | number_of_digits_after_decimal += 1 + zeros; |
236 | 9.38k | zeros = 0; |
237 | 9.38k | } |
238 | 40.5k | } |
239 | 5.47k | } |
240 | | #else |
241 | | if (c && IS_DECIMAL_MARK (c)) |
242 | | { |
243 | | for (p++; |
244 | | (((c = *p) != '\0') |
245 | | && (!c || !strchr (string_of_decimal_exponent_marks, c))); |
246 | | p++) |
247 | | { |
248 | | if (ISDIGIT (c)) |
249 | | { |
250 | | /* This may be retracted below. */ |
251 | | number_of_digits_after_decimal++; |
252 | | |
253 | | if ( /* seen_significant_digit || */ c > '0') |
254 | | { |
255 | | seen_significant_digit = true; |
256 | | } |
257 | | } |
258 | | else |
259 | | { |
260 | | if (!seen_significant_digit) |
261 | | { |
262 | | number_of_digits_after_decimal = 0; |
263 | | } |
264 | | break; |
265 | | } |
266 | | } /* For each digit after decimal mark. */ |
267 | | } |
268 | | |
269 | | while (number_of_digits_after_decimal |
270 | | && first_digit[number_of_digits_before_decimal |
271 | | + number_of_digits_after_decimal] == '0') |
272 | | --number_of_digits_after_decimal; |
273 | | #endif |
274 | | |
275 | 9.39k | if (flag_m68k_mri) |
276 | 0 | { |
277 | 0 | while (c == '_') |
278 | 0 | c = *++p; |
279 | 0 | } |
280 | 9.39k | if (c && strchr (string_of_decimal_exponent_marks, c)) |
281 | 4.01k | { |
282 | 4.01k | char digits_exponent_sign_char; |
283 | | |
284 | 4.01k | c = *++p; |
285 | 4.01k | if (flag_m68k_mri) |
286 | 0 | { |
287 | 0 | while (c == '_') |
288 | 0 | c = *++p; |
289 | 0 | } |
290 | 4.01k | if (c && strchr ("+-", c)) |
291 | 3.96k | { |
292 | 3.96k | digits_exponent_sign_char = c; |
293 | 3.96k | c = *++p; |
294 | 3.96k | } |
295 | 52 | else |
296 | 52 | { |
297 | 52 | digits_exponent_sign_char = '+'; |
298 | 52 | } |
299 | | |
300 | 4.42k | for (; (c); c = *++p) |
301 | 4.38k | { |
302 | 4.38k | if (ISDIGIT (c)) |
303 | 407 | { |
304 | 407 | if (decimal_exponent > LONG_MAX / 10 |
305 | 407 | || (decimal_exponent == LONG_MAX / 10 |
306 | 405 | && c > '0' + (char) (LONG_MAX - LONG_MAX / 10 * 10))) |
307 | 2 | return_value = ERROR_EXPONENT_OVERFLOW; |
308 | 407 | decimal_exponent = decimal_exponent * 10 + c - '0'; |
309 | 407 | } |
310 | 3.97k | else |
311 | 3.97k | { |
312 | 3.97k | break; |
313 | 3.97k | } |
314 | 4.38k | } |
315 | | |
316 | 4.01k | if (digits_exponent_sign_char == '-') |
317 | 3.96k | { |
318 | 3.96k | decimal_exponent = -decimal_exponent; |
319 | 3.96k | } |
320 | 4.01k | } |
321 | | |
322 | 9.39k | #ifndef OLD_FLOAT_READS |
323 | | /* Subtract_decimal_exponent != 0 when number_of_digits_before_decimal = 0 |
324 | | and first digit after decimal is '0'. */ |
325 | 9.39k | decimal_exponent += subtract_decimal_exponent; |
326 | 9.39k | #endif |
327 | | |
328 | 9.39k | *address_of_string_pointer = p; |
329 | | |
330 | 9.39k | number_of_digits_available = |
331 | 9.39k | number_of_digits_before_decimal + number_of_digits_after_decimal; |
332 | 9.39k | if (number_of_digits_available == 0) |
333 | 1.20k | { |
334 | 1.20k | address_of_generic_floating_point_number->exponent = 0; /* Not strictly necessary */ |
335 | 1.20k | address_of_generic_floating_point_number->leader |
336 | 1.20k | = -1 + address_of_generic_floating_point_number->low; |
337 | 1.20k | address_of_generic_floating_point_number->sign = digits_sign_char; |
338 | | /* We have just concocted (+/-)0.0E0 */ |
339 | | |
340 | 1.20k | } |
341 | 8.19k | else |
342 | 8.19k | { |
343 | 8.19k | int count; /* Number of useful digits left to scan. */ |
344 | | |
345 | 8.19k | LITTLENUM_TYPE *temporary_binary_low = NULL; |
346 | 8.19k | LITTLENUM_TYPE *power_binary_low = NULL; |
347 | 8.19k | LITTLENUM_TYPE *digits_binary_low; |
348 | 8.19k | unsigned int precision; |
349 | 8.19k | unsigned int maximum_useful_digits; |
350 | 8.19k | unsigned int number_of_digits_to_use; |
351 | 8.19k | unsigned int more_than_enough_bits_for_digits; |
352 | 8.19k | unsigned int more_than_enough_littlenums_for_digits; |
353 | 8.19k | unsigned int size_of_digits_in_littlenums; |
354 | 8.19k | unsigned int size_of_digits_in_chars; |
355 | 8.19k | FLONUM_TYPE power_of_10_flonum; |
356 | 8.19k | FLONUM_TYPE digits_flonum; |
357 | | |
358 | 8.19k | precision = (address_of_generic_floating_point_number->high |
359 | 8.19k | - address_of_generic_floating_point_number->low |
360 | 8.19k | + 1); /* Number of destination littlenums. */ |
361 | | |
362 | | /* precision includes two littlenums worth of guard bits, |
363 | | so this gives us 10 decimal guard digits here. */ |
364 | 8.19k | maximum_useful_digits = (precision |
365 | 8.19k | * LITTLENUM_NUMBER_OF_BITS |
366 | 8.19k | * 1000000 / 3321928 |
367 | 8.19k | + 1); /* round up. */ |
368 | | |
369 | 8.19k | if (number_of_digits_available > maximum_useful_digits) |
370 | 22 | { |
371 | 22 | number_of_digits_to_use = maximum_useful_digits; |
372 | 22 | } |
373 | 8.16k | else |
374 | 8.16k | { |
375 | 8.16k | number_of_digits_to_use = number_of_digits_available; |
376 | 8.16k | } |
377 | | |
378 | | /* Cast these to SIGNED LONG first, otherwise, on systems with |
379 | | LONG wider than INT (such as Alpha OSF/1), unsignedness may |
380 | | cause unexpected results. */ |
381 | 8.19k | decimal_exponent += ((long) number_of_digits_before_decimal |
382 | 8.19k | - (long) number_of_digits_to_use); |
383 | | |
384 | 8.19k | more_than_enough_bits_for_digits |
385 | 8.19k | = (number_of_digits_to_use * 3321928 / 1000000 + 1); |
386 | | |
387 | 8.19k | more_than_enough_littlenums_for_digits |
388 | 8.19k | = (more_than_enough_bits_for_digits |
389 | 8.19k | / LITTLENUM_NUMBER_OF_BITS) |
390 | 8.19k | + 2; |
391 | | |
392 | | /* Compute (digits) part. In "12.34E56" this is the "1234" part. |
393 | | Arithmetic is exact here. If no digits are supplied then this |
394 | | part is a 0 valued binary integer. Allocate room to build up |
395 | | the binary number as littlenums. We want this memory to |
396 | | disappear when we leave this function. Assume no alignment |
397 | | problems => (room for n objects) == n * (room for 1 |
398 | | object). */ |
399 | | |
400 | 8.19k | size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits; |
401 | 8.19k | size_of_digits_in_chars = size_of_digits_in_littlenums |
402 | 8.19k | * sizeof (LITTLENUM_TYPE); |
403 | | |
404 | 8.19k | digits_binary_low = (LITTLENUM_TYPE *) |
405 | 8.19k | xmalloc (size_of_digits_in_chars); |
406 | | |
407 | 8.19k | memset ((char *) digits_binary_low, '\0', size_of_digits_in_chars); |
408 | | |
409 | | /* Digits_binary_low[] is allocated and zeroed. */ |
410 | | |
411 | | /* |
412 | | * Parse the decimal digits as if * digits_low was in the units position. |
413 | | * Emit a binary number into digits_binary_low[]. |
414 | | * |
415 | | * Use a large-precision version of: |
416 | | * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit |
417 | | */ |
418 | | |
419 | 22.4k | for (p = first_digit, count = number_of_digits_to_use; count; p++, --count) |
420 | 14.2k | { |
421 | 14.2k | c = *p; |
422 | 14.2k | if (ISDIGIT (c)) |
423 | 14.2k | { |
424 | | /* |
425 | | * Multiply by 10. Assume can never overflow. |
426 | | * Add this digit to digits_binary_low[]. |
427 | | */ |
428 | | |
429 | 14.2k | long carry; |
430 | 14.2k | LITTLENUM_TYPE *littlenum_pointer; |
431 | 14.2k | LITTLENUM_TYPE *littlenum_limit; |
432 | | |
433 | 14.2k | littlenum_limit = digits_binary_low |
434 | 14.2k | + more_than_enough_littlenums_for_digits |
435 | 14.2k | - 1; |
436 | | |
437 | 14.2k | carry = c - '0'; /* char -> binary */ |
438 | | |
439 | 14.2k | for (littlenum_pointer = digits_binary_low; |
440 | 60.6k | littlenum_pointer <= littlenum_limit; |
441 | 46.4k | littlenum_pointer++) |
442 | 46.4k | { |
443 | 46.4k | long work; |
444 | | |
445 | 46.4k | work = carry + 10 * (long) (*littlenum_pointer); |
446 | 46.4k | *littlenum_pointer = work & LITTLENUM_MASK; |
447 | 46.4k | carry = work >> LITTLENUM_NUMBER_OF_BITS; |
448 | 46.4k | } |
449 | | |
450 | 14.2k | if (carry != 0) |
451 | 0 | { |
452 | | /* |
453 | | * We have a GROSS internal error. |
454 | | * This should never happen. |
455 | | */ |
456 | 0 | as_fatal (_("failed sanity check")); |
457 | 0 | } |
458 | 14.2k | } |
459 | 0 | else |
460 | 0 | { |
461 | 0 | ++count; /* '.' doesn't alter digits used count. */ |
462 | 0 | } |
463 | 14.2k | } |
464 | | |
465 | | /* |
466 | | * Digits_binary_low[] properly encodes the value of the digits. |
467 | | * Forget about any high-order littlenums that are 0. |
468 | | */ |
469 | 16.6k | while (digits_binary_low[size_of_digits_in_littlenums - 1] == 0 |
470 | 16.6k | && size_of_digits_in_littlenums >= 2) |
471 | 8.46k | size_of_digits_in_littlenums--; |
472 | | |
473 | 8.19k | digits_flonum.low = digits_binary_low; |
474 | 8.19k | digits_flonum.high = digits_binary_low + size_of_digits_in_littlenums - 1; |
475 | 8.19k | digits_flonum.leader = digits_flonum.high; |
476 | 8.19k | digits_flonum.exponent = 0; |
477 | | /* |
478 | | * The value of digits_flonum . sign should not be important. |
479 | | * We have already decided the output's sign. |
480 | | * We trust that the sign won't influence the other parts of the number! |
481 | | * So we give it a value for these reasons: |
482 | | * (1) courtesy to humans reading/debugging |
483 | | * these numbers so they don't get excited about strange values |
484 | | * (2) in future there may be more meaning attached to sign, |
485 | | * and what was |
486 | | * harmless noise may become disruptive, ill-conditioned (or worse) |
487 | | * input. |
488 | | */ |
489 | 8.19k | digits_flonum.sign = '+'; |
490 | | |
491 | 8.19k | { |
492 | | /* |
493 | | * Compute the mantissa (& exponent) of the power of 10. |
494 | | * If successful, then multiply the power of 10 by the digits |
495 | | * giving return_binary_mantissa and return_binary_exponent. |
496 | | */ |
497 | | |
498 | 8.19k | int decimal_exponent_is_negative; |
499 | | /* This refers to the "-56" in "12.34E-56". */ |
500 | | /* FALSE: decimal_exponent is positive (or 0) */ |
501 | | /* TRUE: decimal_exponent is negative */ |
502 | 8.19k | FLONUM_TYPE temporary_flonum; |
503 | 8.19k | unsigned int size_of_power_in_littlenums; |
504 | 8.19k | unsigned int size_of_power_in_chars; |
505 | | |
506 | 8.19k | size_of_power_in_littlenums = precision; |
507 | | /* Precision has a built-in fudge factor so we get a few guard bits. */ |
508 | | |
509 | 8.19k | decimal_exponent_is_negative = (long) decimal_exponent < 0; |
510 | 8.19k | if (decimal_exponent_is_negative) |
511 | 4.96k | { |
512 | 4.96k | decimal_exponent = -decimal_exponent; |
513 | 4.96k | } |
514 | | |
515 | | /* From now on: the decimal exponent is > 0. Its sign is separate. */ |
516 | | |
517 | 8.19k | size_of_power_in_chars = size_of_power_in_littlenums |
518 | 8.19k | * sizeof (LITTLENUM_TYPE) + 2; |
519 | | |
520 | 8.19k | power_binary_low = (LITTLENUM_TYPE *) xmalloc (size_of_power_in_chars); |
521 | 8.19k | temporary_binary_low = (LITTLENUM_TYPE *) xmalloc (size_of_power_in_chars); |
522 | | |
523 | 8.19k | memset ((char *) power_binary_low, '\0', size_of_power_in_chars); |
524 | 8.19k | *power_binary_low = 1; |
525 | 8.19k | power_of_10_flonum.exponent = 0; |
526 | 8.19k | power_of_10_flonum.low = power_binary_low; |
527 | 8.19k | power_of_10_flonum.leader = power_binary_low; |
528 | 8.19k | power_of_10_flonum.high = power_binary_low + size_of_power_in_littlenums - 1; |
529 | 8.19k | power_of_10_flonum.sign = '+'; |
530 | 8.19k | temporary_flonum.low = temporary_binary_low; |
531 | 8.19k | temporary_flonum.high = temporary_binary_low + size_of_power_in_littlenums - 1; |
532 | | /* |
533 | | * (power) == 1. |
534 | | * Space for temporary_flonum allocated. |
535 | | */ |
536 | | |
537 | | /* |
538 | | * ... |
539 | | * |
540 | | * WHILE more bits |
541 | | * DO find next bit (with place value) |
542 | | * multiply into power mantissa |
543 | | * OD |
544 | | */ |
545 | 8.19k | { |
546 | 8.19k | int place_number_limit; |
547 | | /* Any 10^(2^n) whose "n" exceeds this */ |
548 | | /* value will fall off the end of */ |
549 | | /* flonum_XXXX_powers_of_ten[]. */ |
550 | 8.19k | int place_number; |
551 | 8.19k | const FLONUM_TYPE *multiplicand; /* -> 10^(2^n) */ |
552 | | |
553 | 8.19k | place_number_limit = table_size_of_flonum_powers_of_ten; |
554 | | |
555 | 8.19k | multiplicand = (decimal_exponent_is_negative |
556 | 8.19k | ? flonum_negative_powers_of_ten |
557 | 8.19k | : flonum_positive_powers_of_ten); |
558 | | |
559 | 8.19k | for (place_number = 1;/* Place value of this bit of exponent. */ |
560 | 17.8k | decimal_exponent;/* Quit when no more 1 bits in exponent. */ |
561 | 9.63k | decimal_exponent >>= 1, place_number++) |
562 | 9.63k | { |
563 | 9.63k | if (decimal_exponent & 1) |
564 | 7.12k | { |
565 | 7.12k | if (place_number > place_number_limit) |
566 | 15 | { |
567 | | /* The decimal exponent has a magnitude so great |
568 | | that our tables can't help us fragment it. |
569 | | Although this routine is in error because it |
570 | | can't imagine a number that big, signal an |
571 | | error as if it is the user's fault for |
572 | | presenting such a big number. */ |
573 | 15 | return_value = ERROR_EXPONENT_OVERFLOW; |
574 | | /* quit out of loop gracefully */ |
575 | 15 | decimal_exponent = 0; |
576 | 15 | } |
577 | 7.11k | else |
578 | 7.11k | { |
579 | | #ifdef TRACE |
580 | | printf ("before multiply, place_number = %d., power_of_10_flonum:\n", |
581 | | place_number); |
582 | | |
583 | | flonum_print (&power_of_10_flonum); |
584 | | (void) putchar ('\n'); |
585 | | #endif |
586 | | #ifdef TRACE |
587 | | printf ("multiplier:\n"); |
588 | | flonum_print (multiplicand + place_number); |
589 | | (void) putchar ('\n'); |
590 | | #endif |
591 | 7.11k | flonum_multip (multiplicand + place_number, |
592 | 7.11k | &power_of_10_flonum, &temporary_flonum); |
593 | | #ifdef TRACE |
594 | | printf ("after multiply:\n"); |
595 | | flonum_print (&temporary_flonum); |
596 | | (void) putchar ('\n'); |
597 | | #endif |
598 | 7.11k | flonum_copy (&temporary_flonum, &power_of_10_flonum); |
599 | | #ifdef TRACE |
600 | | printf ("after copy:\n"); |
601 | | flonum_print (&power_of_10_flonum); |
602 | | (void) putchar ('\n'); |
603 | | #endif |
604 | 7.11k | } /* If this bit of decimal_exponent was computable.*/ |
605 | 7.12k | } /* If this bit of decimal_exponent was set. */ |
606 | 9.63k | } /* For each bit of binary representation of exponent */ |
607 | | #ifdef TRACE |
608 | | printf ("after computing power_of_10_flonum:\n"); |
609 | | flonum_print (&power_of_10_flonum); |
610 | | (void) putchar ('\n'); |
611 | | #endif |
612 | 8.19k | } |
613 | 8.19k | } |
614 | | |
615 | | /* |
616 | | * power_of_10_flonum is power of ten in binary (mantissa) , (exponent). |
617 | | * It may be the number 1, in which case we don't NEED to multiply. |
618 | | * |
619 | | * Multiply (decimal digits) by power_of_10_flonum. |
620 | | */ |
621 | | |
622 | 8.19k | flonum_multip (&power_of_10_flonum, &digits_flonum, address_of_generic_floating_point_number); |
623 | | /* Assert sign of the number we made is '+'. */ |
624 | 8.19k | address_of_generic_floating_point_number->sign = digits_sign_char; |
625 | | |
626 | 8.19k | free (temporary_binary_low); |
627 | 8.19k | free (power_binary_low); |
628 | 8.19k | free (digits_binary_low); |
629 | 8.19k | } |
630 | 9.39k | return return_value; |
631 | 9.39k | } |
632 | | |
633 | | #ifdef TRACE |
634 | | static void |
635 | | flonum_print (f) |
636 | | const FLONUM_TYPE *f; |
637 | | { |
638 | | LITTLENUM_TYPE *lp; |
639 | | char littlenum_format[10]; |
640 | | sprintf (littlenum_format, " %%0%dx", sizeof (LITTLENUM_TYPE) * 2); |
641 | | #define print_littlenum(LP) (printf (littlenum_format, LP)) |
642 | | printf ("flonum @%p %c e%ld", f, f->sign, f->exponent); |
643 | | if (f->low < f->high) |
644 | | for (lp = f->high; lp >= f->low; lp--) |
645 | | print_littlenum (*lp); |
646 | | else |
647 | | for (lp = f->low; lp <= f->high; lp++) |
648 | | print_littlenum (*lp); |
649 | | printf ("\n"); |
650 | | fflush (stdout); |
651 | | } |
652 | | #endif |
653 | | |
654 | | /* end of atof_generic.c */ |