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