/src/binutils-gdb/gas/atof-generic.c
Line | Count | Source |
1 | | /* atof_generic.c - turn a string of digits into a Flonum |
2 | | Copyright (C) 1987-2026 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 | 893 | { |
76 | 893 | int return_value = 0; /* 0 means OK. */ |
77 | 893 | char *first_digit; |
78 | 893 | unsigned int number_of_digits_before_decimal; |
79 | 893 | unsigned int number_of_digits_after_decimal; |
80 | 893 | unsigned long decimal_exponent; |
81 | 893 | unsigned int number_of_digits_available; |
82 | 893 | 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 | 893 | char *p; |
93 | 893 | char c; |
94 | 893 | int seen_significant_digit; |
95 | | |
96 | 893 | #ifdef ASSUME_DECIMAL_MARK_IS_DOT |
97 | 893 | gas_assert (string_of_decimal_marks[0] == '.' |
98 | 893 | && string_of_decimal_marks[1] == 0); |
99 | 2.19k | #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 | 893 | first_digit = *address_of_string_pointer; |
105 | 893 | c = *first_digit; |
106 | | |
107 | 893 | if (c == '-' || c == '+') |
108 | 302 | { |
109 | 302 | digits_sign_char = c; |
110 | 302 | first_digit++; |
111 | 302 | } |
112 | 591 | else |
113 | 591 | digits_sign_char = '+'; |
114 | | |
115 | 893 | switch (first_digit[0]) |
116 | 893 | { |
117 | 4 | case 's': |
118 | 5 | case 'S': |
119 | 6 | case 'q': |
120 | 6 | case 'Q': |
121 | 6 | if (!strncasecmp ("nan", first_digit + 1, 3)) |
122 | 3 | { |
123 | 3 | address_of_generic_floating_point_number->sign = |
124 | 3 | digits_sign_char == '+' ? TOUPPER (first_digit[0]) |
125 | 3 | : TOLOWER (first_digit[0]); |
126 | 3 | address_of_generic_floating_point_number->exponent = 0; |
127 | 3 | address_of_generic_floating_point_number->leader = |
128 | 3 | address_of_generic_floating_point_number->low; |
129 | 3 | *address_of_string_pointer = first_digit + 4; |
130 | 3 | return 0; |
131 | 3 | } |
132 | 3 | break; |
133 | | |
134 | 3 | case 'n': |
135 | 0 | case 'N': |
136 | 0 | 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 | 0 | break; |
147 | | |
148 | 9 | case 'i': |
149 | 9 | case 'I': |
150 | 9 | if (!strncasecmp ("inf", first_digit, 3)) |
151 | 9 | { |
152 | 9 | address_of_generic_floating_point_number->sign = |
153 | 9 | digits_sign_char == '+' ? 'P' : 'N'; |
154 | 9 | address_of_generic_floating_point_number->exponent = 0; |
155 | 9 | address_of_generic_floating_point_number->leader = |
156 | 9 | address_of_generic_floating_point_number->low; |
157 | | |
158 | 9 | first_digit += 3; |
159 | 9 | if (!strncasecmp ("inity", first_digit, 5)) |
160 | 0 | first_digit += 5; |
161 | | |
162 | 9 | *address_of_string_pointer = first_digit; |
163 | | |
164 | 9 | return 0; |
165 | 9 | } |
166 | 0 | break; |
167 | 893 | } |
168 | | |
169 | 881 | number_of_digits_before_decimal = 0; |
170 | 881 | number_of_digits_after_decimal = 0; |
171 | 881 | decimal_exponent = 0; |
172 | 881 | seen_significant_digit = 0; |
173 | 881 | for (p = first_digit; |
174 | 1.32k | (((c = *p) != '\0') |
175 | 1.31k | && (!c || !IS_DECIMAL_MARK (c)) |
176 | 1.28k | && (!c || !strchr (string_of_decimal_exponent_marks, c))); |
177 | 881 | p++) |
178 | 1.28k | { |
179 | 1.28k | if (ISDIGIT (c)) |
180 | 440 | { |
181 | 440 | if (seen_significant_digit || c > '0') |
182 | 157 | { |
183 | 157 | ++number_of_digits_before_decimal; |
184 | 157 | seen_significant_digit = 1; |
185 | 157 | } |
186 | 283 | else |
187 | 283 | { |
188 | 283 | first_digit++; |
189 | 283 | } |
190 | 440 | } |
191 | 840 | else |
192 | 840 | { |
193 | 840 | break; /* p -> char after pre-decimal digits. */ |
194 | 840 | } |
195 | 1.28k | } /* For each digit before decimal mark. */ |
196 | | |
197 | 881 | #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 | 881 | seen_significant_digit = 0; |
208 | 881 | unsigned long subtract_decimal_exponent = 0; |
209 | | |
210 | 881 | if (c && IS_DECIMAL_MARK (c)) |
211 | 38 | { |
212 | 38 | unsigned int zeros = 0; /* Length of current string of zeros. */ |
213 | | |
214 | 38 | if (number_of_digits_before_decimal == 0) |
215 | | /* Skip decimal mark. */ |
216 | 36 | first_digit++; |
217 | | |
218 | 608 | for (p++; (c = *p) && ISDIGIT (c); p++) |
219 | 570 | { |
220 | 570 | if (c == '0') |
221 | 440 | { |
222 | 440 | if (number_of_digits_before_decimal == 0 |
223 | 440 | && !seen_significant_digit) |
224 | 427 | { |
225 | | /* Skip '0' and the decimal mark. */ |
226 | 427 | first_digit++; |
227 | 427 | subtract_decimal_exponent--; |
228 | 427 | } |
229 | 13 | else |
230 | 13 | zeros++; |
231 | 440 | } |
232 | 130 | else |
233 | 130 | { |
234 | 130 | seen_significant_digit = 1; |
235 | 130 | number_of_digits_after_decimal += 1 + zeros; |
236 | 130 | zeros = 0; |
237 | 130 | } |
238 | 570 | } |
239 | 38 | } |
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 | 881 | if (flag_m68k_mri) |
276 | 0 | { |
277 | 0 | while (c == '_') |
278 | 0 | c = *++p; |
279 | 0 | } |
280 | 881 | if (c && strchr (string_of_decimal_exponent_marks, c)) |
281 | 16 | { |
282 | 16 | char digits_exponent_sign_char; |
283 | | |
284 | 16 | c = *++p; |
285 | 16 | if (flag_m68k_mri) |
286 | 0 | { |
287 | 0 | while (c == '_') |
288 | 0 | c = *++p; |
289 | 0 | } |
290 | 16 | if (c && strchr ("+-", c)) |
291 | 9 | { |
292 | 9 | digits_exponent_sign_char = c; |
293 | 9 | c = *++p; |
294 | 9 | } |
295 | 7 | else |
296 | 7 | { |
297 | 7 | digits_exponent_sign_char = '+'; |
298 | 7 | } |
299 | | |
300 | 104 | for (; (c); c = *++p) |
301 | 90 | { |
302 | 90 | if (ISDIGIT (c)) |
303 | 88 | { |
304 | 88 | if (decimal_exponent > LONG_MAX / 10 |
305 | 79 | || (decimal_exponent == LONG_MAX / 10 |
306 | 2 | && c > '0' + (LONG_MAX - LONG_MAX / 10 * 10))) |
307 | 9 | return_value = ERROR_EXPONENT_OVERFLOW; |
308 | 88 | decimal_exponent = decimal_exponent * 10 + c - '0'; |
309 | 88 | } |
310 | 2 | else |
311 | 2 | { |
312 | 2 | break; |
313 | 2 | } |
314 | 90 | } |
315 | | |
316 | 16 | if (digits_exponent_sign_char == '-') |
317 | 9 | { |
318 | 9 | decimal_exponent = -decimal_exponent; |
319 | 9 | } |
320 | 16 | } |
321 | | |
322 | 881 | #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 | 881 | decimal_exponent += subtract_decimal_exponent; |
326 | 881 | #endif |
327 | | |
328 | 881 | *address_of_string_pointer = p; |
329 | | |
330 | 881 | number_of_digits_available = |
331 | 881 | number_of_digits_before_decimal + number_of_digits_after_decimal; |
332 | 881 | if (number_of_digits_available == 0) |
333 | 829 | { |
334 | 829 | address_of_generic_floating_point_number->exponent = 0; /* Not strictly necessary */ |
335 | 829 | address_of_generic_floating_point_number->leader |
336 | 829 | = -1 + address_of_generic_floating_point_number->low; |
337 | 829 | address_of_generic_floating_point_number->sign = digits_sign_char; |
338 | | /* We have just concocted (+/-)0.0E0 */ |
339 | | |
340 | 829 | } |
341 | 52 | else |
342 | 52 | { |
343 | 52 | int count; /* Number of useful digits left to scan. */ |
344 | | |
345 | 52 | LITTLENUM_TYPE *temporary_binary_low = NULL; |
346 | 52 | LITTLENUM_TYPE *power_binary_low = NULL; |
347 | 52 | LITTLENUM_TYPE *digits_binary_low; |
348 | 52 | unsigned int precision; |
349 | 52 | unsigned int maximum_useful_digits; |
350 | 52 | unsigned int number_of_digits_to_use; |
351 | 52 | unsigned int more_than_enough_bits_for_digits; |
352 | 52 | unsigned int more_than_enough_littlenums_for_digits; |
353 | 52 | unsigned int size_of_digits_in_littlenums; |
354 | 52 | FLONUM_TYPE power_of_10_flonum; |
355 | 52 | FLONUM_TYPE digits_flonum; |
356 | | |
357 | 52 | precision = (address_of_generic_floating_point_number->high |
358 | 52 | - address_of_generic_floating_point_number->low |
359 | 52 | + 1); /* Number of destination littlenums. */ |
360 | | |
361 | | /* precision includes two littlenums worth of guard bits, |
362 | | so this gives us 10 decimal guard digits here. */ |
363 | 52 | maximum_useful_digits = (precision |
364 | 52 | * LITTLENUM_NUMBER_OF_BITS |
365 | 52 | * 1000000 / 3321928 |
366 | 52 | + 1); /* round up. */ |
367 | | |
368 | 52 | if (number_of_digits_available > maximum_useful_digits) |
369 | 4 | { |
370 | 4 | number_of_digits_to_use = maximum_useful_digits; |
371 | 4 | } |
372 | 48 | else |
373 | 48 | { |
374 | 48 | number_of_digits_to_use = number_of_digits_available; |
375 | 48 | } |
376 | | |
377 | 52 | decimal_exponent += number_of_digits_before_decimal; |
378 | 52 | decimal_exponent -= number_of_digits_to_use; |
379 | | |
380 | 52 | more_than_enough_bits_for_digits |
381 | 52 | = (number_of_digits_to_use * 3321928 / 1000000 + 1); |
382 | | |
383 | 52 | more_than_enough_littlenums_for_digits |
384 | 52 | = (more_than_enough_bits_for_digits |
385 | 52 | / LITTLENUM_NUMBER_OF_BITS) |
386 | 52 | + 2; |
387 | | |
388 | | /* Compute (digits) part. In "12.34E56" this is the "1234" part. |
389 | | Arithmetic is exact here. If no digits are supplied then this |
390 | | part is a 0 valued binary integer. Allocate room to build up |
391 | | the binary number as littlenums. We want this memory to |
392 | | disappear when we leave this function. Assume no alignment |
393 | | problems => (room for n objects) == n * (room for 1 |
394 | | object). */ |
395 | | |
396 | 52 | size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits; |
397 | | |
398 | 52 | digits_binary_low = xcalloc (size_of_digits_in_littlenums, |
399 | 52 | sizeof (LITTLENUM_TYPE)); |
400 | | |
401 | | /* Digits_binary_low[] is allocated and zeroed. */ |
402 | | |
403 | | /* |
404 | | * Parse the decimal digits as if * digits_low was in the units position. |
405 | | * Emit a binary number into digits_binary_low[]. |
406 | | * |
407 | | * Use a large-precision version of: |
408 | | * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit |
409 | | */ |
410 | | |
411 | 331 | for (p = first_digit, count = number_of_digits_to_use; count; p++, --count) |
412 | 279 | { |
413 | 279 | c = *p; |
414 | 279 | if (ISDIGIT (c)) |
415 | 279 | { |
416 | | /* |
417 | | * Multiply by 10. Assume can never overflow. |
418 | | * Add this digit to digits_binary_low[]. |
419 | | */ |
420 | | |
421 | 279 | long carry; |
422 | 279 | LITTLENUM_TYPE *littlenum_pointer; |
423 | 279 | LITTLENUM_TYPE *littlenum_limit; |
424 | | |
425 | 279 | littlenum_limit = digits_binary_low |
426 | 279 | + more_than_enough_littlenums_for_digits |
427 | 279 | - 1; |
428 | | |
429 | 279 | carry = c - '0'; /* char -> binary */ |
430 | | |
431 | 279 | for (littlenum_pointer = digits_binary_low; |
432 | 1.38k | littlenum_pointer <= littlenum_limit; |
433 | 1.10k | littlenum_pointer++) |
434 | 1.10k | { |
435 | 1.10k | long work; |
436 | | |
437 | 1.10k | work = carry + 10 * (long) (*littlenum_pointer); |
438 | 1.10k | *littlenum_pointer = work & LITTLENUM_MASK; |
439 | 1.10k | carry = work >> LITTLENUM_NUMBER_OF_BITS; |
440 | 1.10k | } |
441 | | |
442 | 279 | if (carry != 0) |
443 | 0 | { |
444 | | /* |
445 | | * We have a GROSS internal error. |
446 | | * This should never happen. |
447 | | */ |
448 | 0 | as_fatal (_("failed sanity check")); |
449 | 0 | } |
450 | 279 | } |
451 | 0 | else |
452 | 0 | { |
453 | 0 | ++count; /* '.' doesn't alter digits used count. */ |
454 | 0 | } |
455 | 279 | } |
456 | | |
457 | | /* |
458 | | * Digits_binary_low[] properly encodes the value of the digits. |
459 | | * Forget about any high-order littlenums that are 0. |
460 | | */ |
461 | 119 | while (digits_binary_low[size_of_digits_in_littlenums - 1] == 0 |
462 | 67 | && size_of_digits_in_littlenums >= 2) |
463 | 67 | size_of_digits_in_littlenums--; |
464 | | |
465 | 52 | digits_flonum.low = digits_binary_low; |
466 | 52 | digits_flonum.high = digits_binary_low + size_of_digits_in_littlenums - 1; |
467 | 52 | digits_flonum.leader = digits_flonum.high; |
468 | 52 | digits_flonum.exponent = 0; |
469 | | /* |
470 | | * The value of digits_flonum . sign should not be important. |
471 | | * We have already decided the output's sign. |
472 | | * We trust that the sign won't influence the other parts of the number! |
473 | | * So we give it a value for these reasons: |
474 | | * (1) courtesy to humans reading/debugging |
475 | | * these numbers so they don't get excited about strange values |
476 | | * (2) in future there may be more meaning attached to sign, |
477 | | * and what was |
478 | | * harmless noise may become disruptive, ill-conditioned (or worse) |
479 | | * input. |
480 | | */ |
481 | 52 | digits_flonum.sign = '+'; |
482 | | |
483 | 52 | { |
484 | | /* |
485 | | * Compute the mantissa (& exponent) of the power of 10. |
486 | | * If successful, then multiply the power of 10 by the digits |
487 | | * giving return_binary_mantissa and return_binary_exponent. |
488 | | */ |
489 | | |
490 | 52 | int decimal_exponent_is_negative; |
491 | | /* This refers to the "-56" in "12.34E-56". */ |
492 | | /* FALSE: decimal_exponent is positive (or 0) */ |
493 | | /* TRUE: decimal_exponent is negative */ |
494 | 52 | FLONUM_TYPE temporary_flonum; |
495 | 52 | unsigned int size_of_power_in_littlenums; |
496 | 52 | unsigned int size_of_power_in_chars; |
497 | | |
498 | 52 | size_of_power_in_littlenums = precision; |
499 | | /* Precision has a built-in fudge factor so we get a few guard bits. */ |
500 | | |
501 | 52 | decimal_exponent_is_negative = (long) decimal_exponent < 0; |
502 | 52 | if (decimal_exponent_is_negative) |
503 | 19 | { |
504 | 19 | decimal_exponent = -decimal_exponent; |
505 | 19 | } |
506 | | |
507 | | /* From now on: the decimal exponent is > 0. Its sign is separate. */ |
508 | | |
509 | 52 | size_of_power_in_chars = (size_of_power_in_littlenums |
510 | 52 | * sizeof (LITTLENUM_TYPE)) + 2; |
511 | | |
512 | 52 | power_binary_low = xmalloc (size_of_power_in_chars); |
513 | 52 | temporary_binary_low = xmalloc (size_of_power_in_chars); |
514 | | |
515 | 52 | memset (power_binary_low, '\0', size_of_power_in_chars); |
516 | 52 | *power_binary_low = 1; |
517 | 52 | power_of_10_flonum.exponent = 0; |
518 | 52 | power_of_10_flonum.low = power_binary_low; |
519 | 52 | power_of_10_flonum.leader = power_binary_low; |
520 | 52 | power_of_10_flonum.high = power_binary_low + size_of_power_in_littlenums - 1; |
521 | 52 | power_of_10_flonum.sign = '+'; |
522 | 52 | temporary_flonum.low = temporary_binary_low; |
523 | 52 | temporary_flonum.high = temporary_binary_low + size_of_power_in_littlenums - 1; |
524 | | /* |
525 | | * (power) == 1. |
526 | | * Space for temporary_flonum allocated. |
527 | | */ |
528 | | |
529 | | /* |
530 | | * ... |
531 | | * |
532 | | * WHILE more bits |
533 | | * DO find next bit (with place value) |
534 | | * multiply into power mantissa |
535 | | * OD |
536 | | */ |
537 | 52 | { |
538 | 52 | int place_number_limit; |
539 | | /* Any 10^(2^n) whose "n" exceeds this */ |
540 | | /* value will fall off the end of */ |
541 | | /* flonum_XXXX_powers_of_ten[]. */ |
542 | 52 | int place_number; |
543 | 52 | const FLONUM_TYPE *multiplicand; /* -> 10^(2^n) */ |
544 | | |
545 | 52 | place_number_limit = table_size_of_flonum_powers_of_ten; |
546 | | |
547 | 52 | multiplicand = (decimal_exponent_is_negative |
548 | 52 | ? flonum_negative_powers_of_ten |
549 | 52 | : flonum_positive_powers_of_ten); |
550 | | |
551 | 52 | for (place_number = 1;/* Place value of this bit of exponent. */ |
552 | 114 | decimal_exponent;/* Quit when no more 1 bits in exponent. */ |
553 | 62 | decimal_exponent >>= 1, place_number++) |
554 | 62 | { |
555 | 62 | if (decimal_exponent & 1) |
556 | 44 | { |
557 | 44 | if (place_number > place_number_limit) |
558 | 0 | { |
559 | | /* The decimal exponent has a magnitude so great |
560 | | that our tables can't help us fragment it. |
561 | | Although this routine is in error because it |
562 | | can't imagine a number that big, signal an |
563 | | error as if it is the user's fault for |
564 | | presenting such a big number. */ |
565 | 0 | return_value = ERROR_EXPONENT_OVERFLOW; |
566 | | /* quit out of loop gracefully */ |
567 | 0 | decimal_exponent = 0; |
568 | 0 | } |
569 | 44 | else |
570 | 44 | { |
571 | | #ifdef TRACE |
572 | | printf ("before multiply, place_number = %d., power_of_10_flonum:\n", |
573 | | place_number); |
574 | | |
575 | | flonum_print (&power_of_10_flonum); |
576 | | (void) putchar ('\n'); |
577 | | #endif |
578 | | #ifdef TRACE |
579 | | printf ("multiplier:\n"); |
580 | | flonum_print (multiplicand + place_number); |
581 | | (void) putchar ('\n'); |
582 | | #endif |
583 | 44 | flonum_multip (multiplicand + place_number, |
584 | 44 | &power_of_10_flonum, &temporary_flonum); |
585 | | #ifdef TRACE |
586 | | printf ("after multiply:\n"); |
587 | | flonum_print (&temporary_flonum); |
588 | | (void) putchar ('\n'); |
589 | | #endif |
590 | 44 | flonum_copy (&temporary_flonum, &power_of_10_flonum); |
591 | | #ifdef TRACE |
592 | | printf ("after copy:\n"); |
593 | | flonum_print (&power_of_10_flonum); |
594 | | (void) putchar ('\n'); |
595 | | #endif |
596 | 44 | } /* If this bit of decimal_exponent was computable.*/ |
597 | 44 | } /* If this bit of decimal_exponent was set. */ |
598 | 62 | } /* For each bit of binary representation of exponent */ |
599 | | #ifdef TRACE |
600 | | printf ("after computing power_of_10_flonum:\n"); |
601 | | flonum_print (&power_of_10_flonum); |
602 | | (void) putchar ('\n'); |
603 | | #endif |
604 | 52 | } |
605 | 52 | } |
606 | | |
607 | | /* |
608 | | * power_of_10_flonum is power of ten in binary (mantissa) , (exponent). |
609 | | * It may be the number 1, in which case we don't NEED to multiply. |
610 | | * |
611 | | * Multiply (decimal digits) by power_of_10_flonum. |
612 | | */ |
613 | | |
614 | 52 | flonum_multip (&power_of_10_flonum, &digits_flonum, address_of_generic_floating_point_number); |
615 | | /* Assert sign of the number we made is '+'. */ |
616 | 52 | address_of_generic_floating_point_number->sign = digits_sign_char; |
617 | | |
618 | 52 | free (temporary_binary_low); |
619 | 52 | free (power_binary_low); |
620 | 52 | free (digits_binary_low); |
621 | 52 | } |
622 | 881 | return return_value; |
623 | 881 | } |
624 | | |
625 | | #ifdef TRACE |
626 | | static void |
627 | | flonum_print (const FLONUM_TYPE *f) |
628 | | { |
629 | | LITTLENUM_TYPE *lp; |
630 | | char littlenum_format[10]; |
631 | | sprintf (littlenum_format, " %%0%dx", sizeof (LITTLENUM_TYPE) * 2); |
632 | | #define print_littlenum(LP) (printf (littlenum_format, LP)) |
633 | | printf ("flonum @%p %c e%ld", f, f->sign, f->exponent); |
634 | | if (f->low < f->high) |
635 | | for (lp = f->high; lp >= f->low; lp--) |
636 | | print_littlenum (*lp); |
637 | | else |
638 | | for (lp = f->low; lp <= f->high; lp++) |
639 | | print_littlenum (*lp); |
640 | | printf ("\n"); |
641 | | fflush (stdout); |
642 | | } |
643 | | #endif |
644 | | |
645 | | /* end of atof_generic.c */ |