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

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