|
|
1.1 root 1: #define tempfree(x) if (istemp(x)) tfree(x); else
2:
3: /* #define execute(p) (isvalue(p) ? (Cell *)((p)->narg[0]) : r_execute(p)) */
4: #define execute(p) r_execute(p)
5:
6: #define DEBUG
7: #include "awk.h"
8: #include <math.h>
9: #include "y.tab.h"
10: #include <stdio.h>
11: #include <ctype.h>
12: #include <setjmp.h>
13:
14: #ifdef _NFILE
15: #define FILENUM (_NFILE-5) /* a guess about max number of open files */
16: #else
17: #define FILENUM 15
18: #endif
19:
20: extern double modf();
21:
22: jmp_buf env;
23:
24: #define getfval(p) (((p)->tval & (ARR|FLD|REC|NUM)) == NUM ? (p)->fval : r_getfval(p))
25: #define getsval(p) (((p)->tval & (ARR|FLD|REC|STR)) == STR ? (p)->sval : r_getsval(p))
26:
27: extern Awkfloat r_getfval();
28: extern uchar *r_getsval();
29: extern Cell *r_execute(), *fieldel(), *dopa2(), *gettemp(), *copycell();
30: extern FILE *openfile(), *redirect();
31: extern double errcheck();
32:
33: #define PA2NUM 29
34: int pairstack[PA2NUM], paircnt;
35: Node *winner = NULL;
36: Cell *tmps;
37:
38: static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM };
39: Cell *true = &truecell;
40: static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM };
41: Cell *false = &falsecell;
42: static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM };
43: Cell *jbreak = &breakcell;
44: static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM };
45: Cell *jcont = &contcell;
46: static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM };
47: Cell *jnext = &nextcell;
48: static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM };
49: Cell *jexit = &exitcell;
50: static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM };
51: Cell *jret = &retcell;
52: static Cell tempcell ={ OCELL, CTEMP, 0, 0, 0.0, NUM };
53:
54: Node *curnode = NULL; /* the node being executed, for debugging */
55:
56: run(a) Node *a;
57: {
58: execute(a);
59: closeall();
60: }
61:
62: Cell *r_execute(u) Node *u;
63: {
64: register Cell *(*proc)();
65: register Cell *x;
66: register Node *a;
67:
68: if (u == NULL)
69: return(true);
70: for (a = u; ; a = a->nnext) {
71: curnode = a;
72: if (isvalue(a) || a->ntype == NFIELD) {
73: x = (Cell *) (a->narg[0]);
74: x->ctype = OCELL;
75: if ((x->tval & FLD) && !donefld)
76: fldbld();
77: else if ((x->tval & REC) && !donerec)
78: recbld();
79: return(x);
80: }
81: if (notlegal(a->nobj)) /* probably a Cell* but too risky to print */
82: error(FATAL, "illegal statement");
83: proc = proctab[a->nobj-FIRSTTOKEN];
84: x = (*proc)(a->narg, a->nobj);
85: if ((x->tval & FLD) && !donefld)
86: fldbld();
87: else if ((x->tval & REC) && !donerec)
88: recbld();
89: if (isexpr(a))
90: return(x);
91: /* a statement, goto next statement */
92: if (isjump(x))
93: return(x);
94: if (a->nnext == (Node *)NULL)
95: return(x);
96: tempfree(x);
97: }
98: }
99:
100:
101: Cell *program(a, n) register Node **a;
102: {
103: register Cell *x;
104:
105: if (setjmp(env) != 0)
106: goto ex;
107: if (a[0]) { /* BEGIN */
108: x = execute(a[0]);
109: if (isexit(x))
110: return(true);
111: if (isjump(x))
112: error(FATAL, "unexpected break, continue or next");
113: tempfree(x);
114: }
115: loop:
116: if (a[1] || a[2])
117: while (getrec(record) > 0) {
118: x = execute(a[1]);
119: if (isexit(x))
120: break;
121: tempfree(x);
122: }
123: ex:
124: if (setjmp(env) != 0)
125: goto ex1;
126: if (a[2]) { /* END */
127: x = execute(a[2]);
128: if (iscont(x)) /* read some more */
129: goto loop;
130: if (isbreak(x) || isnext(x))
131: error(FATAL, "unexpected break or next");
132: tempfree(x);
133: }
134: ex1:
135: return(true);
136: }
137:
138: #define FRAME 100
139: struct Frame {
140: int nargs; /* number of arguments in this call */
141: Cell *fcncell; /* pointer to Cell for function */
142: Cell **args; /* pointer to array of arguments after execute */
143: Cell *retval; /* return value */
144: } frame[FRAME];
145:
146: struct Frame *fp = frame; /* frame pointer. bottom level unused */
147:
148: Cell *call(a, n) Node **a;
149: {
150: int i, ncall, ndef;
151: Node *x;
152: Cell **args, **oargs, *y, *z, *fcn;
153: uchar *s;
154:
155: fcn = execute(a[0]); /* the function itself */
156: s = fcn->nval;
157: if (!isfunc(fcn))
158: error(FATAL, "calling undefined function %s", s);
159: for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */
160: ncall++;
161: ndef = (int) fcn->fval; /* args in defn */
162: dprintf("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, fp-frame);
163: args = (Cell **) Calloc(ndef>ncall ? ndef : ncall, sizeof (Cell *));
164: oargs = (Cell **) Calloc(ndef>ncall ? ndef : ncall, sizeof (Cell *));
165: for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */
166: dprintf("evaluate args[%d], fp=%d:\n", i, fp-frame);
167: y = execute(x);
168: oargs[i] = y;
169: dprintf("args[%d]: %s %f <%s>, t=%o\n",
170: i, y->nval, y->fval, isarr(y) ? "(array)" : (char*) y->sval, y->tval);
171: if (isfunc(y))
172: error(FATAL, "can't use function %s as argument", y->nval);
173: if (!isarr(y)) {
174: args[i] = copycell(y);
175: } else {
176: args[i] = y; /* arrays by ref */
177: }
178: tempfree(y);
179: }
180: for ( ; i < ndef; i++) { /* add null args for ones not provided */
181: args[i] = gettemp();
182: args[i]->sval = (uchar *) "";
183: args[i]->tval = STR|NUM|DONTFREE;
184: args[i]->csub = CCOPY;
185: }
186: fp++; /* now ok to up frame */
187: if (fp >= frame+FRAME)
188: error(FATAL, "function %s nested too deeply", s);
189: fp->fcncell = fcn;
190: fp->args = args;
191: fp->nargs = ndef; /* number defined with (can be more than call) */
192: fp->retval = gettemp();
193:
194: dprintf("start exec of %s, fp=%d\n", s, fp-frame);
195: y = execute((Node *)(fcn->sval)); /* execute body */
196: dprintf("finished exec of %s, fp=%d\n", s, fp-frame);
197:
198: for (i = 0; i < ndef; i++) {
199: Cell *t = fp->args[i];
200: if (isarr(t)) {
201: if (t->csub == CCOPY) {
202: if (i >= ncall) {
203: freesymtab(t);
204: t->csub = CTEMP;
205: } else {
206: oargs[i]->tval = t->tval;
207: oargs[i]->tval &= ~(STR|NUM|DONTFREE);
208: oargs[i]->sval = t->sval;
209: }
210: }
211: } else
212: t->csub = CTEMP;
213: tempfree(t);
214: }
215: xfree(oargs);
216: if (isexit(y) || isnext(y))
217: return y;
218: z = fp->retval; /* return value */
219: dprintf("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval);
220: xfree(fp->args);
221: fp--;
222: tempfree(fcn);
223: return(z);
224: }
225:
226: Cell *copycell(x) /* make a copy of a cell in a temp */
227: Cell *x;
228: {
229: Cell *y;
230:
231: y = gettemp();
232: y->csub = CCOPY; /* prevents freeing until call is over */
233: y->nval = x->nval;
234: y->sval = x->sval ? tostring(x->sval) : NULL;
235: y->fval = x->fval;
236: y->tval = x->tval & ~(CON|FLD|REC); /* copy is not constant or field */
237: return y;
238: }
239:
240: Cell *arg(a) Node **a;
241: {
242: int n;
243:
244: n = (int) a[0]; /* argument number, counting from 0 */
245: dprintf("arg(%d), fp->nargs=%d\n", n, fp->nargs);
246: if (n+1 > fp->nargs)
247: error(FATAL, "argument #%d of function %s was not supplied",
248: n+1, fp->fcncell->nval);
249: return fp->args[n];
250: }
251:
252: Cell *jump(a, n) Node **a;
253: {
254: register Cell *y;
255:
256: switch (n) {
257: case EXIT:
258: if (a[0] != NULL) {
259: y = execute(a[0]);
260: errorflag = getfval(y);
261: tempfree(y);
262: }
263: longjmp(env, 1);
264: case RETURN:
265: if (a[0] != NULL) {
266: y = execute(a[0]);
267: if ((y->tval & (STR|NUM)) == (STR|NUM)) {
268: setsval(fp->retval, getsval(y));
269: fp->retval->fval = getfval(y);
270: fp->retval->tval |= NUM;
271: }
272: else if (y->tval & STR)
273: setsval(fp->retval, getsval(y));
274: else if (y->tval & NUM)
275: setfval(fp->retval, getfval(y));
276: tempfree(y);
277: }
278: return(jret);
279: case NEXT:
280: return(jnext);
281: case BREAK:
282: return(jbreak);
283: case CONTINUE:
284: return(jcont);
285: default:
286: error(FATAL, "illegal jump type %d", n);
287: }
288: }
289:
290: Cell *getline(a, n) Node **a; int n;
291: {
292: /* a[0] is variable, a[1] is operator, a[2] is filename */
293: register Cell *r, *x;
294: uchar buf[RECSIZE];
295: FILE *fp;
296:
297: fflush(stdout); /* in case someone is waiting for a prompt */
298: r = gettemp();
299: if (a[1] != NULL) { /* getline < file */
300: x = execute(a[2]); /* filename */
301: if ((int) a[1] == '|') /* input pipe */
302: a[1] = (Node *) LE; /* arbitrary flag */
303: fp = openfile((int) a[1], getsval(x));
304: tempfree(x);
305: if (fp == NULL)
306: n = -1;
307: else
308: n = readrec(buf, sizeof(buf), fp);
309: if (n <= 0) {
310: ;
311: } else if (a[0] != NULL) { /* getline var <file */
312: setsval(execute(a[0]), buf);
313: } else { /* getline <file */
314: if (!(recloc->tval & DONTFREE))
315: xfree(recloc->sval);
316: strcpy(record, buf);
317: recloc->sval = record;
318: recloc->tval = REC | STR | DONTFREE;
319: donerec = 1; donefld = 0;
320: }
321: } else { /* bare getline; use current input */
322: if (a[0] == NULL) /* getline */
323: n = getrec(record);
324: else { /* getline var */
325: n = getrec(buf);
326: setsval(execute(a[0]), buf);
327: }
328: }
329: setfval(r, (Awkfloat) n);
330: return r;
331: }
332:
333: Cell *getnf(a,n) register Node **a;
334: {
335: if (donefld == 0)
336: fldbld();
337: return (Cell *) a[0];
338: }
339:
340: Cell *array(a,n) register Node **a;
341: {
342: register Cell *x, *y, *z;
343: register uchar *s;
344: register Node *np;
345: uchar buf[RECSIZE];
346:
347: x = execute(a[0]); /* Cell* for symbol table */
348: buf[0] = 0;
349: for (np = a[1]; np; np = np->nnext) {
350: y = execute(np); /* subscript */
351: s = getsval(y);
352: strcat(buf, s);
353: if (np->nnext)
354: strcat(buf, *SUBSEP);
355: tempfree(y);
356: }
357: if (!isarr(x)) {
358: dprintf("making %s into an array\n", x->nval);
359: if (freeable(x))
360: xfree(x->sval);
361: x->tval &= ~(STR|NUM|DONTFREE);
362: x->tval |= ARR;
363: x->sval = (uchar *) makesymtab(NSYMTAB);
364: }
365: z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
366: z->ctype = OCELL;
367: z->csub = CVAR;
368: tempfree(x);
369: return(z);
370: }
371:
372: Cell *delete(a, n) Node **a;
373: {
374: Cell *x, *y;
375: Node *np;
376: uchar buf[RECSIZE], *s;
377:
378: x = execute(a[0]); /* Cell* for symbol table */
379: buf[0] = 0;
380: for (np = a[1]; np; np = np->nnext) {
381: y = execute(np); /* subscript */
382: s = getsval(y);
383: strcat(buf, s);
384: if (np->nnext)
385: strcat(buf, *SUBSEP);
386: tempfree(y);
387: }
388: freeelem(x, buf);
389: tempfree(x);
390: return true;
391: }
392:
393: Cell *intest(a, n) Node **a;
394: {
395: register Cell *x, *ap, *k;
396: Node *p;
397: char buf[RECSIZE];
398: uchar *s;
399:
400: ap = execute(a[1]); /* array name */
401: if (!isarr(ap))
402: error(FATAL, "%s is not an array", ap->nval);
403: buf[0] = 0;
404: for (p = a[0]; p; p = p->nnext) {
405: x = execute(p); /* expr */
406: s = getsval(x);
407: strcat(buf, s);
408: tempfree(x);
409: if (p->nnext)
410: strcat(buf, *SUBSEP);
411: }
412: k = lookup(buf, (Array *) ap->sval);
413: tempfree(ap);
414: if (k == NULL)
415: return(false);
416: else
417: return(true);
418: }
419:
420:
421: Cell *matchop(a,n) Node **a;
422: {
423: register Cell *x, *y;
424: register uchar *s, *t;
425: register int i;
426: extern int match(), pmatch();
427: fa *pfa;
428: int (*mf)() = match, mode = 0;
429:
430: if (n == MATCHFCN) {
431: mf = pmatch;
432: mode = 1;
433: }
434: x = execute(a[1]);
435: s = getsval(x);
436: if (a[0] == 0)
437: i = (*mf)(a[2], s);
438: else {
439: y = execute(a[2]);
440: t = getsval(y);
441: pfa = makedfa(t, mode);
442: i = (*mf)(pfa, s);
443: tempfree(y);
444: }
445: tempfree(x);
446: if (n == MATCHFCN) {
447: int start = patbeg - s + 1;
448: if (patlen < 0)
449: start = 0;
450: setfval(rstartloc, (Awkfloat) start);
451: setfval(rlengthloc, (Awkfloat) patlen);
452: x = gettemp();
453: x->tval = NUM;
454: x->fval = start;
455: return x;
456: } else if (n == MATCH && i == 1 || n == NOTMATCH && i == 0)
457: return(true);
458: else
459: return(false);
460: }
461:
462:
463: Cell *boolop(a,n) Node **a;
464: {
465: register Cell *x, *y;
466: register int i;
467:
468: x = execute(a[0]);
469: i = istrue(x);
470: tempfree(x);
471: switch (n) {
472: case BOR:
473: if (i) return(true);
474: y = execute(a[1]);
475: i = istrue(y);
476: tempfree(y);
477: if (i) return(true);
478: else return(false);
479: case AND:
480: if ( !i ) return(false);
481: y = execute(a[1]);
482: i = istrue(y);
483: tempfree(y);
484: if (i) return(true);
485: else return(false);
486: case NOT:
487: if (i) return(false);
488: else return(true);
489: default:
490: error(FATAL, "unknown boolean operator %d", n);
491: }
492: }
493:
494: Cell *relop(a,n) Node **a;
495: {
496: register int i;
497: register Cell *x, *y;
498: Awkfloat j;
499:
500: x = execute(a[0]);
501: y = execute(a[1]);
502: if (x->tval&NUM && y->tval&NUM) {
503: j = x->fval - y->fval;
504: i = j<0? -1: (j>0? 1: 0);
505: } else {
506: i = strcmp(getsval(x), getsval(y));
507: }
508: tempfree(x);
509: tempfree(y);
510: switch (n) {
511: case LT: if (i<0) return(true);
512: else return(false);
513: case LE: if (i<=0) return(true);
514: else return(false);
515: case NE: if (i!=0) return(true);
516: else return(false);
517: case EQ: if (i == 0) return(true);
518: else return(false);
519: case GE: if (i>=0) return(true);
520: else return(false);
521: case GT: if (i>0) return(true);
522: else return(false);
523: default:
524: error(FATAL, "unknown relational operator %d", n);
525: }
526: }
527:
528: tfree(a) register Cell *a;
529: {
530: if (freeable(a))
531: xfree(a->sval);
532: a->tval = 0;
533: a->ctype = OCELL;
534: a->cnext = tmps;
535: tmps = a;
536: }
537:
538: Cell *gettemp()
539: { int i;
540: register Cell *x;
541:
542: if (!tmps) {
543: tmps = (Cell *) Calloc(100, sizeof(Cell));
544: if (!tmps)
545: error(FATAL, "no space for temporaries");
546: for(i = 1; i < 100; i++)
547: tmps[i-1].cnext = &tmps[i];
548: tmps[i-1].cnext = 0;
549: }
550: x = tmps;
551: tmps = x->cnext;
552: *x = tempcell;
553: return(x);
554: }
555:
556: Cell *indirect(a,n) Node **a;
557: {
558: register Cell *x;
559: register int m;
560: register uchar *s;
561: Cell *fieldadr();
562:
563: x = execute(a[0]);
564: m = getfval(x);
565: if (m == 0 && !isnumber(s = getsval(x))) /* suspicion! */
566: error(FATAL, "illegal field $(%s)", s);
567: tempfree(x);
568: x = fieldadr(m);
569: x->ctype = OCELL;
570: x->csub = CFLD;
571: return(x);
572: }
573:
574: Cell *substr(a, nnn) Node **a;
575: {
576: register int k, m, n;
577: register uchar *s;
578: int temp;
579: register Cell *x, *y;
580:
581: x = execute(a[0]);
582: s = getsval(x);
583: k = strlen(s) + 1;
584: if (k <= 1) {
585: tempfree(x);
586: x = gettemp();
587: setsval(x, "");
588: return(x);
589: }
590: y = execute(a[1]);
591: m = getfval(y);
592: if (m <= 0)
593: m = 1;
594: else if (m > k)
595: m = k;
596: tempfree(y);
597: if (a[2] != 0) {
598: y = execute(a[2]);
599: n = getfval(y);
600: tempfree(y);
601: }
602: else
603: n = k - 1;
604: if (n < 0)
605: n = 0;
606: else if (n > k - m)
607: n = k - m;
608: dprintf("substr: m=%d, n=%d, s=%s\n", m, n, s);
609: y = gettemp();
610: temp = s[n+m-1]; /* with thanks to John Linderman */
611: s[n+m-1] = '\0';
612: setsval(y, s + m - 1);
613: s[n+m-1] = temp;
614: tempfree(x);
615: return(y);
616: }
617:
618: Cell *sindex(a, nnn) Node **a;
619: {
620: register Cell *x, *y, *z;
621: register uchar *s1, *s2, *p1, *p2, *q;
622: Awkfloat v = 0.0;
623:
624: x = execute(a[0]);
625: s1 = getsval(x);
626: y = execute(a[1]);
627: s2 = getsval(y);
628:
629: z = gettemp();
630: for (p1 = s1; *p1 != '\0'; p1++) {
631: for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
632: ;
633: if (*p2 == '\0') {
634: v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */
635: break;
636: }
637: }
638: tempfree(x);
639: tempfree(y);
640: setfval(z, v);
641: return(z);
642: }
643:
644: uchar *format(buf, s, a) uchar *buf, *s; Node *a;
645: {
646: uchar fmt[RECSIZE];
647: register uchar *p, *t, *os;
648: register Cell *x;
649: int flag = 0;
650: Awkfloat xf;
651:
652: os = s;
653: p = buf;
654: while (*s) {
655: if (*s != '%') {
656: *p++ = *s++;
657: continue;
658: }
659: if (*(s+1) == '%') {
660: *p++ = '%';
661: s += 2;
662: continue;
663: }
664: for (t=fmt; (*t++ = *s) != '\0'; s++) {
665: if (islower(*s) && *s != 'l')
666: break;
667: if (*s == '*')
668: error(FATAL, "in %s: %%*... conversion not supported. try concatenation.", os);
669: }
670: *t = '\0';
671: if (t >= fmt + sizeof(fmt))
672: error(FATAL, "format item %.20s... too long", os);
673: switch (*s) {
674: case 'f': case 'e': case 'g':
675: flag = 1;
676: break;
677: case 'd':
678: flag = 2;
679: if(*(s-1) == 'l') break;
680: *(t-1) = 'l';
681: *t = 'd';
682: *++t = '\0';
683: break;
684: case 'o': case 'x': case 'u':
685: flag = *(s-1) == 'l' ? 2 : 3;
686: break;
687: case 's':
688: flag = 4;
689: break;
690: case 'c':
691: flag = 5;
692: break;
693: default:
694: flag = 0;
695: break;
696: }
697: if (flag == 0) {
698: sprintf(p, "%s", fmt);
699: p += strlen(p);
700: continue;
701: }
702: if (a == NULL)
703: error(FATAL, "not enough args in printf(%s)", os);
704: x = execute(a);
705: a = a->nnext;
706: if (flag != 4) /* watch out for converting to numbers! */
707: xf = getfval(x);
708: switch (flag) {
709: case 1: sprintf(p, fmt, xf); break;
710: case 2: sprintf(p, fmt, (long) xf); break;
711: case 3: sprintf(p, fmt, (int) xf); break;
712: case 4: sprintf(p, fmt, getsval(x)); break;
713: case 5: sprintf(p, fmt, (int) xf); break;
714: }
715: tempfree(x);
716: p += strlen(p);
717: s++;
718: }
719: *p = '\0';
720: return buf;
721: }
722:
723: Cell *asprintf(a,n) Node **a;
724: {
725: register Cell *x;
726: register Node *y;
727: uchar buf[RECSIZE];
728:
729: y = a[0]->nnext;
730: x = execute(a[0]);
731: format(buf, getsval(x), y);
732: tempfree(x);
733: x = gettemp();
734: x->sval = tostring(buf);
735: x->tval = STR;
736: return(x);
737: }
738:
739: Cell *aprintf(a,n) Node **a;
740: {
741: FILE *fp;
742: register Cell *x;
743: register Node *y;
744: uchar buf[RECSIZE];
745:
746: y = a[0]->nnext;
747: x = execute(a[0]);
748: format(buf, getsval(x), y);
749: tempfree(x);
750: #ifdef FLUSH
751: if (a[1] == NULL) {
752: fputs(buf, stdout);
753: fflush(stdout);
754: }
755: #else
756: if (a[1] == NULL)
757: fputs(buf, stdout);
758: #endif
759: else {
760: fp = redirect((int)a[1], a[2]);
761: fputs(buf, fp);
762: fflush(fp);
763: }
764: return(true);
765: }
766:
767: Cell *arith(a,n) Node **a;
768: {
769: Awkfloat i, j;
770: double v;
771: register Cell *x, *y, *z;
772:
773: x = execute(a[0]);
774: i = getfval(x);
775: tempfree(x);
776: if (n != UMINUS) {
777: y = execute(a[1]);
778: j = getfval(y);
779: tempfree(y);
780: }
781: z = gettemp();
782: switch (n) {
783: case ADD:
784: i += j;
785: break;
786: case MINUS:
787: i -= j;
788: break;
789: case MULT:
790: i *= j;
791: break;
792: case DIVIDE:
793: if (j == 0)
794: error(FATAL, "division by zero");
795: i /= j;
796: break;
797: case MOD:
798: if (j == 0)
799: error(FATAL, "division by zero in mod");
800: modf(i/j, &v);
801: i = i - j * v;
802: break;
803: case UMINUS:
804: i = -i;
805: break;
806: case POWER:
807: i = errcheck(pow(i, j), "pow");
808: break;
809: default:
810: error(FATAL, "illegal arithmetic operator %d", n);
811: }
812: setfval(z, i);
813: return(z);
814: }
815:
816: Cell *incrdecr(a, n) Node **a;
817: {
818: register Cell *x, *z;
819: register int k;
820: Awkfloat xf;
821:
822: x = execute(a[0]);
823: xf = getfval(x);
824: k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
825: if (n == PREINCR || n == PREDECR) {
826: setfval(x, xf + k);
827: return(x);
828: }
829: z = gettemp();
830: setfval(z, xf);
831: setfval(x, xf + k);
832: tempfree(x);
833: return(z);
834: }
835:
836: Cell *assign(a,n) Node **a;
837: {
838: register Cell *x, *y;
839: Awkfloat xf, yf;
840: double v;
841:
842: y = execute(a[1]);
843: x = execute(a[0]); /* order reversed from before... */
844: if (n == ASSIGN) { /* ordinary assignment */
845: if ((y->tval & (STR|NUM)) == (STR|NUM)) {
846: setsval(x, getsval(y));
847: x->fval = getfval(y);
848: x->tval |= NUM;
849: }
850: else if (y->tval & STR)
851: setsval(x, getsval(y));
852: else if (y->tval & NUM)
853: setfval(x, getfval(y));
854: else
855: funnyvar(y, "read value of");
856: tempfree(y);
857: return(x);
858: }
859: xf = getfval(x);
860: yf = getfval(y);
861: switch (n) {
862: case ADDEQ:
863: xf += yf;
864: break;
865: case SUBEQ:
866: xf -= yf;
867: break;
868: case MULTEQ:
869: xf *= yf;
870: break;
871: case DIVEQ:
872: if (yf == 0)
873: error(FATAL, "division by zero in /=");
874: xf /= yf;
875: break;
876: case MODEQ:
877: if (yf == 0)
878: error(FATAL, "division by zero in %=");
879: modf(xf/yf, &v);
880: xf = xf - yf * v;
881: break;
882: case POWEQ:
883: xf = errcheck(pow(xf, yf), "pow");
884: break;
885: default:
886: error(FATAL, "illegal assignment operator %d", n);
887: break;
888: }
889: tempfree(y);
890: setfval(x, xf);
891: return(x);
892: }
893:
894: Cell *cat(a,q) Node **a;
895: {
896: register Cell *x, *y, *z;
897: register int n1, n2;
898: register uchar *s;
899:
900: x = execute(a[0]);
901: y = execute(a[1]);
902: getsval(x);
903: getsval(y);
904: n1 = strlen(x->sval);
905: n2 = strlen(y->sval);
906: s = (uchar *) Malloc(n1 + n2 + 1);
907: strcpy(s, x->sval);
908: strcpy(s+n1, y->sval);
909: tempfree(y);
910: z = gettemp();
911: z->sval = s;
912: z->tval = STR;
913: tempfree(x);
914: return(z);
915: }
916:
917: Cell *pastat(a,n) Node **a;
918: {
919: register Cell *x;
920:
921: if (a[0] == 0)
922: x = execute(a[1]);
923: else {
924: x = execute(a[0]);
925: if (istrue(x)) {
926: tempfree(x);
927: x = execute(a[1]);
928: }
929: }
930: return x;
931: }
932:
933: Cell *dopa2(a,n) Node **a;
934: {
935: register Cell *x;
936: register int pair;
937:
938: pair = (int) a[3];
939: if (pairstack[pair] == 0) {
940: x = execute(a[0]);
941: if (istrue(x))
942: pairstack[pair] = 1;
943: tempfree(x);
944: }
945: if (pairstack[pair] == 1) {
946: x = execute(a[1]);
947: if (istrue(x))
948: pairstack[pair] = 0;
949: tempfree(x);
950: x = execute(a[2]);
951: return(x);
952: }
953: return(false);
954: }
955:
956: Cell *split(a,nnn) Node **a;
957: {
958: Cell *x, *y, *ap;
959: register uchar *s;
960: register int sep;
961: uchar *t, temp, num[5], *fs;
962: int n, tempstat;
963:
964: y = execute(a[0]); /* source string */
965: s = getsval(y);
966: if (a[2] == 0) /* fs string */
967: fs = *FS;
968: else if ((int) a[3] == STRING) { /* split(str,arr,"string") */
969: x = execute(a[2]);
970: fs = getsval(x);
971: } else if ((int) a[3] == REGEXPR)
972: fs = (uchar*) "(regexpr)"; /* split(str,arr,/regexpr/) */
973: else
974: error(FATAL, "illegal type of split()");
975: sep = *fs;
976: ap = execute(a[1]); /* array name */
977: freesymtab(ap);
978: dprintf("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs);
979: ap->tval &= ~STR;
980: ap->tval |= ARR;
981: ap->sval = (uchar *) makesymtab(NSYMTAB);
982:
983: n = 0;
984: if (*s != '\0' && strlen(fs) > 1 || (int) a[3] == REGEXPR) { /* reg expr */
985: fa *pfa;
986: if ((int) a[3] == REGEXPR) { /* it's ready already */
987: pfa = (fa *) a[2];
988: } else {
989: pfa = makedfa(fs, 1);
990: }
991: if (nematch(pfa,s)) {
992: tempstat = pfa->initstat;
993: pfa->initstat = 2;
994: do {
995: n++;
996: sprintf(num, "%d", n);
997: temp = *patbeg;
998: *patbeg = '\0';
999: if (isnumber(s))
1000: setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
1001: else
1002: setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1003: *patbeg = temp;
1004: s = patbeg + patlen;
1005: if (*(patbeg+patlen-1) == 0 || *s == 0) {
1006: n++;
1007: sprintf(num, "%d", n);
1008: setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
1009: pfa->initstat = tempstat;
1010: goto spdone;
1011: }
1012: } while (nematch(pfa,s));
1013: }
1014: n++;
1015: sprintf(num, "%d", n);
1016: if (isnumber(s))
1017: setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
1018: else
1019: setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1020: spdone:
1021: pfa = NULL;
1022: } else if (sep == ' ') {
1023: for (n = 0; ; ) {
1024: while (*s == ' ' || *s == '\t' || *s == '\n')
1025: s++;
1026: if (*s == 0)
1027: break;
1028: n++;
1029: t = s;
1030: do
1031: s++;
1032: while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
1033: temp = *s;
1034: *s = '\0';
1035: sprintf(num, "%d", n);
1036: if (isnumber(t))
1037: setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1038: else
1039: setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1040: *s = temp;
1041: if (*s != 0)
1042: s++;
1043: }
1044: } else if (*s != 0) {
1045: for (;;) {
1046: n++;
1047: t = s;
1048: while (*s != sep && *s != '\n' && *s != '\0')
1049: s++;
1050: temp = *s;
1051: *s = '\0';
1052: sprintf(num, "%d", n);
1053: if (isnumber(t))
1054: setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1055: else
1056: setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1057: *s = temp;
1058: if (*s++ == 0)
1059: break;
1060: }
1061: }
1062: tempfree(ap);
1063: tempfree(y);
1064: if (a[2] != 0 && (int) a[3] == STRING)
1065: tempfree(x);
1066: x = gettemp();
1067: x->tval = NUM;
1068: x->fval = n;
1069: return(x);
1070: }
1071:
1072: Cell *condexpr(a,n) Node **a;
1073: {
1074: register Cell *x;
1075:
1076: x = execute(a[0]);
1077: if (istrue(x)) {
1078: tempfree(x);
1079: x = execute(a[1]);
1080: } else {
1081: tempfree(x);
1082: x = execute(a[2]);
1083: }
1084: return(x);
1085: }
1086:
1087: Cell *ifstat(a,n) Node **a;
1088: {
1089: register Cell *x;
1090:
1091: x = execute(a[0]);
1092: if (istrue(x)) {
1093: tempfree(x);
1094: x = execute(a[1]);
1095: } else if (a[2] != 0) {
1096: tempfree(x);
1097: x = execute(a[2]);
1098: }
1099: return(x);
1100: }
1101:
1102: Cell *whilestat(a,n) Node **a;
1103: {
1104: register Cell *x;
1105:
1106: for (;;) {
1107: x = execute(a[0]);
1108: if (!istrue(x))
1109: return(x);
1110: tempfree(x);
1111: x = execute(a[1]);
1112: if (isbreak(x)) {
1113: x = true;
1114: return(x);
1115: }
1116: if (isnext(x) || isexit(x) || isret(x))
1117: return(x);
1118: tempfree(x);
1119: }
1120: }
1121:
1122: Cell *dostat(a,n) Node **a;
1123: {
1124: register Cell *x;
1125:
1126: for (;;) {
1127: x = execute(a[0]);
1128: if (isbreak(x)) {
1129: x = true;
1130: return(x);
1131: }
1132: if (isnext(x) || isexit(x) || isret(x))
1133: return(x);
1134: tempfree(x);
1135: x = execute(a[1]);
1136: if (!istrue(x))
1137: return(x);
1138: tempfree(x);
1139: }
1140: }
1141:
1142: Cell *forstat(a,n) Node **a;
1143: {
1144: register Cell *x;
1145:
1146: x = execute(a[0]);
1147: tempfree(x);
1148: for (;;) {
1149: if (a[1]!=0) {
1150: x = execute(a[1]);
1151: if (!istrue(x)) return(x);
1152: else tempfree(x);
1153: }
1154: x = execute(a[3]);
1155: if (isbreak(x)) { /* turn off break */
1156: x = true;
1157: return(x);
1158: }
1159: if (isnext(x) || isexit(x) || isret(x))
1160: return(x);
1161: tempfree(x);
1162: x = execute(a[2]);
1163: tempfree(x);
1164: }
1165: }
1166:
1167: Cell *instat(a, n) Node **a;
1168: {
1169: register Cell *x, *vp, *arrayp, *cp, *ncp;
1170: Array *tp;
1171: int i;
1172:
1173: vp = execute(a[0]);
1174: arrayp = execute(a[1]);
1175: if (!isarr(arrayp))
1176: error(FATAL, "%s is not an array", arrayp->nval);
1177: tp = (Array *) arrayp->sval;
1178: tempfree(arrayp);
1179: for (i = 0; i < tp->size; i++) { /* this routine knows too much */
1180: for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1181: setsval(vp, cp->nval);
1182: ncp = cp->cnext;
1183: x = execute(a[2]);
1184: if (isbreak(x)) {
1185: tempfree(vp);
1186: x = true;
1187: return(x);
1188: }
1189: if (isnext(x) || isexit(x) || isret(x)) {
1190: tempfree(vp);
1191: return(x);
1192: }
1193: tempfree(x);
1194: }
1195: }
1196: return true;
1197: }
1198:
1199: Cell *bltin(a,n) Node **a;
1200: {
1201: register Cell *x, *y;
1202: Awkfloat u;
1203: register int t;
1204: long time();
1205:
1206: t = (int) a[0];
1207: x = execute(a[1]);
1208: switch (t) {
1209: case FLENGTH:
1210: u = (Awkfloat) strlen(getsval(x)); break;
1211: case FLOG:
1212: u = errcheck(log(getfval(x)), "log"); break;
1213: case FINT:
1214: modf(getfval(x), &u); break;
1215: case FEXP:
1216: u = errcheck(exp(getfval(x)), "exp"); break;
1217: case FSQRT:
1218: u = errcheck(sqrt(getfval(x)), "sqrt"); break;
1219: case FSIN:
1220: u = sin(getfval(x)); break;
1221: case FCOS:
1222: u = cos(getfval(x)); break;
1223: case FATAN:
1224: y = execute(a[1]->nnext);
1225: u = atan2(getfval(x), getfval(y));
1226: tempfree(y);
1227: break;
1228: case FSYSTEM:
1229: fflush(stdout); /* in case something buffered already */
1230: u = (Awkfloat) system(getsval(x)) / 256;
1231: break;
1232: case FRAND:
1233: u = (Awkfloat) (rand() % 32767) / 32767.0; break;
1234: case FSRAND:
1235: if (x->tval & REC)
1236: srand(time((long *)0));
1237: else
1238: srand((long)getfval(x));
1239: u = 0;
1240: break;
1241: default:
1242: error(FATAL, "illegal function type %d", t); break;
1243: }
1244: tempfree(x);
1245: x = gettemp();
1246: setfval(x, u);
1247: return(x);
1248: }
1249:
1250: Cell *print(a,n) Node **a;
1251: {
1252: register Node *x;
1253: register Cell *y;
1254: FILE *fp;
1255:
1256: if (a[1] == 0)
1257: fp = stdout;
1258: else
1259: fp = redirect((int)a[1], a[2]);
1260: for (x=a[0]; x!=NULL; x=x->nnext) {
1261: y = execute(x);
1262: fputs(getsval(y), fp);
1263: tempfree(y);
1264: if (x->nnext == NULL)
1265: fputs(*ORS, fp);
1266: else
1267: fputs(*OFS, fp);
1268: }
1269: #ifdef FLUSH
1270: fflush(fp);
1271: #else
1272: if (a[1] != 0)
1273: fflush(fp);
1274: #endif
1275: return(true);
1276: }
1277:
1278: Cell *nullproc() {}
1279:
1280:
1281: struct
1282: {
1283: FILE *fp;
1284: uchar *fname;
1285: int mode; /* '|', 'a', 'w' */
1286: } files[FILENUM];
1287:
1288: FILE *redirect(a, b)
1289: Node *b;
1290: {
1291: FILE *fp;
1292: Cell *x;
1293: uchar *fname;
1294:
1295: x = execute(b);
1296: fname = getsval(x);
1297: fp = openfile(a, fname);
1298: if (fp == NULL)
1299: error(FATAL, "can't open file %s", fname);
1300: tempfree(x);
1301: return fp;
1302: }
1303:
1304: FILE *openfile(a, s)
1305: uchar *s;
1306: {
1307: register int i, m;
1308: register FILE *fp;
1309:
1310: if (*s == '\0')
1311: error(FATAL, "null file name in print or getline");
1312: for (i=0; i < FILENUM; i++)
1313: if (files[i].fname && strcmp(s, files[i].fname) == 0)
1314: if (a == files[i].mode || a==APPEND && files[i].mode==GT)
1315: return files[i].fp;
1316: for (i=0; i < FILENUM; i++)
1317: if (files[i].fp == 0)
1318: break;
1319: if (i >= FILENUM)
1320: error(FATAL, "%s makes too many open files", s);
1321: m = a;
1322: if (a == GT) {
1323: fp = fopen(s, "w");
1324: } else if (a == APPEND) {
1325: fp = fopen(s, "a");
1326: m = GT; /* so can mix > and >> */
1327: } else if (a == '|') { /* output pipe */
1328: fp = popen(s, "w");
1329: } else if (a == LE) { /* input pipe */
1330: fp = popen(s, "r");
1331: } else if (a == LT) { /* getline <file */
1332: fp = fopen(s, "r");
1333: } else
1334: error(FATAL, "illegal redirection");
1335: if (fp != NULL) {
1336: files[i].fname = tostring(s);
1337: files[i].fp = fp;
1338: files[i].mode = m;
1339: }
1340: return fp;
1341: }
1342:
1343:
1344: Cell *closefile(a) Node **a;
1345: {
1346: register Cell *x;
1347: int i;
1348:
1349: x = execute(a[0]);
1350: getsval(x);
1351: for (i = 0; i < FILENUM; i++)
1352: if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) {
1353: if (files[i].mode == '|' || files[i].mode == LE)
1354: pclose(files[i].fp);
1355: else
1356: fclose(files[i].fp);
1357: xfree(files[i].fname);
1358: files[i].fname = NULL; /* watch out for ref thru this */
1359: files[i].fp = NULL;
1360: }
1361: return(x);
1362: }
1363:
1364: closeall()
1365: {
1366: int i;
1367:
1368: for (i = 0; i < FILENUM; i++)
1369: if (files[i].fp) {
1370: if (files[i].mode == '|' || files[i].mode == LE)
1371: pclose(files[i].fp);
1372: else
1373: fclose(files[i].fp);
1374: }
1375: }
1376:
1377: Cell *sub(a, nnn) Node **a;
1378: {
1379: register uchar *sptr, *pb, *q;
1380: register Cell *x, *y;
1381: uchar buf[RECSIZE], *t;
1382: fa *pfa;
1383:
1384: x = execute(a[3]); /* target string */
1385: t = getsval(x);
1386: if (a[0] == 0)
1387: pfa = (fa *) a[1]; /* regular expression */
1388: else {
1389: y = execute(a[1]);
1390: pfa = makedfa(getsval(y), 1);
1391: tempfree(y);
1392: }
1393: if (pmatch(pfa, t)) {
1394: pb = buf;
1395: sptr = t;
1396: while (sptr < patbeg)
1397: *pb++ = *sptr++;
1398: y = execute(a[2]); /* replacement string */
1399: sptr = getsval(y);
1400: while (*sptr != 0 && pb < buf + RECSIZE - 1)
1401: if (*sptr == '\\' && *(sptr+1) == '&') {
1402: sptr++; /* skip \, */
1403: *pb++ = *sptr++; /* add & */
1404: } else if (*sptr == '&') {
1405: sptr++;
1406: for (q = patbeg; q < patbeg+patlen; )
1407: *pb++ = *q++;
1408: } else
1409: *pb++ = *sptr++;
1410: *pb = '\0';
1411: if (pb >= buf + RECSIZE)
1412: error(FATAL, "sub() result %.20s too big", buf);
1413: tempfree(y);
1414: sptr = patbeg + patlen;
1415: if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1)))
1416: while (*pb++ = *sptr++)
1417: ;
1418: if (pb >= buf + RECSIZE)
1419: error(FATAL, "sub() result %.20s too big", buf);
1420: setsval(x, buf);
1421: tempfree(x);
1422: return (true);
1423: }
1424: tempfree(x);
1425: return (false);
1426: }
1427:
1428: Cell *gsub(a, nnn) Node **a;
1429: {
1430: register Cell *x, *y;
1431: register uchar *rptr, *sptr, *t, *pb;
1432: uchar buf[RECSIZE];
1433: register fa *pfa;
1434: int mflag, tempstat, num;
1435:
1436: mflag = 0; /* if mflag == 0, can replace empty string */
1437: num = 0;
1438: x = execute(a[3]); /* target string */
1439: t = getsval(x);
1440: if (a[0] == 0)
1441: pfa = (fa *) a[1]; /* regular expression */
1442: else {
1443: y = execute(a[1]);
1444: pfa = makedfa(getsval(y), 1);
1445: tempfree(y);
1446: }
1447: if (pmatch(pfa, t)) {
1448: tempstat = pfa->initstat;
1449: pfa->initstat = 2;
1450: pb = buf;
1451: y = execute(a[2]); /* replacement string */
1452: rptr = getsval(y);
1453: do {
1454: /*
1455: uchar *p;
1456: int i;
1457: printf("target string: %s, *patbeg = %o, patlen = %d\n",
1458: t, *patbeg, patlen);
1459: printf(" match found: ");
1460: p=patbeg;
1461: for (i=0; i<patlen; i++)
1462: printf("%c", *p++);
1463: printf("\n");
1464: */
1465: if (patlen == 0 && *patbeg != 0) { /* matched empty string */
1466: if (mflag == 0) { /* can replace empty */
1467: num++;
1468: sptr = rptr;
1469: while (*sptr != 0 && pb < buf + RECSIZE-1)
1470: if (*sptr == '\\' && *(sptr+1) == '&') {
1471: sptr++;
1472: *pb++ = *sptr++;
1473: } else if (*sptr == '&') {
1474: uchar *q;
1475: sptr++;
1476: for (q = patbeg; q < patbeg+patlen; )
1477: *pb++ = *q++;
1478: } else
1479: *pb++ = *sptr++;
1480: }
1481: if (*t == 0) /* at end */
1482: goto done;
1483: *pb++ = *t++;
1484: if (pb >= buf + RECSIZE)
1485: error(FATAL, "gsub() result %.20s too big", buf);
1486: mflag = 0;
1487: }
1488: else { /* matched nonempty string */
1489: num++;
1490: sptr = t;
1491: while (sptr < patbeg && pb < buf + RECSIZE-1)
1492: *pb++ = *sptr++;
1493: sptr = rptr;
1494: while (*sptr != 0 && pb < buf + RECSIZE-1)
1495: if (*sptr == '\\' && *(sptr+1) == '&') {
1496: sptr++;
1497: *pb++ = *sptr++;
1498: } else if (*sptr == '&') {
1499: uchar *q;
1500: sptr++;
1501: for (q = patbeg; q < patbeg+patlen; )
1502: *pb++ = *q++;
1503: } else
1504: *pb++ = *sptr++;
1505: t = patbeg + patlen;
1506: if ((*(t-1) == 0) || (*t == 0))
1507: goto done;
1508: if (pb >= buf + RECSIZE)
1509: error(FATAL, "gsub() result %.20s too big", buf);
1510: mflag = 1;
1511: }
1512: } while (pmatch(pfa,t));
1513: sptr = t;
1514: while (*pb++ = *sptr++)
1515: ;
1516: done: tempfree(y);
1517: if (pb >= buf + RECSIZE)
1518: error(FATAL, "gsub() result %.20s too big", buf);
1519: *pb = '\0';
1520: setsval(x, buf);
1521: pfa->initstat = tempstat;
1522: }
1523: tempfree(x);
1524: x = gettemp();
1525: x->tval = NUM;
1526: x->fval = num;
1527: return(x);
1528: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.