Annotation of researchv10no/cmd/sort/optiona.c, revision 1.1.1.1

1.1       root        1: #include <float.h>
                      2: #include <math.h>
                      3: #include <ctype.h>
                      4: #include <string.h>
                      5: #include <stdlib.h>
                      6: #include "fsort.h"
                      7: 
                      8:        /* portability hack for old libc's */
                      9: #define realloc(p,q) (p?realloc(p,q):malloc(q))
                     10: 
                     11: struct field accum[NF];
                     12: int naccum;
                     13: 
                     14: typedef struct {
                     15:        uchar *e;       /* last+1st char */
                     16:        signed char s;  /* -1 for neg, 1 for pos */
                     17:        char c;         /* 1 if + sign, else 0 */
                     18:        char z;         /* 1 for leading 0, else 0 */
                     19:        char p;         /* nonzero if a decimal point */
                     20:        int f;          /* number of digits after dec. pt. */
                     21: } desc;
                     22: 
                     23: #define max(a, b) ((a)>(b)?(a):(b))
                     24: #define mod10(a) (((a)+20)%10)
                     25: #define div10(a) (((a)+20)/10-2)
                     26: 
                     27: /* find least significant digit and other facts about a number
                     28:    in field beginning at a and ending just before e */
                     29: 
                     30: desc
                     31: lsd(uchar *a, uchar *e)
                     32: {
                     33:        desc d = { 0, 1, 0, 0, 0, 0 };
                     34:        while(a<e && (*a==' '||*a=='\t')) a++;
                     35:        if(a >= e)
                     36:                ;
                     37:        else if(*a == '-') {
                     38:                d.s = -1;
                     39:                a++;
                     40:        } else if(*a == '+') {
                     41:                d.c = 1;
                     42:                a++;
                     43:        }
                     44:        if(a+1<e && *a=='0' && isdigit(a[1])) d.z = 1;
                     45:        while(a<e && isdigit(*a))
                     46:                a++;
                     47:        if(a<e && *a=='.') {
                     48:                d.p = 1;
                     49:                while(++a<e && isdigit(*a))
                     50:                        d.f++;
                     51:        }
                     52:        d.e = a;
                     53:        return d;
                     54: }
                     55: 
                     56: /* add the fields at a and b as desc-ribed,
                     57:    putting result, with decimal point omitted,
                     58:    right justified before re.
                     59:    calculates in 10's complement and recomplements
                     60:    magnitude if negative.
                     61:    set *sgn -1 for neg, 1 for signed +, 0 for unsigned. */
                     62: 
                     63: uchar *
                     64: add(uchar *re, uchar *a, desc ad, uchar *b, desc bd, int *sgn)
                     65: {
                     66:        int d = 0;
                     67:        uchar *t;
                     68:        uchar *r = re;
                     69:        while(ad.f > bd.f) {
                     70:                d += (*--ad.e - '0')*ad.s;
                     71:                *--re = mod10(d);
                     72:                d = div10(d);
                     73:                ad.f--;
                     74:        }
                     75:        while(bd.f > ad.f) {
                     76:                d += (*--bd.e - '0')*bd.s;
                     77:                *--re = mod10(d);
                     78:                d = div10(d);
                     79:                bd.f--;
                     80:        }
                     81:        while(ad.e>a || bd.e>b) {
                     82:                if(ad.f-- == 0) {
                     83:                        if(ad.p)
                     84:                                ad.e--;
                     85:                        if(bd.p)
                     86:                                bd.e--;
                     87:                }
                     88:                if(ad.e > a)
                     89:                        if(isdigit(*--ad.e))
                     90:                                d += (*ad.e - '0')*ad.s;
                     91:                        else 
                     92:                                ad.e = a;
                     93:                if(bd.e > b)
                     94:                        if(isdigit(*--bd.e))
                     95:                                d += (*bd.e - '0')*bd.s;
                     96:                        else
                     97:                                bd.e = b;
                     98:                *--re = mod10(d);
                     99:                d = div10(d);
                    100:        }
                    101:        *sgn = ad.c | bd.c;
                    102:        if(d > 0)
                    103:                *--re = 1;      /* happens only on overflow */
                    104:        else if(d < 0) {
                    105:                int x = 10;
                    106:                *sgn = -1;
                    107:                for(t = r; --t>=re; ) {
                    108:                        *t = (x - *t)%10;
                    109:                        if(*t != 0)
                    110:                                x = 9;
                    111:                }
                    112:                if(d < -1)
                    113:                        *--re = 1; /* hygiene, can't happen */
                    114:        }
                    115:        while(re<r && *re==0)
                    116:                re++;
                    117:        return re;
                    118: }
                    119: 
                    120: int
                    121: fieldaccum(uchar *a, uchar *ae, uchar *b, uchar *be)
                    122: {
                    123:        static uchar *r, *re;   /* not pure ansi (re-r=nil-nil=?) */
                    124:        desc da = lsd(a, ae);
                    125:        desc db = lsd(b, be);
                    126:        int sgn, Sgn, f;
                    127:        uchar *v;
                    128:        while(re-r < max(da.e-a+db.f, db.e-b+da.f) + 1) {
                    129:                int l = re - r + 100;
                    130:                r = (uchar*)realloc(r, l);
                    131:                if(r == 0)
                    132:                        fatal("out of space","",0);
                    133:                re = r + l;
                    134:        }
                    135:        f = max(da.f, db.f);
                    136:        v = add(re, a, da, b, db, &sgn);
                    137:        Sgn = sgn != 0;
                    138:        if(Sgn+max(re-v,f+1)+(da.p|db.p) > ae-a)
                    139:                return 0;
                    140:        while(re>v && --f>=0)
                    141:                *--ae = *--re + '0';
                    142:        while(--f >= 0)
                    143:                *--ae = '0';
                    144:        if(da.p | db.p)
                    145:                *--ae = '.';
                    146:        if(re <= v)
                    147:                *--ae = '0';
                    148:        while(re > v)
                    149:                *--ae = *--re + '0';
                    150:        if(da.z | db.z)
                    151:                while(ae > a+Sgn)
                    152:                        *--ae = '0';
                    153:        if(sgn > 0)
                    154:                *--ae = '+';
                    155:        else if(sgn < 0)
                    156:                *--ae = '-';
                    157:        if(ae<a || v<r)
                    158:                fatal("bug in accumulation","",0);
                    159:        while(ae > a)
                    160:                *--ae = ' ';
                    161:        return 1;
                    162: }
                    163: 
                    164: void
                    165: chkaccum(struct field *field)
                    166: {
                    167:        if(field->coder == 0)
                    168:                field->coder = acode;
                    169:        if(field->coder != acode)
                    170:                goto bad;
                    171:        if(field->trans == 0)
                    172:                field->trans = ident;
                    173:        if(field->trans != ident)
                    174:                goto bad;
                    175:        if(field->keep == 0)
                    176:                field->keep = all;
                    177:        if(field->keep != all)
                    178:                goto bad;
                    179:        if(field->rflag)
                    180:                goto bad;
                    181:        return;
                    182: bad:
                    183:        fatal("improper modifier with -a","",0);
                    184:        return;
                    185: }
                    186: 
                    187: /* acode is unlike other coding functions.  instead of
                    188:    making a key in the place pointed to by op,
                    189:    it makes a list of field locations.  it might
                    190:    be more honest if op were declared void* */
                    191: 
                    192: struct loc { uchar *from, *to; };
                    193: 
                    194: int
                    195: acode(uchar *ip, uchar *op, int len, struct field *f)
                    196: {
                    197:        struct loc *lp = (struct loc*)op;
                    198:        lp->from = ip;
                    199:        lp->to = ip + len;
                    200:        if(!tab && !f->bflag &&
                    201:           f->begin.fieldno>0 && f->begin.charno==0)
                    202:                lp->from++;
                    203:        return sizeof(*lp);
                    204: }
                    205: 
                    206: int
                    207: doaccum(struct rec *arec, struct rec *brec)
                    208: {
                    209:        int i;
                    210:        struct loc aloc[NF], bloc[NF];
                    211:        fieldcode(data(arec), (uchar*)aloc, arec->dlen,
                    212:                (uchar*)-1, accum, naccum);
                    213:        fieldcode(data(brec), (uchar*)bloc, brec->dlen,
                    214:                (uchar*)-1, accum, naccum);
                    215:        for(i=0; i<naccum; i++)
                    216:                if(!fieldaccum(aloc[i].from, aloc[i].to,
                    217:                               bloc[i].from, bloc[i].to)) {
                    218:                        if(i==0)
                    219:                                warn("sum too long; record kept: ",
                    220:                                     (char*)data(brec), brec->dlen);
                    221:                        else
                    222:                                fatal("sum too long on adding: ",
                    223:                                     (char*)data(brec), brec->dlen);
                    224:                        return 0;
                    225:                }
                    226:        return 1;
                    227: }
                    228: 
                    229: struct rec *
                    230: listaccum(struct rec *head, struct rec *tail)
                    231: {
                    232:        struct rec *q = head;
                    233:        struct rec *p = head;
                    234:        for(;;) {
                    235:                if(q == tail)
                    236:                        break;
                    237:                q = q->next;
                    238:                if(doaccum(p, q))
                    239:                        p->next = q->next;
                    240:                else
                    241:                        p = q;
                    242:        }
                    243:        return p;
                    244: }

unix.superglobalmegacorp.com

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