Annotation of gas/atof-generic.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.