]> Git Repo - binutils.git/blob - gas/atof-generic.c
* config/obj-coffbfd.c (fixup_segment): If TC_M88K, don't adjust
[binutils.git] / gas / 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 #include <ctype.h>
21 #include <string.h>
22
23 #include "as.h"
24
25 #ifdef __GNUC__
26 #define alloca __builtin_alloca
27 #else
28 #ifdef sparc
29 #include <alloca.h>
30 #endif
31 #endif
32
33 #ifdef USG
34 #define bzero(s,n) memset(s,0,n)
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         if ((first_digit[0] == 'i' || first_digit[0] == 'I') 
131             && (first_digit[1] == 'n' || first_digit[1] == 'N')
132             && (first_digit[2] == 'f' || first_digit[2] == 'F')) {
133                 address_of_generic_floating_point_number->sign =
134                     digits_sign_char == '+' ? 'P' : 'N';
135                 address_of_generic_floating_point_number->exponent = 0;
136                 address_of_generic_floating_point_number->leader =
137                     address_of_generic_floating_point_number->low;
138                 
139                 if ((first_digit[3] == 'i'
140                      || first_digit[3] == 'I')
141                     && (first_digit[4] == 'n'
142                         || first_digit[4] == 'N')
143                     && (first_digit[5] == 'i'
144                         || first_digit[5] == 'I')
145                     && (first_digit[6] == 't'
146                         || first_digit[6] == 'T')
147                     && (first_digit[7] == 'y'
148                         || first_digit[7] == 'Y')) {
149                         *address_of_string_pointer = first_digit + 8;
150                 } else {
151                         *address_of_string_pointer = first_digit + 3;
152                 }
153                 return(0);
154         }
155         
156         number_of_digits_before_decimal = 0;
157         number_of_digits_after_decimal = 0;
158         decimal_exponent = 0;
159         seen_significant_digit = 0;
160         for (p = first_digit; (((c = * p) != '\0')
161                                && (!c || ! strchr(string_of_decimal_marks, c))
162                                && (!c || !strchr(string_of_decimal_exponent_marks, c)));
163              p++) {
164                 if (isdigit(c)) {
165                         if (seen_significant_digit || c > '0') {
166                                 ++number_of_digits_before_decimal;
167                                 seen_significant_digit = 1;
168                         } else {
169                                 first_digit++;
170                         }
171                 } else {
172                         break; /* p -> char after pre-decimal digits. */
173                 }
174         } /* For each digit before decimal mark. */
175         
176 #ifndef OLD_FLOAT_READS
177         /* Ignore trailing 0's after the decimal point.  The original code here
178          * (ifdef'd out) does not do this, and numbers like
179          *      4.29496729600000000000e+09      (2**31)
180          * come out inexact for some reason related to length of the digit
181          * string.
182          */
183         if (c && strchr(string_of_decimal_marks, c)) {
184                 int zeros = 0;  /* Length of current string of zeros */
185                 
186                 for (p++; (c = *p) && isdigit(c); p++) {
187                         if (c == '0') {
188                                 zeros++;
189                         } else {
190                                 number_of_digits_after_decimal += 1 + zeros;
191                                 zeros = 0;
192                         }
193                 }
194         }
195 #else
196         if (c && strchr(string_of_decimal_marks, c)) {
197                 for (p++; (((c = *p) != '\0')
198                            && (!c || !strchr(string_of_decimal_exponent_marks, c)));
199                      p++) {
200                         if (isdigit(c)) {
201                                 number_of_digits_after_decimal++; /* This may be retracted below. */
202                                 if (/* seen_significant_digit || */ c > '0') {
203                                         seen_significant_digit = TRUE;
204                                 }
205                         } else {
206                                 if (!seen_significant_digit) {
207                                         number_of_digits_after_decimal = 0;
208                                 }
209                                 break;
210                         }
211                 } /* For each digit after decimal mark. */
212         }
213         
214         while (number_of_digits_after_decimal && first_digit[number_of_digits_before_decimal
215                                                              + number_of_digits_after_decimal] == '0')
216             --number_of_digits_after_decimal;
217         /* last_digit = p; JF unused */
218 #endif
219         
220         if (c && strchr(string_of_decimal_exponent_marks, c) ) {
221                 char digits_exponent_sign_char;
222                 
223                 c = *++p;
224                 if (c && strchr ("+-",c)) {
225                         digits_exponent_sign_char = c;
226                         c = *++p;
227                 } else {
228                         digits_exponent_sign_char = '+';
229                 }
230                 
231                 for ( ; (c); c = *++p) {
232                         if (isdigit(c)) {
233                                 decimal_exponent = decimal_exponent * 10 + c - '0';
234                                 /*
235                                  * BUG! If we overflow here, we lose!
236                                  */
237                         } else {
238                                 break;
239                         }
240                 }
241                 
242                 if (digits_exponent_sign_char == '-') {
243                         decimal_exponent = -decimal_exponent;
244                 }
245         }
246         
247         *address_of_string_pointer = p;
248
249
250         
251         number_of_digits_available =
252             number_of_digits_before_decimal + number_of_digits_after_decimal;
253         return_value = 0;
254         if (number_of_digits_available == 0) {
255                 address_of_generic_floating_point_number->exponent = 0; /* Not strictly necessary */
256                 address_of_generic_floating_point_number->leader
257                     = -1 + address_of_generic_floating_point_number->low;
258                 address_of_generic_floating_point_number->sign = digits_sign_char;
259                 /* We have just concocted (+/-)0.0E0 */
260
261         } else {
262                 int count;      /* Number of useful digits left to scan. */
263                 
264                 LITTLENUM_TYPE *digits_binary_low;
265                 int precision;
266                 int maximum_useful_digits;
267                 int number_of_digits_to_use;
268                 int more_than_enough_bits_for_digits;
269                 int more_than_enough_littlenums_for_digits;
270                 int size_of_digits_in_littlenums;
271                 int size_of_digits_in_chars;
272                 FLONUM_TYPE power_of_10_flonum;
273                 FLONUM_TYPE digits_flonum;
274                 
275                 precision = (address_of_generic_floating_point_number->high
276                              - address_of_generic_floating_point_number->low
277                              + 1); /* Number of destination littlenums. */
278                 
279                 /* Includes guard bits (two littlenums worth) */
280                 maximum_useful_digits = (((double) (precision - 2))
281                                          * ((double) (LITTLENUM_NUMBER_OF_BITS))
282                                          / (LOG_TO_BASE_2_OF_10))
283                     + 2; /* 2 :: guard digits. */
284                 
285                 if (number_of_digits_available > maximum_useful_digits) {
286                         number_of_digits_to_use = maximum_useful_digits;
287                 } else {
288                         number_of_digits_to_use = number_of_digits_available;
289                 }
290                 
291                 decimal_exponent += number_of_digits_before_decimal - number_of_digits_to_use;
292                 
293                 more_than_enough_bits_for_digits
294                     = ((((double)number_of_digits_to_use) * LOG_TO_BASE_2_OF_10) + 1);
295                 
296                 more_than_enough_littlenums_for_digits
297                     = (more_than_enough_bits_for_digits
298                        / LITTLENUM_NUMBER_OF_BITS)
299                         + 2;
300                 
301                 /*
302                  * Compute (digits) part. In "12.34E56" this is the "1234" part.
303                  * Arithmetic is exact here. If no digits are supplied then
304                  * this part is a 0 valued binary integer.
305                  * Allocate room to build up the binary number as littlenums.
306                  * We want this memory to disappear when we leave this function.
307                  * Assume no alignment problems => (room for n objects) ==
308                  * n * (room for 1 object).
309                  */
310                 
311                 size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits;
312                 size_of_digits_in_chars = size_of_digits_in_littlenums
313                     * sizeof(LITTLENUM_TYPE);
314                 
315                 digits_binary_low = (LITTLENUM_TYPE *)
316                     alloca(size_of_digits_in_chars);
317                 
318                 bzero((char *)digits_binary_low, size_of_digits_in_chars);
319                 
320                 /* Digits_binary_low[] is allocated and zeroed. */
321                 
322                 /*
323                  * Parse the decimal digits as if * digits_low was in the units position.
324                  * Emit a binary number into digits_binary_low[].
325                  *
326                  * Use a large-precision version of:
327                  * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit
328                  */
329                 
330                 for (p = first_digit, count = number_of_digits_to_use; count; p++,  --count) {
331                         c = *p;
332                         if (isdigit(c)) {
333                                 /*
334                                  * Multiply by 10. Assume can never overflow.
335                                  * Add this digit to digits_binary_low[].
336                                  */
337                                 
338                                 long carry;
339                                 LITTLENUM_TYPE *littlenum_pointer;
340                                 LITTLENUM_TYPE *littlenum_limit;
341                                 
342                                 littlenum_limit = digits_binary_low
343                                     + more_than_enough_littlenums_for_digits
344                                         - 1;
345
346                                 carry = c - '0'; /* char -> binary */
347
348                                 for (littlenum_pointer = digits_binary_low;
349                                      littlenum_pointer <= littlenum_limit;
350                                      littlenum_pointer++) {
351                                         long work;
352                                         
353                                         work = carry + 10 * (long) (*littlenum_pointer);
354                                         *littlenum_pointer = work & LITTLENUM_MASK;
355                                         carry = work >> LITTLENUM_NUMBER_OF_BITS;
356                                 }
357
358                                 if (carry != 0) {
359                                         /*
360                                          * We have a GROSS internal error.
361                                          * This should never happen.
362                                          */
363                                         as_fatal("failed sanity check.");       /* RMS prefers abort() to any message. */
364                                 }
365                         } else {
366                                 ++ count;       /* '.' doesn't alter digits used count. */
367                         } /* if valid digit */
368                 } /* for each digit */
369                 
370                 
371                 /*
372                  * Digits_binary_low[] properly encodes the value of the digits.
373                  * Forget about any high-order littlenums that are 0.
374                  */
375                 while (digits_binary_low[size_of_digits_in_littlenums - 1] == 0
376                        && size_of_digits_in_littlenums >= 2)
377                     size_of_digits_in_littlenums--;
378                 
379                 digits_flonum.low       = digits_binary_low;
380                 digits_flonum.high      = digits_binary_low + size_of_digits_in_littlenums - 1;
381                 digits_flonum.leader    = digits_flonum.high;
382                 digits_flonum.exponent = 0;
383                 /*
384                  * The value of digits_flonum . sign should not be important.
385                  * We have already decided the output's sign.
386                  * We trust that the sign won't influence the other parts of the number!
387                  * So we give it a value for these reasons:
388                  * (1) courtesy to humans reading/debugging
389                  *     these numbers so they don't get excited about strange values
390                  * (2) in future there may be more meaning attached to sign,
391                  *     and what was
392                  *     harmless noise may become disruptive, ill-conditioned (or worse)
393                  *     input.
394                  */
395                 digits_flonum.sign = '+';
396                 
397                 {
398                         /*
399                          * Compute the mantssa (& exponent) of the power of 10.
400                          * If sucessful, then multiply the power of 10 by the digits
401                          * giving return_binary_mantissa and return_binary_exponent.
402                          */
403                         
404                         LITTLENUM_TYPE *power_binary_low;
405                         int decimal_exponent_is_negative;
406                         /* This refers to the "-56" in "12.34E-56". */
407                         /* FALSE: decimal_exponent is positive (or 0) */
408                         /* TRUE:  decimal_exponent is negative */
409                         FLONUM_TYPE temporary_flonum;
410                         LITTLENUM_TYPE *temporary_binary_low;
411                         int size_of_power_in_littlenums;
412                         int size_of_power_in_chars;
413                         
414                         size_of_power_in_littlenums = precision;
415                         /* Precision has a built-in fudge factor so we get a few guard bits. */
416                         
417                         decimal_exponent_is_negative = decimal_exponent < 0;
418                         if (decimal_exponent_is_negative) {
419                                 decimal_exponent = -decimal_exponent;
420                         }
421
422                         /* From now on: the decimal exponent is > 0. Its sign is seperate. */
423                         
424                         size_of_power_in_chars = size_of_power_in_littlenums
425                             * sizeof(LITTLENUM_TYPE) + 2;
426
427                         power_binary_low = (LITTLENUM_TYPE *) alloca(size_of_power_in_chars);
428                         temporary_binary_low = (LITTLENUM_TYPE *) alloca(size_of_power_in_chars);
429                         bzero((char *)power_binary_low, size_of_power_in_chars);
430                         * power_binary_low = 1;
431                         power_of_10_flonum.exponent = 0;
432                         power_of_10_flonum.low = power_binary_low;
433                         power_of_10_flonum.leader = power_binary_low;
434                         power_of_10_flonum.high = power_binary_low + size_of_power_in_littlenums - 1;
435                         power_of_10_flonum.sign = '+';
436                         temporary_flonum.low = temporary_binary_low;
437                         temporary_flonum.high = temporary_binary_low + size_of_power_in_littlenums - 1;
438                         /*
439                          * (power) == 1.
440                          * Space for temporary_flonum allocated.
441                          */
442                         
443                         /*
444                          * ...
445                          *
446                          * WHILE        more bits
447                          * DO   find next bit (with place value)
448                          *      multiply into power mantissa
449                          * OD
450                          */
451                         {
452                                 int place_number_limit;
453                                 /* Any 10^(2^n) whose "n" exceeds this */
454                                 /* value will fall off the end of */
455                                 /* flonum_XXXX_powers_of_ten[]. */
456                                 int place_number;
457                                 const FLONUM_TYPE *multiplicand; /* -> 10^(2^n) */
458                                 
459                                 place_number_limit = table_size_of_flonum_powers_of_ten;
460
461                                 multiplicand = (decimal_exponent_is_negative
462                                                 ? flonum_negative_powers_of_ten
463                                                 : flonum_positive_powers_of_ten);
464
465                                 for (place_number = 1;  /* Place value of this bit of exponent. */
466                                      decimal_exponent;  /* Quit when no more 1 bits in exponent. */
467                                      decimal_exponent >>= 1, place_number++) {
468                                         if (decimal_exponent & 1) {
469                                                 if (place_number > place_number_limit) {
470                                                         /*
471                                                          * The decimal exponent has a magnitude so great that
472                                                          * our tables can't help us fragment it.  Although this
473                                                          * routine is in error because it can't imagine a
474                                                          * number that big, signal an error as if it is the
475                                                          * user's fault for presenting such a big number.
476                                                          */
477                                                         return_value = ERROR_EXPONENT_OVERFLOW;
478                                                         /*
479                                                          * quit out of loop gracefully
480                                                          */
481                                                         decimal_exponent = 0;
482                                                 } else {
483 #ifdef TRACE
484                                                         printf("before multiply, place_number = %d., power_of_10_flonum:\n",
485                                                                place_number);
486
487                                                         flonum_print(&power_of_10_flonum);
488                                                         (void)putchar('\n');
489 #endif
490                                                         flonum_multip(multiplicand + place_number,
491                                                                       &power_of_10_flonum, &temporary_flonum);
492                                                         flonum_copy(&temporary_flonum, &power_of_10_flonum);
493                                                 } /* If this bit of decimal_exponent was computable.*/
494                                         } /* If this bit of decimal_exponent was set. */
495                                 } /* For each bit of binary representation of exponent */
496 #ifdef TRACE
497                                 printf(" after computing power_of_10_flonum: ");
498                                 flonum_print(&power_of_10_flonum );
499                                 (void) putchar('\n');
500 #endif
501                         }
502                         
503                 }
504                 
505                 /*
506                  * power_of_10_flonum is power of ten in binary (mantissa) , (exponent).
507                  * It may be the number 1, in which case we don't NEED to multiply.
508                  *
509                  * Multiply (decimal digits) by power_of_10_flonum.
510                  */
511                 
512                 flonum_multip(&power_of_10_flonum, &digits_flonum, address_of_generic_floating_point_number);
513                 /* Assert sign of the number we made is '+'. */
514                 address_of_generic_floating_point_number->sign = digits_sign_char;
515                 
516         } /* If we had any significant digits. */
517         return(return_value);
518 } /* atof_generic () */
519
520 /* end of atof_generic.c */
This page took 0.056037 seconds and 4 git commands to generate.