|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.