Annotation of 42BSD/bin/as/natof.c, revision 1.1

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

unix.superglobalmegacorp.com

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