|
|
1.1 root 1: /*
2: * AWK
3: * Part 3 - execution of the compiled code.
4: */
5:
6: #include "awk.h"
7: #include "y.tab.h"
8:
9: static CHAR *sb; /* String beginning -- evalre */
10: static CHAR toodeep[] = "For/while nesting too deep";
11: CHAR *reexec();
12:
13: /*
14: * Called for each input file
15: * Also, called before the first file
16: * and after the last file.
17: * This routine executes the code for
18: * each input line.
19: */
20: awk(np, fp, fn)
21: register NODE *np;
22: register FILE *fp;
23: CHAR *fn;
24: {
25: CHAR ibuf[MAXRECORD];
26:
27: sassign(FILENAMEp, fn);
28: if (fp == NULL) {
29: lineno = 0;
30: execute(np, NULL);
31: } else {
32: if (fp != stdin)
33: setbuf(fp, inbuf);
34: lineno = 1;
35: setjmp(nextenv);
36: while (awkinput(ibuf, MAXRECORD, fp) != NULL) {
37: iassign(NRp, NRp->t_INT+1);
38: execute(np, ibuf);
39: }
40: if (fp != stdin)
41: fclose(fp);
42: }
43: }
44:
45: /*
46: * Read a record in for
47: * awk.
48: */
49: STRING
50: awkinput(as, lim, fp)
51: STRING as;
52: unsigned lim;
53: register FILE *fp;
54: {
55: register int c;
56: register CHAR *s;
57: register int rs;
58: register STRING ret;
59: register int nf = 0;
60: register int spcflag = 0;
61:
62: if ((rs = RS[0]) == '\0') {
63: rs = '\n';
64: spcflag++;
65: }
66: s = as;
67: while (--lim>0 && (c = getc(fp))!=EOF) {
68: if (c == '\n')
69: lineno++;
70: if (c == rs)
71: if (!spcflag || s==as || s[-1]=='\n')
72: break;
73: *s++ = c;
74: }
75: *s = '\0';
76: ret = c==EOF && s==as ? NULL : as;
77: s = as;
78: if (whitesw) {
79: for (;;) {
80: while (FSMAP[c = *s]) /* pass spaces */
81: s++;
82: if (c == '\0') /* if end of line no field */
83: break;
84: nf++;
85: while ((c = *s) != '\0' && !FSMAP[c]) /* pass field */
86: s++;
87: if (c == '\0')
88: break;
89: }
90: }
91: else if (*s) {
92: for (;;) {
93: nf++;
94: while ((c = *s) != '\0' && !FSMAP[c])
95: s++;
96: if (c == '\0')
97: break;
98: if (FSMAP[c = *s]) /* pass delimeter */
99: s++;
100: if (c == '\0')
101: break;
102: }
103: }
104: iassign(NFp, (INT)nf);
105: return (ret);
106: }
107:
108: /*
109: * This is the root of the execution tree
110: * that handles patterns and actions
111: * and lists of the above.
112: * `s' is the input string.
113: * Free all outstanding nodes accumulated
114: * during execution at the end of this
115: * routine (each input line).
116: */
117: execute(np, s)
118: register NODE *np;
119: register STRING s;
120: {
121: register NODE *xp;
122:
123: inline = s;
124: while (np != NULL) {
125: if (np->n_op == ALIST) {
126: xp = np->n_O1;
127: np = np->n_O2;
128: } else {
129: xp = np;
130: np = NULL;
131: }
132: if (xp->n_op != AROOT)
133: awkerr("Bad op in execute %d", xp->n_op);
134: if (xp->n_O1 != NULL) {
135: if (evalpat(xp->n_O1))
136: if (xp->n_O2 == NULL) {
137: if (!beginflag && !endflag)
138: xprint(&xfield0, NULL);
139: } else
140: evalact(xp->n_O2);
141: } else if (!beginflag && !endflag)
142: evalact(xp->n_O2);
143: }
144: while ((np = tempnodes) != NULL) {
145: tempnodes = np->t_next;
146: freenode(np);
147: }
148: if (inline != s)
149: free(inline);
150: }
151:
152: /*
153: * Evaluate the pattern half
154: * of the expression.
155: */
156: evalpat(np)
157: register NODE *np;
158: {
159: register int ret = 0;
160:
161: if ((beginflag && np->n_op==ABEGIN) || (endflag && np->n_op==AEND))
162: return (1);
163: if (beginflag || endflag)
164: return (0);
165: switch (np->n_op) {
166: case ABEGIN:
167: case AEND:
168: return (0);
169:
170: case ARANGE:
171: if (np->n_flag==0 && evalpat(np->n_O1)) {
172: np->n_flag++;
173: ret = 1;
174: } else if (np->n_flag == 1) {
175: if (evalpat(np->n_O2))
176: np->n_flag = 0;
177: ret = 1;
178: }
179: break;
180:
181: default:
182: ret = evalint(np);
183: break;
184: }
185: return (ret);
186: }
187:
188: /*
189: * Evaluate the action part of the
190: * statement.
191: */
192: evalact(anp)
193: register NODE *anp;
194: {
195: register NODE *np;
196: register int i;
197:
198: again:
199: if (anp == NULL)
200: return;
201: if (anp->n_op == ALIST) {
202: np = anp->n_O1;
203: anp = anp->n_O2;
204: } else {
205: np = anp;
206: anp = NULL;
207: }
208: switch (np->n_op) {
209: case AIF:
210: if (evalint(np->n_O1) != 0)
211: evalact(np->n_O2);
212: else if (np->n_O3 != NULL)
213: evalact(np->n_O3);
214: break;
215:
216: case AWHILE:
217: if (++fwlevel >= NNEST)
218: awkerr(toodeep);
219: while (evalint(np->n_O1) != 0) {
220: if ((i = setjmp(fwenv[fwlevel])) == ABREAK)
221: break;
222: else if (i == ACONTIN)
223: continue;
224: evalact(np->n_O2);
225: }
226: fwlevel--;
227: break;
228:
229: case AFOR:
230: if (++fwlevel >= NNEST)
231: awkerr(toodeep);
232: if (np->n_O1 != NULL)
233: evalact(np->n_O1);
234: for ( ; evalint(np->n_O2); evalact(np->n_O3)) {
235: if ((i = setjmp(fwenv[fwlevel])) == ABREAK)
236: break;
237: else if (i == ACONTIN)
238: continue;
239: evalact(np->n_O4);
240: }
241: fwlevel--;
242: break;
243:
244: case AFORIN:
245: if (++fwlevel >= NNEST)
246: awkerr(toodeep);
247: xforin(np->n_O1, np->n_O2, np->n_O3);
248: fwlevel--;
249: break;
250:
251: case ABREAK:
252: case ACONTIN:
253: i = np->n_op;
254: if (fwlevel < 0)
255: awkwarn("No for or while for %s",
256: i==ABREAK ? "break" : "continue");
257: else
258: longjmp(fwenv[fwlevel], i);
259: break;
260:
261: case ANEXT:
262: longjmp(nextenv, 1);
263: break;
264:
265: case AEXIT:
266: if (!exitflag)
267: awkexit(0);
268: break;
269:
270: case APRINT:
271: xprint(np->n_O1, np->n_O2);
272: break;
273:
274: case APRINTF:
275: xprintf(np->n_O1, np->n_O2, NULL);
276: break;
277:
278: default:
279: evalexpr(np);
280: }
281: while ((np = tempnodes) != NULL) {
282: tempnodes = np->t_next;
283: freenode(np);
284: }
285: goto again;
286: }
287:
288: /*
289: * Evaluate an expression.
290: */
291: NODE *
292: evalexpr(np)
293: register NODE *np;
294: {
295: register NODE *tnp;
296: register int i;
297:
298: switch (np->n_op) {
299: case ATERM:
300: break;
301:
302: case AARRAY:
303: np = xarray(np->n_O1, np->n_O2);
304: break;
305:
306: case AFIELD:
307: np = xfield((int)evalint(np->n_O1), NULL);
308: break;
309:
310: case AFUNC:
311: i = fnargs(tnp = np->n_O2);
312: np = np->n_O1;
313: if (i<np->t_MINARG || (np->t_MAXARG!=-1 && i>np->t_MAXARG))
314: awkerr("Too %s arguments: %s",
315: i<np->t_MINARG ? "few" : "many", np->t_name);
316: np = (*np->t_FUNC)(tnp, i);
317: break;
318:
319: case AREMAT:
320: case ARENMAT:
321: i = evalre(np->n_O2, evalstring(np->n_O1));
322: if (np->n_op == ARENMAT)
323: i = !i;
324: np = inode((INT)i);
325: break;
326:
327: case ARE:
328: np = inode((INT)evalre(np->n_O1, inline));
329: break;
330:
331: case ACONC:
332: np = xconc(np->n_O1, np->n_O2);
333: break;
334:
335: case AADD:
336: np = xadd(evalexpr(np->n_O1), evalexpr(np->n_O2));
337: break;
338:
339: case ASUB:
340: np = xsub(evalexpr(np->n_O1), evalexpr(np->n_O2));
341: break;
342:
343: case AMUL:
344: np = xmul(evalexpr(np->n_O1), evalexpr(np->n_O2));
345: break;
346:
347: case ANEG:
348: np = xneg(evalexpr(np->n_O1));
349: break;
350:
351: case ADIV:
352: np = xdiv(evalexpr(np->n_O1), evalexpr(np->n_O2));
353: break;
354:
355: case AMOD:
356: np = xmod(evalexpr(np->n_O1), evalexpr(np->n_O2));
357: break;
358:
359: case AEQ:
360: case ANE:
361: case AGT:
362: case AGE:
363: case ALT:
364: case ALE:
365: np = xcmp(np->n_O1, np->n_O2, np->n_op);
366: break;
367:
368: case AOROR:
369: np = inode((INT)(evalint(np->n_O1) || evalint(np->n_O2)));
370: break;
371:
372: case AANDAND:
373: np = inode((INT)(evalint(np->n_O1) && evalint(np->n_O2)));
374: break;
375:
376: case ANOT:
377: np = inode((INT)(!evalint(np->n_O1)));
378: break;
379:
380: case AASGN:
381: np = xassign(np->n_O1, evalexpr(np->n_O2));
382: break;
383:
384: case AINCA:
385: np = xinca(np->n_O1);
386: break;
387:
388: case ADECA:
389: np = xdeca(np->n_O1);
390: break;
391:
392: default:
393: awkerr("Bad op in evalexpr %d", np->n_op);
394: }
395: return (np);
396: }
397:
398: /*
399: * Evaluate an expression and
400: * return the resultant string.
401: */
402: CHAR *
403: evalstring(np)
404: register NODE *np;
405: {
406: static CHAR numbuf[100];
407:
408: np = evalexpr(np);
409: if (np->n_flag & T_NUM) {
410: if (np->n_flag & T_INT)
411: sprintf(numbuf, "%ld", np->t_INT);
412: else
413: sprintf(numbuf, "%.6g", np->t_FLOAT);
414: return (numbuf);
415: } else
416: return (np->t_STRING);
417: }
418:
419: /*
420: * Evaluate an expression and
421: * return the resultant INT.
422: */
423: INT
424: evalint(np)
425: register NODE *np;
426: {
427: np = evalexpr(np);
428: if (np->n_flag & T_NUM) {
429: if (np->n_flag & T_INT)
430: return (np->t_INT); else
431: return (np->t_FLOAT);
432: } else
433: return (stoi(np->t_STRING));
434: }
435:
436: /*
437: * Evaluate an expression and
438: * return the resultant FLOAT.
439: */
440: FLOAT
441: evalfloat(np)
442: register NODE *np;
443: {
444: np = evalexpr(np);
445: if (np->n_flag & T_NUM) {
446: if (np->n_flag & T_INT)
447: return (np->t_INT); else
448: return (np->t_FLOAT);
449: } else
450: return (stof(np->t_STRING));
451: }
452:
453: /*
454: * Called to evaluate a regular expression
455: * with the given string.
456: */
457: evalre(np, s)
458: register NODE *np;
459: register CHAR *s;
460: {
461: sb = s;
462: if (np!=NULL && np->n_op==ARBOL)
463: return (reexec(np, s) != NULL);
464: s--;
465: do {
466: if (reexec(np, ++s) != NULL)
467: return (1);
468: } while (*s!='\n' && *s!='\0');
469: return (0);
470: }
471:
472: /*
473: * Internal regular expression
474: * execution routines
475: */
476: CHAR *
477: reexec(np, s)
478: register NODE *np;
479: register CHAR *s;
480: {
481: register c;
482: register CHAR *ss, *es;
483:
484: for ( ; np != NULL; np = np->n_O3)
485: switch (np->n_op) {
486: case ARBOL:
487: if (s != sb)
488: return (NULL);
489: break;
490:
491: case AREOL:
492: if (*s!='\n' && *s!='\0')
493: return (NULL);
494: break;
495:
496: case ARANY:
497: c = *s++;
498: if (c=='\n' || c=='\0')
499: return (NULL);
500: break;
501:
502: case ARDCHAR:
503: if (islower(np->n_o1.n_char)) {
504: if (isupper(c = *s++))
505: c = tolower(c);
506: if (c != np->n_o1.n_char)
507: return (NULL);
508: break;
509: }
510: case ARCHAR:
511: c = *s++;
512: if (c != np->n_o1.n_char)
513: return (NULL);
514: break;
515:
516: case ARDCLASS:
517: if (isupper(c = *s++))
518: c = tolower(c);
519: if ((np->n_o1.n_charp[c/NBPC] & (1<<(c%NBPC))) == 0)
520: return (NULL);
521: break;
522:
523: case ARCLASS:
524: c = *s++;
525: if ((np->n_o1.n_charp[c/NBPC] & (1<<(c%NBPC))) == 0)
526: return (NULL);
527: break;
528:
529: case AROR:
530: ss = s;
531: if ((s = reexec(np->n_O1, s)) == NULL)
532: if ((s = reexec(np->n_O2, ss))==NULL)
533: return (NULL);
534: break;
535:
536: case ARCLOS:
537: ss = s;
538: while ((es = reexec(np->n_O1, s)) != NULL)
539: s = es;
540: while (s >= ss)
541: if ((es = reexec(np->n_O3, s--))!=NULL)
542: return (es);
543: return (NULL);
544:
545: case ARNECL:
546: ss = s;
547: while ((es = reexec(np->n_O1, s)) != NULL)
548: s = es;
549: while (s > ss)
550: if ((es = reexec(np->n_O3, s--))!=NULL)
551: return (es);
552: return (NULL);
553:
554: case ARZOCL:
555: ss = s;
556: if ((es = reexec(np->n_O1, s)) != NULL)
557: s = es;
558: while (s >= ss)
559: if ((es = reexec(np->n_O3, s--))!=NULL)
560: return (es);
561: return (NULL);
562:
563: default:
564: awkerr("RE bad op %d", np->n_op);
565: }
566: return (s);
567: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.