|
|
1.1 root 1: /*
2: Copyright (c) 1989 AT&T
3: All Rights Reserved
4:
5: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T.
6:
7: The copyright notice above does not evidence any
8: actual or intended publication of such source code.
9: */
10:
11: #define DEBUG
12: #include <stdio.h>
13: #include <string.h>
14: #include <ctype.h>
15: #include <errno.h>
16: #include <stdlib.h>
17: #include "awk.h"
18: #include "y.tab.h"
19:
20: #define getfval(p) (((p)->tval & (ARR|FLD|REC|NUM)) == NUM ? (p)->fval : r_getfval(p))
21: #define getsval(p) (((p)->tval & (ARR|FLD|REC|STR)) == STR ? (p)->sval : r_getsval(p))
22:
23: FILE *infile = NULL;
24: uchar *file = (uchar*) "";
25: int recsize = RECSIZE;
26: uchar *recdata;
27: uchar *record;
28: uchar *fields;
29: Cell *fldtab;
30:
31: #define MAXFLD 200
32: int nfields = MAXFLD; /* can be set from commandline in main */
33:
34: int donefld; /* 1 = implies rec broken into fields */
35: int donerec; /* 1 = record is valid (no flds have changed) */
36:
37: int maxfld = 0; /* last used field */
38: int argno = 1; /* current input argument number */
39: extern Awkfloat *ARGC;
40:
41: void recinit(unsigned int n)
42: {
43: static Cell dollar0 = {
44: OCELL, CFLD, (uchar*) "$0", /*recdata*/0, 0.0, REC|STR|DONTFREE};
45: static Cell dollar1 = {
46: OCELL, CFLD, NULL, (uchar*) "", 0.0, FLD|STR|DONTFREE };
47: int i;
48:
49: record = recdata = (uchar *) malloc(n);
50: fields = (uchar *) malloc(n);
51: fldtab = (Cell *) malloc(nfields * sizeof(Cell));
52: if (recdata == NULL || fields == NULL || fldtab == NULL)
53: ERROR "out of space for $0 and fields" FATAL;
54: fldtab[0] = dollar0;
55: fldtab[0].sval = recdata;
56: for (i = 1; i < nfields; i++)
57: fldtab[i] = dollar1;
58: }
59:
60: void initgetrec(void)
61: {
62: int i;
63: uchar *p;
64:
65: for (i = 1; i < *ARGC; i++) {
66: if (!isclvar(p = getargv(i))) /* find 1st real filename */
67: return;
68: setclvar(p); /* a commandline assignment before filename */
69: argno++;
70: }
71: infile = stdin; /* no filenames, so use stdin */
72: /* *FILENAME = file = (uchar*) "-"; */
73: }
74:
75: getrec(uchar *buf)
76: {
77: int c;
78: static int firsttime = 1;
79:
80: if (firsttime) {
81: firsttime = 0;
82: initgetrec();
83: }
84: dprintf( ("RS=<%s>, FS=<%s>, ARGC=%g, FILENAME=%s\n",
85: *RS, *FS, *ARGC, *FILENAME) );
86: donefld = 0;
87: donerec = 1;
88: buf[0] = 0;
89: while (argno < *ARGC || infile == stdin) {
90: dprintf( ("argno=%d, file=|%s|\n", argno, file) );
91: if (infile == NULL) { /* have to open a new file */
92: file = getargv(argno);
93: if (*file == '\0') { /* it's been zapped */
94: argno++;
95: continue;
96: }
97: if (isclvar(file)) { /* a var=value arg */
98: setclvar(file);
99: argno++;
100: continue;
101: }
102: *FILENAME = file;
103: dprintf( ("opening file %s\n", file) );
104: if (*file == '-' && *(file+1) == '\0')
105: infile = stdin;
106: else if ((infile = fopen((char *)file, "r")) == NULL)
107: ERROR "can't open file %s", file FATAL;
108: setfval(fnrloc, 0.0);
109: }
110: c = readrec(buf, recsize, infile);
111: if (c != 0 || buf[0] != '\0') { /* normal record */
112: if (buf == record) {
113: if (!(recloc->tval & DONTFREE))
114: xfree(recloc->sval);
115: recloc->sval = record;
116: recloc->tval = REC | STR | DONTFREE;
117: if (isnumber(recloc->sval)) {
118: recloc->fval = atof(recloc->sval);
119: recloc->tval |= NUM;
120: }
121: }
122: setfval(nrloc, nrloc->fval+1);
123: setfval(fnrloc, fnrloc->fval+1);
124: return 1;
125: }
126: /* EOF arrived on this file; set up next */
127: if (infile != stdin)
128: fclose(infile);
129: infile = NULL;
130: argno++;
131: }
132: return 0; /* true end of file */
133: }
134:
135: readrec(uchar *buf, int bufsize, FILE *inf) /* read one record into buf */
136: {
137: register int sep, c;
138: register uchar *rr;
139: register int nrr;
140:
141: if ((sep = **RS) == 0) {
142: sep = '\n';
143: while ((c=getc(inf)) == '\n' && c != EOF) /* skip leading \n's */
144: ;
145: if (c != EOF)
146: ungetc(c, inf);
147: }
148: for (rr = buf, nrr = bufsize; ; ) {
149: for (; (c=getc(inf)) != sep && c != EOF; *rr++ = c)
150: if (--nrr < 0)
151: ERROR "input record `%.30s...' too long; try -mr n", buf FATAL;
152: if (**RS == sep || c == EOF)
153: break;
154: if ((c = getc(inf)) == '\n' || c == EOF) /* 2 in a row */
155: break;
156: *rr++ = '\n';
157: *rr++ = c;
158: }
159: if (rr > buf + bufsize)
160: ERROR "input record `%.30s...' too long; try -mr n", buf FATAL;
161: *rr = 0;
162: dprintf( ("readrec saw <%s>, returns %d\n", buf, c == EOF && rr == buf ? 0 : 1) );
163: return c == EOF && rr == buf ? 0 : 1;
164: }
165:
166: uchar *getargv(int n) /* get ARGV[n] */
167: {
168: Cell *x;
169: uchar *s, temp[10];
170: extern Array *ARGVtab;
171:
172: sprintf((char *)temp, "%d", n);
173: x = setsymtab(temp, "", 0.0, STR, ARGVtab);
174: s = getsval(x);
175: dprintf( ("getargv(%d) returns |%s|\n", n, s) );
176: return s;
177: }
178:
179: void setclvar(uchar *s) /* set var=value from s */
180: {
181: uchar *p;
182: Cell *q;
183:
184: for (p=s; *p != '='; p++)
185: ;
186: *p++ = 0;
187: p = qstring(p, '\0');
188: q = setsymtab(s, p, 0.0, STR, symtab);
189: setsval(q, p);
190: if (isnumber(q->sval)) {
191: q->fval = atof(q->sval);
192: q->tval |= NUM;
193: }
194: dprintf( ("command line set %s to |%s|\n", s, p) );
195: }
196:
197:
198: void fldbld(void)
199: {
200: register uchar *r, *fr, sep;
201: Cell *p;
202: int i;
203:
204: if (donefld)
205: return;
206: if (!(recloc->tval & STR))
207: getsval(recloc);
208: r = recloc->sval; /* was record! */
209: fr = fields;
210: i = 0; /* number of fields accumulated here */
211: if (strlen(*FS) > 1) { /* it's a regular expression */
212: i = refldbld(r, *FS);
213: } else if ((sep = **FS) == ' ') {
214: for (i = 0; ; ) {
215: while (*r == ' ' || *r == '\t' || *r == '\n')
216: r++;
217: if (*r == 0)
218: break;
219: i++;
220: if (i >= nfields)
221: break;
222: if (!(fldtab[i].tval & DONTFREE))
223: xfree(fldtab[i].sval);
224: fldtab[i].sval = fr;
225: fldtab[i].tval = FLD | STR | DONTFREE;
226: do
227: *fr++ = *r++;
228: while (*r != ' ' && *r != '\t' && *r != '\n' && *r != '\0');
229: *fr++ = 0;
230: }
231: *fr = 0;
232: } else if (*r != 0) { /* if 0, it's a null field */
233: for (;;) {
234: i++;
235: if (i >= nfields)
236: break;
237: if (!(fldtab[i].tval & DONTFREE))
238: xfree(fldtab[i].sval);
239: fldtab[i].sval = fr;
240: fldtab[i].tval = FLD | STR | DONTFREE;
241: while (*r != sep && *r != '\n' && *r != '\0') /* \n always a separator */
242: *fr++ = *r++;
243: *fr++ = 0;
244: if (*r++ == 0)
245: break;
246: }
247: *fr = 0;
248: }
249: if (i >= nfields)
250: ERROR "record `%.20s...' has too many fields; try -mf n", record FATAL;
251: /* clean out junk from previous record */
252: cleanfld(i, maxfld);
253: maxfld = i;
254: donefld = 1;
255: for (p = fldtab+1; p <= fldtab+maxfld; p++) {
256: if(isnumber(p->sval)) {
257: p->fval = atof(p->sval);
258: p->tval |= NUM;
259: }
260: }
261: setfval(nfloc, (Awkfloat) maxfld);
262: if (dbg)
263: for (p = fldtab; p <= fldtab+maxfld; p++)
264: printf("field %d: |%s|\n", p-fldtab, p->sval);
265: }
266:
267: void cleanfld(int n1, int n2) /* clean out fields n1..n2 inclusive */
268: {
269: static uchar *nullstat = (uchar *) "";
270: register Cell *p, *q;
271:
272: for (p = &fldtab[n2], q = &fldtab[n1]; p > q; p--) {
273: if (!(p->tval & DONTFREE))
274: xfree(p->sval);
275: p->tval = FLD | STR | DONTFREE;
276: p->sval = nullstat;
277: }
278: }
279:
280: void newfld(int n) /* add field n (after end) */
281: {
282: if (n >= nfields)
283: ERROR "creating too many fields; try -mf n", record FATAL;
284: cleanfld(maxfld, n);
285: maxfld = n;
286: setfval(nfloc, (Awkfloat) n);
287: }
288:
289: refldbld(uchar *rec, uchar *fs) /* build fields from reg expr in FS */
290: {
291: uchar *fr;
292: int i, tempstat;
293: fa *pfa;
294:
295: fr = fields;
296: *fr = '\0';
297: if (*rec == '\0')
298: return 0;
299: pfa = makedfa(fs, 1);
300: dprintf( ("into refldbld, rec = <%s>, pat = <%s>\n", rec, fs) );
301: tempstat = pfa->initstat;
302: for (i = 1; i < nfields; i++) {
303: if (!(fldtab[i].tval & DONTFREE))
304: xfree(fldtab[i].sval);
305: fldtab[i].tval = FLD | STR | DONTFREE;
306: fldtab[i].sval = fr;
307: dprintf( ("refldbld: i=%d\n", i) );
308: if (nematch(pfa, rec)) {
309: pfa->initstat = 2;
310: dprintf( ("match %s (%d chars)\n", patbeg, patlen) );
311: strncpy(fr, rec, patbeg-rec);
312: fr += patbeg - rec + 1;
313: *(fr-1) = '\0';
314: rec = patbeg + patlen;
315: } else {
316: dprintf( ("no match %s\n", rec) );
317: strcpy(fr, rec);
318: pfa->initstat = tempstat;
319: break;
320: }
321: }
322: return i;
323: }
324:
325: void recbld(void)
326: {
327: int i;
328: register uchar *r, *p;
329: static uchar *rec = 0;
330:
331: if (donerec == 1)
332: return;
333: if (rec == 0) {
334: rec = (uchar *) malloc(recsize);
335: if (rec == 0)
336: ERROR "out of space building $0, record size %d", recsize FATAL;
337: }
338: r = rec;
339: for (i = 1; i <= *NF; i++) {
340: p = getsval(&fldtab[i]);
341: while (r < rec+recsize-1 && (*r = *p++))
342: r++;
343: if (i < *NF)
344: for (p = *OFS; r < rec+recsize-1 && (*r = *p++); )
345: r++;
346: }
347: if (r > rec + recsize - 1)
348: ERROR "built giant record `%.20s...'; try -mr n", record FATAL;
349: *r = '\0';
350: dprintf( ("in recbld FS=%o, recloc=%o\n", **FS, recloc) );
351: recloc->tval = REC | STR | DONTFREE;
352: recloc->sval = record = rec;
353: dprintf( ("in recbld FS=%o, recloc=%o\n", **FS, recloc) );
354: dprintf( ("recbld = |%s|\n", record) );
355: donerec = 1;
356: }
357:
358: Cell *fieldadr(int n)
359: {
360: if (n < 0 || n >= nfields)
361: ERROR "trying to access field %d; try -mf n", n FATAL;
362: return(&fldtab[n]);
363: }
364:
365: int errorflag = 0;
366: char errbuf[200];
367:
368: void yyerror(uchar *s)
369: {
370: extern uchar *cmdname, *curfname;
371: static int been_here = 0;
372:
373: if (been_here++ > 2)
374: return;
375: fprintf(stderr, "%s: %s", cmdname, s);
376: fprintf(stderr, " at source line %d", lineno);
377: if (curfname != NULL)
378: fprintf(stderr, " in function %s", curfname);
379: fprintf(stderr, "\n");
380: errorflag = 2;
381: eprint();
382: }
383:
384: void fpecatch(int n)
385: {
386: ERROR "floating point exception %d", n FATAL;
387: }
388:
389: extern int bracecnt, brackcnt, parencnt;
390:
391: void bracecheck(void)
392: {
393: int c;
394: static int beenhere = 0;
395:
396: if (beenhere++)
397: return;
398: while ((c = input()) != EOF && c != '\0')
399: bclass(c);
400: bcheck2(bracecnt, '{', '}');
401: bcheck2(brackcnt, '[', ']');
402: bcheck2(parencnt, '(', ')');
403: }
404:
405: void bcheck2(int n, int c1, int c2)
406: {
407: if (n == 1)
408: fprintf(stderr, "\tmissing %c\n", c2);
409: else if (n > 1)
410: fprintf(stderr, "\t%d missing %c's\n", n, c2);
411: else if (n == -1)
412: fprintf(stderr, "\textra %c\n", c2);
413: else if (n < -1)
414: fprintf(stderr, "\t%d extra %c's\n", -n, c2);
415: }
416:
417: void error(int f, char *s)
418: {
419: extern Node *curnode;
420: extern uchar *cmdname;
421:
422: fflush(stdout);
423: fprintf(stderr, "%s: ", cmdname);
424: fprintf(stderr, "%s", s);
425: fprintf(stderr, "\n");
426: if (compile_time != 2 && NR && *NR > 0) {
427: fprintf(stderr, " input record number %g", *FNR);
428: if (strcmp(*FILENAME, "-") != 0)
429: fprintf(stderr, ", file %s", *FILENAME);
430: fprintf(stderr, "\n");
431: }
432: if (compile_time != 2 && curnode)
433: fprintf(stderr, " source line number %d\n", curnode->lineno);
434: else if (compile_time != 2 && lineno)
435: fprintf(stderr, " source line number %d\n", lineno);
436: eprint();
437: if (f) {
438: if (dbg > 1)
439: abort();
440: exit(2);
441: }
442: }
443:
444: void eprint(void) /* try to print context around error */
445: {
446: uchar *p, *q;
447: int c;
448: static int been_here = 0;
449: extern uchar ebuf[300], *ep;
450:
451: if (compile_time == 2 || compile_time == 0 || been_here++ > 0)
452: return;
453: p = ep - 1;
454: if (p > ebuf && *p == '\n')
455: p--;
456: for ( ; p > ebuf && *p != '\n' && *p != '\0'; p--)
457: ;
458: while (*p == '\n')
459: p++;
460: fprintf(stderr, " context is\n\t");
461: for (q=ep-1; q>=p && *q!=' ' && *q!='\t' && *q!='\n'; q--)
462: ;
463: for ( ; p < q; p++)
464: if (*p)
465: putc(*p, stderr);
466: fprintf(stderr, " >>> ");
467: for ( ; p < ep; p++)
468: if (*p)
469: putc(*p, stderr);
470: fprintf(stderr, " <<< ");
471: if (*ep)
472: while ((c = input()) != '\n' && c != '\0' && c != EOF) {
473: putc(c, stderr);
474: bclass(c);
475: }
476: putc('\n', stderr);
477: ep = ebuf;
478: }
479:
480: void bclass(int c)
481: {
482: switch (c) {
483: case '{': bracecnt++; break;
484: case '}': bracecnt--; break;
485: case '[': brackcnt++; break;
486: case ']': brackcnt--; break;
487: case '(': parencnt++; break;
488: case ')': parencnt--; break;
489: }
490: }
491:
492: double errcheck(double x, uchar *s)
493: {
494: extern int errno;
495:
496: if (errno == EDOM) {
497: errno = 0;
498: ERROR "%s argument out of domain", s WARNING;
499: x = 1;
500: } else if (errno == ERANGE) {
501: errno = 0;
502: ERROR "%s result out of range", s WARNING;
503: x = 1;
504: }
505: return x;
506: }
507:
508: isclvar(uchar *s) /* is s of form var=something? */
509: {
510: uchar *os = s;
511:
512: if (!isalpha(*s) && *s != '_')
513: return 0;
514: for ( ; *s; s++)
515: if (!(isalnum(*s) || *s == '_'))
516: break;
517: return *s == '=' && s > os && *(s+1) != '=';
518: }
519:
520: #define MAXEXPON 38 /* maximum exponent for fp number */
521:
522: isnumber(uchar *s)
523: {
524: register int d1, d2;
525: int point;
526: uchar *es;
527:
528: d1 = d2 = point = 0;
529: while (*s == ' ' || *s == '\t' || *s == '\n')
530: s++;
531: if (*s == '\0')
532: return(0); /* empty stuff isn't number */
533: if (*s == '+' || *s == '-')
534: s++;
535: if (!isdigit(*s) && *s != '.')
536: return(0);
537: if (isdigit(*s)) {
538: do {
539: d1++;
540: s++;
541: } while (isdigit(*s));
542: }
543: if (*s == '.') {
544: point++;
545: s++;
546: }
547: if (isdigit(*s)) {
548: d2++;
549: do {
550: s++;
551: } while (isdigit(*s));
552: }
553: if (!(d1 || point && d2))
554: return(0);
555: if (*s == 'e' || *s == 'E') {
556: s++;
557: if (*s == '+' || *s == '-')
558: s++;
559: if (!isdigit(*s))
560: return(0);
561: es = s;
562: do {
563: s++;
564: } while (isdigit(*s));
565: if (s - es > 2)
566: return(0);
567: else if (s - es == 2 && (int)(10 * (*es-'0') + *(es+1)-'0') >= MAXEXPON)
568: return(0);
569: }
570: while (*s == ' ' || *s == '\t' || *s == '\n')
571: s++;
572: if (*s == '\0')
573: return(1);
574: else
575: return(0);
576: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.