Annotation of 43BSD/bin/as/natof.c, revision 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.