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