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

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

unix.superglobalmegacorp.com

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