home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Atari / Gnu / gassrc04.zoo / atof-generic.c < prev    next >
C/C++ Source or Header  |  1991-01-24  |  17KB  |  527 lines

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