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

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