Back to index

cell-binutils  2.17cvs20070401
atof-generic.c
Go to the documentation of this file.
00001 /* atof_generic.c - turn a string of digits into a Flonum
00002    Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1998, 1999, 2000,
00003    2001, 2003, 2005, 2006 Free Software Foundation, Inc.
00004 
00005    This file is part of GAS, the GNU Assembler.
00006 
00007    GAS is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2, or (at your option)
00010    any later version.
00011 
00012    GAS is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with GAS; see the file COPYING.  If not, write to the Free
00019    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
00020    02110-1301, USA.  */
00021 
00022 #include "as.h"
00023 #include "safe-ctype.h"
00024 
00025 #ifndef FALSE
00026 #define FALSE (0)
00027 #endif
00028 #ifndef TRUE
00029 #define TRUE  (1)
00030 #endif
00031 
00032 #ifdef TRACE
00033 static void flonum_print (const FLONUM_TYPE *);
00034 #endif
00035 
00036 #define ASSUME_DECIMAL_MARK_IS_DOT
00037 
00038 /***********************************************************************\
00039  *                                                             *
00040  *     Given a string of decimal digits , with optional decimal       *
00041  *     mark and optional decimal exponent (place value) of the        *
00042  *     lowest_order decimal digit: produce a floating point           *
00043  *     number. The number is 'generic' floating point: our            *
00044  *     caller will encode it for a specific machine architecture.     *
00045  *                                                             *
00046  *     Assumptions                                             *
00047  *            uses base (radix) 2                              *
00048  *            this machine uses 2's complement binary integers *
00049  *            target flonums use "      "         "       "           *
00050  *            target flonums exponents fit in a long                  *
00051  *                                                             *
00052  \***********************************************************************/
00053 
00054 /*
00055 
00056   Syntax:
00057 
00058   <flonum> ::= <optional-sign> <decimal-number> <optional-exponent>
00059   <optional-sign> ::= '+' | '-' | {empty}
00060   <decimal-number> ::= <integer>
00061   | <integer> <radix-character>
00062   | <integer> <radix-character> <integer>
00063   | <radix-character> <integer>
00064 
00065   <optional-exponent> ::= {empty}
00066   | <exponent-character> <optional-sign> <integer>
00067 
00068   <integer> ::= <digit> | <digit> <integer>
00069   <digit> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
00070   <exponent-character> ::= {one character from "string_of_decimal_exponent_marks"}
00071   <radix-character> ::= {one character from "string_of_decimal_marks"}
00072 
00073   */
00074 
00075 int
00076 atof_generic (/* return pointer to just AFTER number we read.  */
00077              char **address_of_string_pointer,
00078              /* At most one per number.  */
00079              const char *string_of_decimal_marks,
00080              const char *string_of_decimal_exponent_marks,
00081              FLONUM_TYPE *address_of_generic_floating_point_number)
00082 {
00083   int return_value;         /* 0 means OK.  */
00084   char *first_digit;
00085   unsigned int number_of_digits_before_decimal;
00086   unsigned int number_of_digits_after_decimal;
00087   long decimal_exponent;
00088   unsigned int number_of_digits_available;
00089   char digits_sign_char;
00090 
00091   /*
00092    * Scan the input string, abstracting (1)digits (2)decimal mark (3) exponent.
00093    * It would be simpler to modify the string, but we don't; just to be nice
00094    * to caller.
00095    * We need to know how many digits we have, so we can allocate space for
00096    * the digits' value.
00097    */
00098 
00099   char *p;
00100   char c;
00101   int seen_significant_digit;
00102 
00103 #ifdef ASSUME_DECIMAL_MARK_IS_DOT
00104   assert (string_of_decimal_marks[0] == '.'
00105          && string_of_decimal_marks[1] == 0);
00106 #define IS_DECIMAL_MARK(c)  ((c) == '.')
00107 #else
00108 #define IS_DECIMAL_MARK(c)  (0 != strchr (string_of_decimal_marks, (c)))
00109 #endif
00110 
00111   first_digit = *address_of_string_pointer;
00112   c = *first_digit;
00113 
00114   if (c == '-' || c == '+')
00115     {
00116       digits_sign_char = c;
00117       first_digit++;
00118     }
00119   else
00120     digits_sign_char = '+';
00121 
00122   switch (first_digit[0])
00123     {
00124     case 'n':
00125     case 'N':
00126       if (!strncasecmp ("nan", first_digit, 3))
00127        {
00128          address_of_generic_floating_point_number->sign = 0;
00129          address_of_generic_floating_point_number->exponent = 0;
00130          address_of_generic_floating_point_number->leader =
00131            address_of_generic_floating_point_number->low;
00132          *address_of_string_pointer = first_digit + 3;
00133          return 0;
00134        }
00135       break;
00136 
00137     case 'i':
00138     case 'I':
00139       if (!strncasecmp ("inf", first_digit, 3))
00140        {
00141          address_of_generic_floating_point_number->sign =
00142            digits_sign_char == '+' ? 'P' : 'N';
00143          address_of_generic_floating_point_number->exponent = 0;
00144          address_of_generic_floating_point_number->leader =
00145            address_of_generic_floating_point_number->low;
00146 
00147          first_digit += 3;
00148          if (!strncasecmp ("inity", first_digit, 5))
00149            first_digit += 5;
00150 
00151          *address_of_string_pointer = first_digit;
00152 
00153          return 0;
00154        }
00155       break;
00156     }
00157 
00158   number_of_digits_before_decimal = 0;
00159   number_of_digits_after_decimal = 0;
00160   decimal_exponent = 0;
00161   seen_significant_digit = 0;
00162   for (p = first_digit;
00163        (((c = *p) != '\0')
00164        && (!c || !IS_DECIMAL_MARK (c))
00165        && (!c || !strchr (string_of_decimal_exponent_marks, c)));
00166        p++)
00167     {
00168       if (ISDIGIT (c))
00169        {
00170          if (seen_significant_digit || c > '0')
00171            {
00172              ++number_of_digits_before_decimal;
00173              seen_significant_digit = 1;
00174            }
00175          else
00176            {
00177              first_digit++;
00178            }
00179        }
00180       else
00181        {
00182          break;             /* p -> char after pre-decimal digits.  */
00183        }
00184     }                       /* For each digit before decimal mark.  */
00185 
00186 #ifndef OLD_FLOAT_READS
00187   /* Ignore trailing 0's after the decimal point.  The original code here
00188    * (ifdef'd out) does not do this, and numbers like
00189    *   4.29496729600000000000e+09  (2**31)
00190    * come out inexact for some reason related to length of the digit
00191    * string.
00192    */
00193   if (c && IS_DECIMAL_MARK (c))
00194     {
00195       unsigned int zeros = 0;      /* Length of current string of zeros */
00196 
00197       for (p++; (c = *p) && ISDIGIT (c); p++)
00198        {
00199          if (c == '0')
00200            {
00201              zeros++;
00202            }
00203          else
00204            {
00205              number_of_digits_after_decimal += 1 + zeros;
00206              zeros = 0;
00207            }
00208        }
00209     }
00210 #else
00211   if (c && IS_DECIMAL_MARK (c))
00212     {
00213       for (p++;
00214           (((c = *p) != '\0')
00215            && (!c || !strchr (string_of_decimal_exponent_marks, c)));
00216           p++)
00217        {
00218          if (ISDIGIT (c))
00219            {
00220              /* This may be retracted below.  */
00221              number_of_digits_after_decimal++;
00222 
00223              if ( /* seen_significant_digit || */ c > '0')
00224               {
00225                 seen_significant_digit = TRUE;
00226               }
00227            }
00228          else
00229            {
00230              if (!seen_significant_digit)
00231               {
00232                 number_of_digits_after_decimal = 0;
00233               }
00234              break;
00235            }
00236        }                    /* For each digit after decimal mark.  */
00237     }
00238 
00239   while (number_of_digits_after_decimal
00240         && first_digit[number_of_digits_before_decimal
00241                      + number_of_digits_after_decimal] == '0')
00242     --number_of_digits_after_decimal;
00243 #endif
00244 
00245   if (flag_m68k_mri)
00246     {
00247       while (c == '_')
00248        c = *++p;
00249     }
00250   if (c && strchr (string_of_decimal_exponent_marks, c))
00251     {
00252       char digits_exponent_sign_char;
00253 
00254       c = *++p;
00255       if (flag_m68k_mri)
00256        {
00257          while (c == '_')
00258            c = *++p;
00259        }
00260       if (c && strchr ("+-", c))
00261        {
00262          digits_exponent_sign_char = c;
00263          c = *++p;
00264        }
00265       else
00266        {
00267          digits_exponent_sign_char = '+';
00268        }
00269 
00270       for (; (c); c = *++p)
00271        {
00272          if (ISDIGIT (c))
00273            {
00274              decimal_exponent = decimal_exponent * 10 + c - '0';
00275              /*
00276               * BUG! If we overflow here, we lose!
00277               */
00278            }
00279          else
00280            {
00281              break;
00282            }
00283        }
00284 
00285       if (digits_exponent_sign_char == '-')
00286        {
00287          decimal_exponent = -decimal_exponent;
00288        }
00289     }
00290 
00291   *address_of_string_pointer = p;
00292 
00293   number_of_digits_available =
00294     number_of_digits_before_decimal + number_of_digits_after_decimal;
00295   return_value = 0;
00296   if (number_of_digits_available == 0)
00297     {
00298       address_of_generic_floating_point_number->exponent = 0;  /* Not strictly necessary */
00299       address_of_generic_floating_point_number->leader
00300        = -1 + address_of_generic_floating_point_number->low;
00301       address_of_generic_floating_point_number->sign = digits_sign_char;
00302       /* We have just concocted (+/-)0.0E0 */
00303 
00304     }
00305   else
00306     {
00307       int count;            /* Number of useful digits left to scan.  */
00308 
00309       LITTLENUM_TYPE *digits_binary_low;
00310       unsigned int precision;
00311       unsigned int maximum_useful_digits;
00312       unsigned int number_of_digits_to_use;
00313       unsigned int more_than_enough_bits_for_digits;
00314       unsigned int more_than_enough_littlenums_for_digits;
00315       unsigned int size_of_digits_in_littlenums;
00316       unsigned int size_of_digits_in_chars;
00317       FLONUM_TYPE power_of_10_flonum;
00318       FLONUM_TYPE digits_flonum;
00319 
00320       precision = (address_of_generic_floating_point_number->high
00321                  - address_of_generic_floating_point_number->low
00322                  + 1);      /* Number of destination littlenums.  */
00323 
00324       /* Includes guard bits (two littlenums worth) */
00325       maximum_useful_digits = (((precision - 2))
00326                             * ( (LITTLENUM_NUMBER_OF_BITS))
00327                             * 1000000 / 3321928)
00328        + 2;                 /* 2 :: guard digits.  */
00329 
00330       if (number_of_digits_available > maximum_useful_digits)
00331        {
00332          number_of_digits_to_use = maximum_useful_digits;
00333        }
00334       else
00335        {
00336          number_of_digits_to_use = number_of_digits_available;
00337        }
00338 
00339       /* Cast these to SIGNED LONG first, otherwise, on systems with
00340         LONG wider than INT (such as Alpha OSF/1), unsignedness may
00341         cause unexpected results.  */
00342       decimal_exponent += ((long) number_of_digits_before_decimal
00343                         - (long) number_of_digits_to_use);
00344 
00345       more_than_enough_bits_for_digits
00346        = (number_of_digits_to_use * 3321928 / 1000000 + 1);
00347 
00348       more_than_enough_littlenums_for_digits
00349        = (more_than_enough_bits_for_digits
00350           / LITTLENUM_NUMBER_OF_BITS)
00351        + 2;
00352 
00353       /* Compute (digits) part. In "12.34E56" this is the "1234" part.
00354         Arithmetic is exact here. If no digits are supplied then this
00355         part is a 0 valued binary integer.  Allocate room to build up
00356         the binary number as littlenums.  We want this memory to
00357         disappear when we leave this function.  Assume no alignment
00358         problems => (room for n objects) == n * (room for 1
00359         object).  */
00360 
00361       size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits;
00362       size_of_digits_in_chars = size_of_digits_in_littlenums
00363        * sizeof (LITTLENUM_TYPE);
00364 
00365       digits_binary_low = (LITTLENUM_TYPE *)
00366        alloca (size_of_digits_in_chars);
00367 
00368       memset ((char *) digits_binary_low, '\0', size_of_digits_in_chars);
00369 
00370       /* Digits_binary_low[] is allocated and zeroed.  */
00371 
00372       /*
00373        * Parse the decimal digits as if * digits_low was in the units position.
00374        * Emit a binary number into digits_binary_low[].
00375        *
00376        * Use a large-precision version of:
00377        * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit
00378        */
00379 
00380       for (p = first_digit, count = number_of_digits_to_use; count; p++, --count)
00381        {
00382          c = *p;
00383          if (ISDIGIT (c))
00384            {
00385              /*
00386               * Multiply by 10. Assume can never overflow.
00387               * Add this digit to digits_binary_low[].
00388               */
00389 
00390              long carry;
00391              LITTLENUM_TYPE *littlenum_pointer;
00392              LITTLENUM_TYPE *littlenum_limit;
00393 
00394              littlenum_limit = digits_binary_low
00395               + more_than_enough_littlenums_for_digits
00396               - 1;
00397 
00398              carry = c - '0';      /* char -> binary */
00399 
00400              for (littlenum_pointer = digits_binary_low;
00401                  littlenum_pointer <= littlenum_limit;
00402                  littlenum_pointer++)
00403               {
00404                 long work;
00405 
00406                 work = carry + 10 * (long) (*littlenum_pointer);
00407                 *littlenum_pointer = work & LITTLENUM_MASK;
00408                 carry = work >> LITTLENUM_NUMBER_OF_BITS;
00409               }
00410 
00411              if (carry != 0)
00412               {
00413                 /*
00414                  * We have a GROSS internal error.
00415                  * This should never happen.
00416                  */
00417                 as_fatal (_("failed sanity check"));
00418               }
00419            }
00420          else
00421            {
00422              ++count;              /* '.' doesn't alter digits used count.  */
00423            }
00424        }
00425 
00426       /*
00427        * Digits_binary_low[] properly encodes the value of the digits.
00428        * Forget about any high-order littlenums that are 0.
00429        */
00430       while (digits_binary_low[size_of_digits_in_littlenums - 1] == 0
00431             && size_of_digits_in_littlenums >= 2)
00432        size_of_digits_in_littlenums--;
00433 
00434       digits_flonum.low = digits_binary_low;
00435       digits_flonum.high = digits_binary_low + size_of_digits_in_littlenums - 1;
00436       digits_flonum.leader = digits_flonum.high;
00437       digits_flonum.exponent = 0;
00438       /*
00439        * The value of digits_flonum . sign should not be important.
00440        * We have already decided the output's sign.
00441        * We trust that the sign won't influence the other parts of the number!
00442        * So we give it a value for these reasons:
00443        * (1) courtesy to humans reading/debugging
00444        *     these numbers so they don't get excited about strange values
00445        * (2) in future there may be more meaning attached to sign,
00446        *     and what was
00447        *     harmless noise may become disruptive, ill-conditioned (or worse)
00448        *     input.
00449        */
00450       digits_flonum.sign = '+';
00451 
00452       {
00453        /*
00454         * Compute the mantssa (& exponent) of the power of 10.
00455         * If successful, then multiply the power of 10 by the digits
00456         * giving return_binary_mantissa and return_binary_exponent.
00457         */
00458 
00459        LITTLENUM_TYPE *power_binary_low;
00460        int decimal_exponent_is_negative;
00461        /* This refers to the "-56" in "12.34E-56".  */
00462        /* FALSE: decimal_exponent is positive (or 0) */
00463        /* TRUE:  decimal_exponent is negative */
00464        FLONUM_TYPE temporary_flonum;
00465        LITTLENUM_TYPE *temporary_binary_low;
00466        unsigned int size_of_power_in_littlenums;
00467        unsigned int size_of_power_in_chars;
00468 
00469        size_of_power_in_littlenums = precision;
00470        /* Precision has a built-in fudge factor so we get a few guard bits.  */
00471 
00472        decimal_exponent_is_negative = decimal_exponent < 0;
00473        if (decimal_exponent_is_negative)
00474          {
00475            decimal_exponent = -decimal_exponent;
00476          }
00477 
00478        /* From now on: the decimal exponent is > 0. Its sign is separate.  */
00479 
00480        size_of_power_in_chars = size_of_power_in_littlenums
00481          * sizeof (LITTLENUM_TYPE) + 2;
00482 
00483        power_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars);
00484        temporary_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars);
00485        memset ((char *) power_binary_low, '\0', size_of_power_in_chars);
00486        *power_binary_low = 1;
00487        power_of_10_flonum.exponent = 0;
00488        power_of_10_flonum.low = power_binary_low;
00489        power_of_10_flonum.leader = power_binary_low;
00490        power_of_10_flonum.high = power_binary_low + size_of_power_in_littlenums - 1;
00491        power_of_10_flonum.sign = '+';
00492        temporary_flonum.low = temporary_binary_low;
00493        temporary_flonum.high = temporary_binary_low + size_of_power_in_littlenums - 1;
00494        /*
00495         * (power) == 1.
00496         * Space for temporary_flonum allocated.
00497         */
00498 
00499        /*
00500         * ...
00501         *
00502         * WHILE      more bits
00503         * DO  find next bit (with place value)
00504         *     multiply into power mantissa
00505         * OD
00506         */
00507        {
00508          int place_number_limit;
00509          /* Any 10^(2^n) whose "n" exceeds this */
00510          /* value will fall off the end of */
00511          /* flonum_XXXX_powers_of_ten[].  */
00512          int place_number;
00513          const FLONUM_TYPE *multiplicand; /* -> 10^(2^n) */
00514 
00515          place_number_limit = table_size_of_flonum_powers_of_ten;
00516 
00517          multiplicand = (decimal_exponent_is_negative
00518                        ? flonum_negative_powers_of_ten
00519                        : flonum_positive_powers_of_ten);
00520 
00521          for (place_number = 1;/* Place value of this bit of exponent.  */
00522               decimal_exponent;/* Quit when no more 1 bits in exponent.  */
00523               decimal_exponent >>= 1, place_number++)
00524            {
00525              if (decimal_exponent & 1)
00526               {
00527                 if (place_number > place_number_limit)
00528                   {
00529                     /* The decimal exponent has a magnitude so great
00530                       that our tables can't help us fragment it.
00531                       Although this routine is in error because it
00532                       can't imagine a number that big, signal an
00533                       error as if it is the user's fault for
00534                       presenting such a big number.  */
00535                     return_value = ERROR_EXPONENT_OVERFLOW;
00536                     /* quit out of loop gracefully */
00537                     decimal_exponent = 0;
00538                   }
00539                 else
00540                   {
00541 #ifdef TRACE
00542                     printf ("before multiply, place_number = %d., power_of_10_flonum:\n",
00543                            place_number);
00544 
00545                     flonum_print (&power_of_10_flonum);
00546                     (void) putchar ('\n');
00547 #endif
00548 #ifdef TRACE
00549                     printf ("multiplier:\n");
00550                     flonum_print (multiplicand + place_number);
00551                     (void) putchar ('\n');
00552 #endif
00553                     flonum_multip (multiplicand + place_number,
00554                                  &power_of_10_flonum, &temporary_flonum);
00555 #ifdef TRACE
00556                     printf ("after multiply:\n");
00557                     flonum_print (&temporary_flonum);
00558                     (void) putchar ('\n');
00559 #endif
00560                     flonum_copy (&temporary_flonum, &power_of_10_flonum);
00561 #ifdef TRACE
00562                     printf ("after copy:\n");
00563                     flonum_print (&power_of_10_flonum);
00564                     (void) putchar ('\n');
00565 #endif
00566                   } /* If this bit of decimal_exponent was computable.*/
00567               } /* If this bit of decimal_exponent was set.  */
00568            } /* For each bit of binary representation of exponent */
00569 #ifdef TRACE
00570          printf ("after computing power_of_10_flonum:\n");
00571          flonum_print (&power_of_10_flonum);
00572          (void) putchar ('\n');
00573 #endif
00574        }
00575 
00576       }
00577 
00578       /*
00579        * power_of_10_flonum is power of ten in binary (mantissa) , (exponent).
00580        * It may be the number 1, in which case we don't NEED to multiply.
00581        *
00582        * Multiply (decimal digits) by power_of_10_flonum.
00583        */
00584 
00585       flonum_multip (&power_of_10_flonum, &digits_flonum, address_of_generic_floating_point_number);
00586       /* Assert sign of the number we made is '+'.  */
00587       address_of_generic_floating_point_number->sign = digits_sign_char;
00588 
00589     }
00590   return return_value;
00591 }
00592 
00593 #ifdef TRACE
00594 static void
00595 flonum_print (f)
00596      const FLONUM_TYPE *f;
00597 {
00598   LITTLENUM_TYPE *lp;
00599   char littlenum_format[10];
00600   sprintf (littlenum_format, " %%0%dx", sizeof (LITTLENUM_TYPE) * 2);
00601 #define print_littlenum(LP) (printf (littlenum_format, LP))
00602   printf ("flonum @%p %c e%ld", f, f->sign, f->exponent);
00603   if (f->low < f->high)
00604     for (lp = f->high; lp >= f->low; lp--)
00605       print_littlenum (*lp);
00606   else
00607     for (lp = f->low; lp <= f->high; lp++)
00608       print_littlenum (*lp);
00609   printf ("\n");
00610   fflush (stdout);
00611 }
00612 #endif
00613 
00614 /* end of atof_generic.c */