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