Annotation of researchv10no/cmd/sort/number.c, revision 1.1.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.