Annotation of GNUtools/cctools/as/atof-generic.c, revision 1.1.1.1

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