Annotation of researchv10no/cmd/sort/number.c, revision 1.1

1.1     ! root        1: /* Copyright 1990, AT&T Bell Labs */
        !             2: 
        !             3: /* Canonicalize the number string pointed to by dp, of length
        !             4:    len.  Put the result in kp.
        !             5: 
        !             6:    A field of length zero, or all blank, is regarded as 0.
        !             7:    Over/underflow is rendered as huge or zero and properly signed.
        !             8:    It happens 1e+-1022.
        !             9: 
        !            10:    Canonicalized strings may be compared as strings of unsigned
        !            11:    chars.  For good measure, a canonical string has no zero bytes.
        !            12: 
        !            13:    Syntax: optionally signed floating point, with optional
        !            14:    leading spaces.  A syntax deviation ends the number.
        !            15: 
        !            16:    Form of output: packed in 4-bit nibbles.  First
        !            17:    3 nibbles count the number N of significant digits
        !            18:    before the decimal point.  The quantity actually stored
        !            19:    is 2048+sign(x)*(N+1024).  Further nibbles contain
        !            20:    1 decimal digit d each, stored as d+2 if x is positive
        !            21:    and as 10-d if x is negative.  Leading and trailing
        !            22:    zeros are stripped, and a trailing "digit" d = -1 
        !            23:    is appended.  (The trailing digit handled like all others,
        !            24:    so encodes as 1 or 0xb according to the sign of x.)
        !            25:    An odd number of nibbles is padded with zero.
        !            26: 
        !            27:    Buglet: overflow is reported if output is exactly filled.
        !            28: 
        !            29: */
        !            30: #include "fsort.h"
        !            31: 
        !            32: #define encode(x) (neg? 10-(x): (x)+2)
        !            33: #define putdig(x) (nib? (*dig=encode(x)<<4, nib=0): \
        !            34:                  (*dig++|=encode(x), nib=1))
        !            35: 
        !            36: static int gflag;
        !            37: 
        !            38: int
        !            39: gcode(uchar *dp, uchar*kp, int len, struct field *f)
        !            40: {
        !            41:        int ret;
        !            42:        gflag++;
        !            43:        ret = ncode(dp, kp, len, f);
        !            44:        gflag--;
        !            45:        return ret;
        !            46: }
        !            47: 
        !            48: int
        !            49: ncode(uchar *dp, uchar*kp, int len, struct field *f)
        !            50: {
        !            51:        uchar *dig = kp + 1;    /* byte for next digit */
        !            52:        int nib = 0;    /* high nibble 1, low nibble 0 */
        !            53:        uchar *cp = dp;
        !            54:        uchar *ep = cp + len;   /* end pointer */
        !            55:        int zeros = 0;  /* count zeros seen but not installed */
        !            56:        int sigdig = 1024;
        !            57:        int neg = f->rflag;     /* 0 for +, 1 for - */
        !            58:        int decimal = 0;
        !            59:        int n, inv;
        !            60: 
        !            61:        kp[1] = 0;
        !            62:        for( ; cp<ep ; cp++)    /* eat blanks */
        !            63:                if(*cp!=' ' && *cp!='\t')
        !            64:                        break;
        !            65:        if(cp < ep)             /* eat sign */
        !            66:                switch(*cp) {
        !            67:                case '-':
        !            68:                        neg ^= 1;
        !            69:                case '+':
        !            70:                        cp++;
        !            71:                }
        !            72:        for( ; cp<ep; cp++)     /* eat leading zeros */
        !            73:                if(*cp != '0')
        !            74:                        break;
        !            75:        if(*cp=='.' && cp<ep) { /* decimal point among lead zeros */
        !            76:                decimal++;
        !            77:                for(cp++; cp<ep; cp++) {
        !            78:                        if(*cp != '0')
        !            79:                                break;
        !            80:                        sigdig--;
        !            81:                }
        !            82:        }
        !            83:        if(*cp>'9' || *cp<'0' || cp>=ep) {      /* no sig digit*/
        !            84:                sigdig = 0;
        !            85:                neg = 0;
        !            86:                goto retzero;
        !            87:        }
        !            88:        for( ; cp<ep; cp++) {
        !            89:                switch(*cp) {
        !            90:                default:
        !            91:                        goto out;
        !            92:                case '.':
        !            93:                        if(decimal)
        !            94:                                goto out;
        !            95:                        decimal++;
        !            96:                        continue;
        !            97:                case '0':
        !            98:                        zeros++;
        !            99:                        if(!decimal)
        !           100:                                sigdig++;
        !           101:                        continue;
        !           102:                case '1': case '2': case '3': case '4': case '5':
        !           103:                case '6': case '7': case '8': case '9':
        !           104:                        for( ; zeros>0; zeros--)
        !           105:                                putdig(0);
        !           106:                        n = *cp - '0';
        !           107:                        putdig(n);
        !           108:                        if(!decimal)
        !           109:                                sigdig++;
        !           110:                        continue;
        !           111:                case 'e':
        !           112:                case 'E':
        !           113:                        if(!gflag)
        !           114:                                goto out;
        !           115:                        inv = 1;
        !           116:                        if(cp < ep) switch(*++cp) {
        !           117:                        case '-':
        !           118:                                inv = -1;
        !           119:                        case '+':
        !           120:                                cp++;
        !           121:                        }
        !           122:                        if(*cp>'9' || *cp<'0' || cp>=ep)
        !           123:                                goto out;
        !           124:                        for(n=0; cp<ep; cp++) {
        !           125:                                int c = *cp;
        !           126:                                if(c<'0' || c>'9')
        !           127:                                        break;
        !           128:                                if((n = 10*n+c-'0') >= 0)
        !           129:                                        continue;
        !           130:                                sigdig = 2047*inv;
        !           131:                                goto out;
        !           132:                        }
        !           133:                        sigdig += n*inv;
        !           134:                        goto out;
        !           135:                }
        !           136:        }
        !           137: out:
        !           138:        if(sigdig<0 || sigdig>=2047) {
        !           139:                sigdig = sigdig<0? 0: 2047;
        !           140:                warn("numeric field overflow", (char*)dp, len);
        !           141:                dig = kp + 1;
        !           142:                *dig = 0;
        !           143:                nib = 0;
        !           144:        }
        !           145: retzero:
        !           146:        if(neg)
        !           147:                sigdig = 2048 - sigdig;
        !           148:        else
        !           149:                sigdig = 2048 + sigdig;
        !           150:        kp[0] = sigdig >> 4;
        !           151:        kp[1] |= sigdig << 4;
        !           152:        putdig(-1);
        !           153:        return dig - kp + 1 - nib;
        !           154: }

unix.superglobalmegacorp.com

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