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