|
|
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.