Annotation of 43BSD/bin/as/natof.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1982 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char sccsid[] = "@(#)natof.c    5.1 (Berkeley) 4/30/85";
                      9: #endif not lint
                     10: 
                     11: #include <stdio.h>
                     12: #include <ctype.h>
                     13: #include <errno.h>
                     14: 
                     15: #include "as.h"
                     16: 
                     17: Bignum bigatof(str, radix)
                     18:        reg     char    *str;           /* r11 */
                     19:                int     radix;          /* TYPF ... TYPH */
                     20: {
                     21:                int     msign;
                     22:                int     esign;
                     23:                int     decpt;
                     24:        reg     chptr   temp;           /* r10 */
                     25:        reg     u_int   quotient;       /* r9 */        /* must be here */
                     26:        reg     u_int   remainder;      /* r8 */        /* must be here */
                     27:        reg     chptr   acc;
                     28:        reg     int     dividend;       /* for doing division */
                     29:        reg     u_int   i;      
                     30:                short   *sptr;          /* for doing division */
                     31:                int     ch;
                     32:                int     dexponent;      /* decimal exponent */
                     33:                int     bexponent;      /* binary exponent */
                     34:                Bignum  Acc;
                     35:                Bignum  Temp;
                     36:        static  Bignum  znumber;
                     37:                Ovf     ovf;
                     38:                u_int   j;
                     39:        extern  int     errno;
                     40:                u_int   ediv();
                     41: 
                     42: #ifdef lint
                     43:        quotient = 0;
                     44:        remainder = 0;
                     45: #endif lint
                     46:        msign = 0;
                     47:        esign = 0;
                     48:        decpt = 0;
                     49:        dexponent = 0;
                     50:        Acc = znumber;
                     51:        Acc.num_tag = radix;
                     52:        acc = CH_FIELD(Acc);
                     53:        temp = CH_FIELD(Temp);
                     54: 
                     55:        do{
                     56:                ch = *str++;
                     57:        } while(isspace(ch));
                     58: 
                     59:        switch(ch){
                     60:        case '-':
                     61:                msign = -1;
                     62:                /* FALLTHROUGH */
                     63:        case '+':
                     64:                ch = *str++;
                     65:                break;
                     66:        }
                     67:   dofract:
                     68:        for(; isdigit(ch); ch = *str++){
                     69:                assert(((acc[HOC] & SIGNBIT) == 0), "Negative HOC");
                     70:                if (acc[HOC] < MAXINT_10){
                     71:                        ovf = numshift(3, temp, acc);
                     72:                        ovf |= numshift(1, acc, acc);
                     73:                        ovf |= numaddv(acc, temp, acc);
                     74:                        ovf |= numaddd(acc, acc, ch - '0');
                     75:                        assert(ovf == 0, "Overflow building mantissa");
                     76:                } else {
                     77:                        /*
                     78:                         *      Then, the number is too large anyway
                     79:                         */
                     80:                        dexponent++;
                     81:                }
                     82:                if (decpt)
                     83:                        dexponent--;
                     84:        }
                     85:        switch(ch){
                     86:        case '.':
                     87:                if (decpt == 0){
                     88:                        decpt++;
                     89:                        ch = *str++;
                     90:                        goto dofract;
                     91:                }
                     92:                break;
                     93:        /*
                     94:         *      only 'e' and 'E' are recognized by atof()
                     95:         */
                     96:        case 'e':
                     97:        case 'E':
                     98:        /*
                     99:         *      we include the remainder for compatability with as formats
                    100:         *      in as, the radix actual paramater agrees with the character
                    101:         *      we expect; consequently, no checking is done.
                    102:         */
                    103:        case 'd':
                    104:        case 'D':
                    105:        case 'g':
                    106:        case 'G':
                    107:        case 'h':
                    108:        case 'H':
                    109:                j = 0;
                    110:                ch = *str++;
                    111:                esign = 0;
                    112:                switch(ch){
                    113:                case '-':
                    114:                        esign = 1;
                    115:                        /* FALLTHROUGH */
                    116:                case '+':
                    117:                        ch = *str++;
                    118:                }
                    119:                for(; isdigit(ch); ch = *str++){
                    120:                        if (j < MAXINT_10){
                    121:                                j *= 10;
                    122:                                j += ch - '0';
                    123:                        } else {
                    124:                                /*
                    125:                                 *      outrageously large exponent
                    126:                                 */
                    127:                                 /*VOID*/
                    128:                        }
                    129:                }
                    130:                if (esign)
                    131:                        dexponent -= j;
                    132:                else
                    133:                        dexponent += j;
                    134:                /*
                    135:                 *      There should be a range check on dexponent here
                    136:                 */
                    137:        }
                    138:        /*
                    139:         *      The number has now been reduced to a mantissa
                    140:         *      and an exponent.
                    141:         *      The mantissa is an n bit number (to the precision
                    142:         *      of the extended words) in the acc.
                    143:         *      The exponent is a signed power of 10 in dexponent.
                    144:         *      msign is on if the resulting number will eventually
                    145:         *      be negative.
                    146:         *
                    147:         *      We now must convert the number to standard format floating
                    148:         *      number, which will be done by accumulating
                    149:         *      a binary exponent in bexponent, as we gradually
                    150:         *      drive dexponent towards zero, one count at a time.
                    151:         */
                    152:        if (isclear(acc)){
                    153:                return(Acc);
                    154:        }
                    155:        bexponent = 0;
                    156: 
                    157:        /*
                    158:         *      Scale the number down.
                    159:         *      We must divide acc by 10 as many times as needed.
                    160:         */
                    161:        for (; dexponent < 0; dexponent++){
                    162:                /*
                    163:                 *      Align the number so that the most significant
                    164:                 *      bits are aligned in the most significant
                    165:                 *      bits of the accumulator, adjusting the
                    166:                 *      binary exponent as we shift.
                    167:                 *      The goal is to get the high order bit (NOT the
                    168:                 *      sign bit) set.
                    169:                 */
                    170:                assert(((acc[HOC] & SIGNBIT) == 0), "Negative HOC");
                    171:                ovf = 0;
                    172: 
                    173:                for (j = 5; j >= 1; --j){
                    174:                        i = 1 << (j - 1);               /* 16, 8, 4, 2, 1 */
                    175:                        quotient = ONES(i);
                    176:                        quotient <<= (CH_BITS - 1) - i;
                    177:                        while((acc[HOC] & quotient) == 0){
                    178:                                ovf |= numshift((int)i, acc, acc);
                    179:                                bexponent -= i;
                    180:                        }
                    181:                }
                    182:                /*
                    183:                 *      Add 2 to the accumulator to effect rounding,
                    184:                 *      and get set up to divide by 5.
                    185:                 */
                    186:                ovf = numaddd(acc, acc, 2);
                    187:                assert(ovf == 0, "Carry out of left rounding up by 2");
                    188:                /*
                    189:                 *      Divide the high order chunks by 5;
                    190:                 *      The last chunk will be divided by 10,
                    191:                 *      (to see what the remainder is, also to effect rounding)
                    192:                 *      and then multipiled by 2 to effect division by 5.
                    193:                 */
                    194:                remainder = 0;
                    195: #if DEBUGNATOF
                    196:                printf("Dividing: ");
                    197:                bignumprint(Acc);
                    198:                printf("\n");
                    199: #endif DEBUGNATOF
                    200:                sptr = (short *)acc;
                    201:                for (i = (CH_N * 2 - 1); i >= 1; --i){
                    202:                        /*
                    203:                         *      Divide (remainder:16).(acc[i]:16)
                    204:                         *      by 5, putting the quotient back
                    205:                         *      into acc[i]:16, and save the remainder
                    206:                         *      for the next iteration.
                    207:                         */
                    208:                        dividend = (remainder << 16) | (sptr[i] & ONES(16));
                    209:                        assert(dividend >= 0, "dividend < 0");
                    210:                        quotient = dividend / 5;
                    211:                        remainder = dividend - (quotient * 5);
                    212:                        sptr[i] = quotient;
                    213:                        remainder = remainder;
                    214:                }
                    215:                /*
                    216:                 *      Divide the lowest order chunk by 10,
                    217:                 *      saving the remainder to decide how to round.
                    218:                 *      Then, multiply by 2, making it look as
                    219:                 *      if we divided by 10.
                    220:                 *      This multiply fills in a 0 on the least sig bit.
                    221:                 */
                    222:                dividend = (remainder << 16) | (sptr[0] & ONES(16));
                    223:                assert(dividend >= 0, "dividend < 0");
                    224:                quotient = dividend / 10;
                    225:                remainder = dividend - (quotient * 10);
                    226:                sptr[0] = quotient + quotient;
                    227: 
                    228:                if (remainder >= 5)
                    229:                        ovf = numaddd(acc, acc, 1);
                    230:                /*
                    231:                 *      Now, divide by 2, effecting division by 10,
                    232:                 *      merely by adjusting the binary exponent.
                    233:                 */
                    234:                bexponent--;
                    235:        }
                    236:        /*
                    237:         *      Scale the number up by multiplying by 10 as 
                    238:         *      many times as necessary
                    239:         */
                    240:        for (; dexponent > 0; dexponent--){
                    241:                /*
                    242:                 *      Compare high word to (2**31)/5,
                    243:                 *      and scale accordingly
                    244:                 */
                    245:                while ( ((unsigned)acc[HOC]) > MAXINT_5){
                    246:                        (void)numshift(-1, acc, acc);
                    247:                        bexponent++;
                    248:                }
                    249:                /*
                    250:                 *      multiply the mantissa by 5,
                    251:                 *      and scale the binary exponent by 2
                    252:                 */
                    253:                ovf = numshift(2, temp, acc);
                    254:                ovf |= numaddv(acc, acc, temp);
                    255:                assert(ovf == 0, "Scaling * 10 of manitissa");
                    256:                bexponent++;
                    257:        }
                    258:        /*
                    259:         *      We now have:
                    260:         *      a CH_N chunk length binary integer, right
                    261:         *              justified (in native format).
                    262:         *      a binary exponent.
                    263:         *
                    264:         *      Now, we treat this large integer as an octa word
                    265:         *      number, and unpack it into standard unpacked
                    266:         *      format.  That unpacking will give us yet
                    267:         *      another binary exponent, which we adjust with
                    268:         *      the accumulated binary exponent.
                    269:         */
                    270:        Acc.num_tag = TYPO;
                    271: #if DEBUGNATOF
                    272:        printf("Octal number: ");
                    273:        bignumprint(Acc);
                    274:        printf("\n");
                    275: #endif DEBUGNATOF
                    276:        Acc = bignumunpack(Acc, &ovf);
                    277: 
                    278:        if (ovf)
                    279:                errno = ERANGE;
                    280: #if DEBUGNATOF
                    281:        printf("Unpacked octal number: ");
                    282:        bignumprint(Acc);
                    283:        printf("bexponent == %d\n", bexponent);
                    284: #endif DEBUGNATOF
                    285:        Acc.num_exponent += bexponent;
                    286:        assert(Acc.num_sign == 0, "unpacked integer is < 0");
                    287:        Acc.num_sign = msign;
                    288:        /*
                    289:         *      We now pack the number back into a radix format number.
                    290:         *      This checks for overflow, underflow,
                    291:         *      and rounds by 1/2 ulp.
                    292:         */
                    293:        ovf = 0;
                    294:        Acc = bignumpack(Acc, radix, &ovf);
                    295:        if (ovf)
                    296:                errno = ERANGE;
                    297: #if DEBUGNATOF
                    298:        printf("packed number: ");
                    299:        bignumprint(Acc);
                    300:        printf("\n");
                    301: #endif DEBUGNATOF
                    302:        return(Acc);
                    303: }
                    304: #if 0
                    305: /*
                    306:  *     Unfortunately, one can't use the ediv instruction to do
                    307:  *     division on numbers with > 64 bits.
                    308:  *     This is because ediv returns signed quantities;
                    309:  *     if the quotient is an unsigned number > 2^31,
                    310:  *     ediv sets integer overflow.
                    311:  */
                    312: unsigned int ediv(high, low, divisor, qp, i)
                    313:        register        unsigned int    high;           /* r11 */
                    314:        register        unsigned int    low;            /* r10 */
                    315:        register        unsigned int    divisor;        /* r9 */
                    316:                        unsigned int    *qp;
                    317: {
                    318:        register        unsigned int    remainder;      /* r8 */
                    319:        register        unsigned int    quotient;       /* r7 */
                    320: 
                    321:        asm("ediv r9, r10, r7, r8       # Divide.  q->r7, r->r8 (discarded)");
                    322:        *qp = quotient;
                    323:        return(remainder);
                    324: }
                    325: #endif 0

unix.superglobalmegacorp.com

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