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