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