File:
[local] /
rpl /
rplawk /
run.c
Revision
1.1:
download - view:
text,
annotated -
select for diffs -
revision graph
Tue Sep 7 12:53:06 2010 UTC (14 years ago) by
bertrand
Branches:
MAIN
CVS tags:
rpl-4_1_9,
rpl-4_1_8,
rpl-4_1_7,
rpl-4_1_6,
rpl-4_1_5,
rpl-4_1_4,
rpl-4_1_3,
rpl-4_1_2,
rpl-4_1_13,
rpl-4_1_12,
rpl-4_1_11,
rpl-4_1_10,
rpl-4_1_1,
rpl-4_1_0,
rpl-4_0_24,
rpl-4_0_22,
rpl-4_0_21,
rpl-4_0_20,
rpl-4_0_19,
rpl-4_0,
HEAD
Ajout d'un AWK interne pour éviter des problèmes sur les OS non Unix.
1: /****************************************************************
2: Copyright (C) Lucent Technologies 1997
3: All Rights Reserved
4:
5: Permission to use, copy, modify, and distribute this software and
6: its documentation for any purpose and without fee is hereby
7: granted, provided that the above copyright notice appear in all
8: copies and that both that the copyright notice and this
9: permission notice and warranty disclaimer appear in supporting
10: documentation, and that the name Lucent Technologies or any of
11: its entities not be used in advertising or publicity pertaining
12: to distribution of the software without specific, written prior
13: permission.
14:
15: LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17: IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18: SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19: WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20: IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22: THIS SOFTWARE.
23: ****************************************************************/
24:
25: #define DEBUG
26: #include <stdio.h>
27: #include <ctype.h>
28: #include <setjmp.h>
29: #include <limits.h>
30: #include <math.h>
31: #include <string.h>
32: #include <stdlib.h>
33: #include <time.h>
34: #include "awk.h"
35: #include "ytab.h"
36:
37: #define tempfree(x) if (istemp(x)) tfree(x); else
38:
39: /*
40: #undef tempfree
41:
42: void tempfree(Cell *p) {
43: if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) {
44: WARNING("bad csub %d in Cell %d %s",
45: p->csub, p->ctype, p->sval);
46: }
47: if (istemp(p))
48: tfree(p);
49: }
50: */
51:
52: /* do we really need these? */
53: /* #ifdef _NFILE */
54: /* #ifndef FOPEN_MAX */
55: /* #define FOPEN_MAX _NFILE */
56: /* #endif */
57: /* #endif */
58: /* */
59: /* #ifndef FOPEN_MAX */
60: /* #define FOPEN_MAX 40 */ /* max number of open files */
61: /* #endif */
62: /* */
63: /* #ifndef RAND_MAX */
64: /* #define RAND_MAX 32767 */ /* all that ansi guarantees */
65: /* #endif */
66:
67: jmp_buf env;
68: extern int pairstack[];
69:
70: Node *winner = NULL; /* root of parse tree */
71: Cell *tmps; /* free temporary cells for execution */
72:
73: static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM };
74: Cell *True = &truecell;
75: static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM };
76: Cell *False = &falsecell;
77: static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM };
78: Cell *jbreak = &breakcell;
79: static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM };
80: Cell *jcont = &contcell;
81: static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM };
82: Cell *jnext = &nextcell;
83: static Cell nextfilecell ={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM };
84: Cell *jnextfile = &nextfilecell;
85: static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM };
86: Cell *jexit = &exitcell;
87: static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM };
88: Cell *jret = &retcell;
89: static Cell tempcell ={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE };
90:
91: Node *curnode = NULL; /* the node being executed, for debugging */
92:
93: /* buffer memory management */
94: int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,
95: const char *whatrtn)
96: /* pbuf: address of pointer to buffer being managed
97: * psiz: address of buffer size variable
98: * minlen: minimum length of buffer needed
99: * quantum: buffer size quantum
100: * pbptr: address of movable pointer into buffer, or 0 if none
101: * whatrtn: name of the calling routine if failure should cause fatal error
102: *
103: * return 0 for realloc failure, !=0 for success
104: */
105: {
106: if (minlen > *psiz) {
107: char *tbuf;
108: int rminlen = quantum ? minlen % quantum : 0;
109: int boff = pbptr ? *pbptr - *pbuf : 0;
110: /* round up to next multiple of quantum */
111: if (rminlen)
112: minlen += quantum - rminlen;
113: tbuf = (char *) realloc(*pbuf, minlen);
114: dprintf( ("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, *pbuf, tbuf) );
115: if (tbuf == NULL) {
116: if (whatrtn)
117: FATAL("out of memory in %s", whatrtn);
118: return 0;
119: }
120: *pbuf = tbuf;
121: *psiz = minlen;
122: if (pbptr)
123: *pbptr = tbuf + boff;
124: }
125: return 1;
126: }
127:
128: void run(Node *a) /* execution of parse tree starts here */
129: {
130: extern void stdinit(void);
131:
132: stdinit();
133: execute(a);
134: closeall();
135: }
136:
137: Cell *execute(Node *u) /* execute a node of the parse tree */
138: {
139: Cell *(*proc)(Node **, int);
140: Cell *x;
141: Node *a;
142:
143: if (u == NULL)
144: return(True);
145: for (a = u; ; a = a->nnext) {
146: curnode = a;
147: if (isvalue(a)) {
148: x = (Cell *) (a->narg[0]);
149: if (isfld(x) && !donefld)
150: fldbld();
151: else if (isrec(x) && !donerec)
152: recbld();
153: return(x);
154: }
155: if (notlegal(a->nobj)) /* probably a Cell* but too risky to print */
156: FATAL("illegal statement");
157: proc = proctab[a->nobj-FIRSTTOKEN];
158: x = (*proc)(a->narg, a->nobj);
159: if (isfld(x) && !donefld)
160: fldbld();
161: else if (isrec(x) && !donerec)
162: recbld();
163: if (isexpr(a))
164: return(x);
165: if (isjump(x))
166: return(x);
167: if (a->nnext == NULL)
168: return(x);
169: tempfree(x);
170: }
171: }
172:
173:
174: Cell *program(Node **a, int n) /* execute an awk program */
175: { /* a[0] = BEGIN, a[1] = body, a[2] = END */
176: Cell *x;
177:
178: if (setjmp(env) != 0)
179: goto ex;
180: if (a[0]) { /* BEGIN */
181: x = execute(a[0]);
182: if (isexit(x))
183: return(True);
184: if (isjump(x))
185: FATAL("illegal break, continue, next or nextfile from BEGIN");
186: tempfree(x);
187: }
188: if (a[1] || a[2])
189: while (getrec(&record, &recsize, 1) > 0) {
190: x = execute(a[1]);
191: if (isexit(x))
192: break;
193: tempfree(x);
194: }
195: ex:
196: if (setjmp(env) != 0) /* handles exit within END */
197: goto ex1;
198: if (a[2]) { /* END */
199: x = execute(a[2]);
200: if (isbreak(x) || isnext(x) || iscont(x))
201: FATAL("illegal break, continue, next or nextfile from END");
202: tempfree(x);
203: }
204: ex1:
205: return(True);
206: }
207:
208: struct Frame { /* stack frame for awk function calls */
209: int nargs; /* number of arguments in this call */
210: Cell *fcncell; /* pointer to Cell for function */
211: Cell **args; /* pointer to array of arguments after execute */
212: Cell *retval; /* return value */
213: };
214:
215: #define NARGS 50 /* max args in a call */
216:
217: struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */
218: int nframe = 0; /* number of frames allocated */
219: struct Frame *fp = NULL; /* frame pointer. bottom level unused */
220:
221: Cell *call(Node **a, int n) /* function call. very kludgy and fragile */
222: {
223: static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE };
224: int i, ncall, ndef;
225: int freed = 0; /* handles potential double freeing when fcn & param share a tempcell */
226: Node *x;
227: Cell *args[NARGS], *oargs[NARGS]; /* BUG: fixed size arrays */
228: Cell *y, *z, *fcn;
229: char *s;
230:
231: fcn = execute(a[0]); /* the function itself */
232: s = fcn->nval;
233: if (!isfcn(fcn))
234: FATAL("calling undefined function %s", s);
235: if (frame == NULL) {
236: fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
237: if (frame == NULL)
238: FATAL("out of space for stack frames calling %s", s);
239: }
240: for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */
241: ncall++;
242: ndef = (int) fcn->fval; /* args in defn */
243: dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) );
244: if (ncall > ndef)
245: WARNING("function %s called with %d args, uses only %d",
246: s, ncall, ndef);
247: if (ncall + ndef > NARGS)
248: FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS);
249: for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */
250: dprintf( ("evaluate args[%d], fp=%d:\n", i, (int) (fp-frame)) );
251: y = execute(x);
252: oargs[i] = y;
253: dprintf( ("args[%d]: %s %f <%s>, t=%o\n",
254: i, NN(y->nval), y->fval, isarr(y) ? "(array)" : NN(y->sval), y->tval) );
255: if (isfcn(y))
256: FATAL("can't use function %s as argument in %s", y->nval, s);
257: if (isarr(y))
258: args[i] = y; /* arrays by ref */
259: else
260: args[i] = copycell(y);
261: tempfree(y);
262: }
263: for ( ; i < ndef; i++) { /* add null args for ones not provided */
264: args[i] = gettemp();
265: *args[i] = newcopycell;
266: }
267: fp++; /* now ok to up frame */
268: if (fp >= frame + nframe) {
269: int dfp = fp - frame; /* old index */
270: frame = (struct Frame *)
271: realloc((char *) frame, (nframe += 100) * sizeof(struct Frame));
272: if (frame == NULL)
273: FATAL("out of space for stack frames in %s", s);
274: fp = frame + dfp;
275: }
276: fp->fcncell = fcn;
277: fp->args = args;
278: fp->nargs = ndef; /* number defined with (excess are locals) */
279: fp->retval = gettemp();
280:
281: dprintf( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) );
282: y = execute((Node *)(fcn->sval)); /* execute body */
283: dprintf( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) );
284:
285: for (i = 0; i < ndef; i++) {
286: Cell *t = fp->args[i];
287: if (isarr(t)) {
288: if (t->csub == CCOPY) {
289: if (i >= ncall) {
290: freesymtab(t);
291: t->csub = CTEMP;
292: tempfree(t);
293: } else {
294: oargs[i]->tval = t->tval;
295: oargs[i]->tval &= ~(STR|NUM|DONTFREE);
296: oargs[i]->sval = t->sval;
297: tempfree(t);
298: }
299: }
300: } else if (t != y) { /* kludge to prevent freeing twice */
301: t->csub = CTEMP;
302: tempfree(t);
303: } else if (t == y && t->csub == CCOPY) {
304: t->csub = CTEMP;
305: tempfree(t);
306: freed = 1;
307: }
308: }
309: tempfree(fcn);
310: if (isexit(y) || isnext(y))
311: return y;
312: if (freed == 0) {
313: tempfree(y); /* don't free twice! */
314: }
315: z = fp->retval; /* return value */
316: dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );
317: fp--;
318: return(z);
319: }
320:
321: Cell *copycell(Cell *x) /* make a copy of a cell in a temp */
322: {
323: Cell *y;
324:
325: y = gettemp();
326: y->csub = CCOPY; /* prevents freeing until call is over */
327: y->nval = x->nval; /* BUG? */
328: if (isstr(x))
329: y->sval = tostring(x->sval);
330: y->fval = x->fval;
331: y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */
332: /* is DONTFREE right? */
333: return y;
334: }
335:
336: Cell *arg(Node **a, int n) /* nth argument of a function */
337: {
338:
339: n = ptoi(a[0]); /* argument number, counting from 0 */
340: dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );
341: if (n+1 > fp->nargs)
342: FATAL("argument #%d of function %s was not supplied",
343: n+1, fp->fcncell->nval);
344: return fp->args[n];
345: }
346:
347: Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */
348: {
349: Cell *y;
350:
351: switch (n) {
352: case EXIT:
353: if (a[0] != NULL) {
354: y = execute(a[0]);
355: errorflag = (int) getfval(y);
356: tempfree(y);
357: }
358: longjmp(env, 1);
359: case RETURN:
360: if (a[0] != NULL) {
361: y = execute(a[0]);
362: if ((y->tval & (STR|NUM)) == (STR|NUM)) {
363: setsval(fp->retval, getsval(y));
364: fp->retval->fval = getfval(y);
365: fp->retval->tval |= NUM;
366: }
367: else if (y->tval & STR)
368: setsval(fp->retval, getsval(y));
369: else if (y->tval & NUM)
370: setfval(fp->retval, getfval(y));
371: else /* can't happen */
372: FATAL("bad type variable %d", y->tval);
373: tempfree(y);
374: }
375: return(jret);
376: case NEXT:
377: return(jnext);
378: case NEXTFILE:
379: nextfile();
380: return(jnextfile);
381: case BREAK:
382: return(jbreak);
383: case CONTINUE:
384: return(jcont);
385: default: /* can't happen */
386: FATAL("illegal jump type %d", n);
387: }
388: return 0; /* not reached */
389: }
390:
391: Cell *awkgetline(Node **a, int n) /* get next line from specific input */
392: { /* a[0] is variable, a[1] is operator, a[2] is filename */
393: Cell *r, *x;
394: extern Cell **fldtab;
395: FILE *fp;
396: char *buf;
397: int bufsize = recsize;
398: int mode;
399:
400: if ((buf = (char *) malloc(bufsize)) == NULL)
401: FATAL("out of memory in getline");
402:
403: fflush(stdout); /* in case someone is waiting for a prompt */
404: r = gettemp();
405: if (a[1] != NULL) { /* getline < file */
406: x = execute(a[2]); /* filename */
407: mode = ptoi(a[1]);
408: if (mode == '|') /* input pipe */
409: mode = LE; /* arbitrary flag */
410: fp = openfile(mode, getsval(x));
411: tempfree(x);
412: if (fp == NULL)
413: n = -1;
414: else
415: n = readrec(&buf, &bufsize, fp);
416: if (n <= 0) {
417: ;
418: } else if (a[0] != NULL) { /* getline var <file */
419: x = execute(a[0]);
420: setsval(x, buf);
421: tempfree(x);
422: } else { /* getline <file */
423: setsval(fldtab[0], buf);
424: if (is_number(fldtab[0]->sval)) {
425: fldtab[0]->fval = atof(fldtab[0]->sval);
426: fldtab[0]->tval |= NUM;
427: }
428: }
429: } else { /* bare getline; use current input */
430: if (a[0] == NULL) /* getline */
431: n = getrec(&record, &recsize, 1);
432: else { /* getline var */
433: n = getrec(&buf, &bufsize, 0);
434: x = execute(a[0]);
435: setsval(x, buf);
436: tempfree(x);
437: }
438: }
439: setfval(r, (Awkfloat) n);
440: free(buf);
441: return r;
442: }
443:
444: Cell *getnf(Node **a, int n) /* get NF */
445: {
446: if (donefld == 0)
447: fldbld();
448: return (Cell *) a[0];
449: }
450:
451: Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
452: {
453: Cell *x, *y, *z;
454: char *s;
455: Node *np;
456: char *buf;
457: int bufsz = recsize;
458: int nsub = strlen(*SUBSEP);
459:
460: if ((buf = (char *) malloc(bufsz)) == NULL)
461: FATAL("out of memory in array");
462:
463: x = execute(a[0]); /* Cell* for symbol table */
464: buf[0] = 0;
465: for (np = a[1]; np; np = np->nnext) {
466: y = execute(np); /* subscript */
467: s = getsval(y);
468: if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "array"))
469: FATAL("out of memory for %s[%s...]", x->nval, buf);
470: strcat(buf, s);
471: if (np->nnext)
472: strcat(buf, *SUBSEP);
473: tempfree(y);
474: }
475: if (!isarr(x)) {
476: dprintf( ("making %s into an array\n", NN(x->nval)) );
477: if (freeable(x))
478: xfree(x->sval);
479: x->tval &= ~(STR|NUM|DONTFREE);
480: x->tval |= ARR;
481: x->sval = (char *) makesymtab(NSYMTAB);
482: }
483: z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
484: z->ctype = OCELL;
485: z->csub = CVAR;
486: tempfree(x);
487: free(buf);
488: return(z);
489: }
490:
491: Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
492: {
493: Cell *x, *y;
494: Node *np;
495: char *s;
496: int nsub = strlen(*SUBSEP);
497:
498: x = execute(a[0]); /* Cell* for symbol table */
499: if (!isarr(x))
500: return True;
501: if (a[1] == 0) { /* delete the elements, not the table */
502: freesymtab(x);
503: x->tval &= ~STR;
504: x->tval |= ARR;
505: x->sval = (char *) makesymtab(NSYMTAB);
506: } else {
507: int bufsz = recsize;
508: char *buf;
509: if ((buf = (char *) malloc(bufsz)) == NULL)
510: FATAL("out of memory in adelete");
511: buf[0] = 0;
512: for (np = a[1]; np; np = np->nnext) {
513: y = execute(np); /* subscript */
514: s = getsval(y);
515: if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "awkdelete"))
516: FATAL("out of memory deleting %s[%s...]", x->nval, buf);
517: strcat(buf, s);
518: if (np->nnext)
519: strcat(buf, *SUBSEP);
520: tempfree(y);
521: }
522: freeelem(x, buf);
523: free(buf);
524: }
525: tempfree(x);
526: return True;
527: }
528:
529: Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
530: {
531: Cell *x, *ap, *k;
532: Node *p;
533: char *buf;
534: char *s;
535: int bufsz = recsize;
536: int nsub = strlen(*SUBSEP);
537:
538: ap = execute(a[1]); /* array name */
539: if (!isarr(ap)) {
540: dprintf( ("making %s into an array\n", ap->nval) );
541: if (freeable(ap))
542: xfree(ap->sval);
543: ap->tval &= ~(STR|NUM|DONTFREE);
544: ap->tval |= ARR;
545: ap->sval = (char *) makesymtab(NSYMTAB);
546: }
547: if ((buf = (char *) malloc(bufsz)) == NULL) {
548: FATAL("out of memory in intest");
549: }
550: buf[0] = 0;
551: for (p = a[0]; p; p = p->nnext) {
552: x = execute(p); /* expr */
553: s = getsval(x);
554: if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "intest"))
555: FATAL("out of memory deleting %s[%s...]", x->nval, buf);
556: strcat(buf, s);
557: tempfree(x);
558: if (p->nnext)
559: strcat(buf, *SUBSEP);
560: }
561: k = lookup(buf, (Array *) ap->sval);
562: tempfree(ap);
563: free(buf);
564: if (k == NULL)
565: return(False);
566: else
567: return(True);
568: }
569:
570:
571: Cell *matchop(Node **a, int n) /* ~ and match() */
572: {
573: Cell *x, *y;
574: char *s, *t;
575: int i;
576: fa *pfa;
577: int (*mf)(fa *, const char *) = match, mode = 0;
578:
579: if (n == MATCHFCN) {
580: mf = pmatch;
581: mode = 1;
582: }
583: x = execute(a[1]); /* a[1] = target text */
584: s = getsval(x);
585: if (a[0] == 0) /* a[1] == 0: already-compiled reg expr */
586: i = (*mf)((fa *) a[2], s);
587: else {
588: y = execute(a[2]); /* a[2] = regular expr */
589: t = getsval(y);
590: pfa = makedfa(t, mode);
591: i = (*mf)(pfa, s);
592: tempfree(y);
593: }
594: tempfree(x);
595: if (n == MATCHFCN) {
596: int start = patbeg - s + 1;
597: if (patlen < 0)
598: start = 0;
599: setfval(rstartloc, (Awkfloat) start);
600: setfval(rlengthloc, (Awkfloat) patlen);
601: x = gettemp();
602: x->tval = NUM;
603: x->fval = start;
604: return x;
605: } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
606: return(True);
607: else
608: return(False);
609: }
610:
611:
612: Cell *boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */
613: {
614: Cell *x, *y;
615: int i;
616:
617: x = execute(a[0]);
618: i = istrue(x);
619: tempfree(x);
620: switch (n) {
621: case BOR:
622: if (i) return(True);
623: y = execute(a[1]);
624: i = istrue(y);
625: tempfree(y);
626: if (i) return(True);
627: else return(False);
628: case AND:
629: if ( !i ) return(False);
630: y = execute(a[1]);
631: i = istrue(y);
632: tempfree(y);
633: if (i) return(True);
634: else return(False);
635: case NOT:
636: if (i) return(False);
637: else return(True);
638: default: /* can't happen */
639: FATAL("unknown boolean operator %d", n);
640: }
641: return 0; /*NOTREACHED*/
642: }
643:
644: Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */
645: {
646: int i;
647: Cell *x, *y;
648: Awkfloat j;
649:
650: x = execute(a[0]);
651: y = execute(a[1]);
652: if (x->tval&NUM && y->tval&NUM) {
653: j = x->fval - y->fval;
654: i = j<0? -1: (j>0? 1: 0);
655: } else {
656: i = strcmp(getsval(x), getsval(y));
657: }
658: tempfree(x);
659: tempfree(y);
660: switch (n) {
661: case LT: if (i<0) return(True);
662: else return(False);
663: case LE: if (i<=0) return(True);
664: else return(False);
665: case NE: if (i!=0) return(True);
666: else return(False);
667: case EQ: if (i == 0) return(True);
668: else return(False);
669: case GE: if (i>=0) return(True);
670: else return(False);
671: case GT: if (i>0) return(True);
672: else return(False);
673: default: /* can't happen */
674: FATAL("unknown relational operator %d", n);
675: }
676: return 0; /*NOTREACHED*/
677: }
678:
679: void tfree(Cell *a) /* free a tempcell */
680: {
681: if (freeable(a)) {
682: dprintf( ("freeing %s %s %o\n", NN(a->nval), NN(a->sval), a->tval) );
683: xfree(a->sval);
684: }
685: if (a == tmps)
686: FATAL("tempcell list is curdled");
687: a->cnext = tmps;
688: tmps = a;
689: }
690:
691: Cell *gettemp(void) /* get a tempcell */
692: { int i;
693: Cell *x;
694:
695: if (!tmps) {
696: tmps = (Cell *) calloc(100, sizeof(Cell));
697: if (!tmps)
698: FATAL("out of space for temporaries");
699: for(i = 1; i < 100; i++)
700: tmps[i-1].cnext = &tmps[i];
701: tmps[i-1].cnext = 0;
702: }
703: x = tmps;
704: tmps = x->cnext;
705: *x = tempcell;
706: return(x);
707: }
708:
709: Cell *indirect(Node **a, int n) /* $( a[0] ) */
710: {
711: Awkfloat val;
712: Cell *x;
713: int m;
714: char *s;
715:
716: x = execute(a[0]);
717: val = getfval(x); /* freebsd: defend against super large field numbers */
718: if ((Awkfloat)INT_MAX < val)
719: FATAL("trying to access out of range field %s", x->nval);
720: m = (int) val;
721: if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */
722: FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
723: /* BUG: can x->nval ever be null??? */
724: tempfree(x);
725: x = fieldadr(m);
726: x->ctype = OCELL; /* BUG? why are these needed? */
727: x->csub = CFLD;
728: return(x);
729: }
730:
731: Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */
732: {
733: int k, m, n;
734: char *s;
735: int temp;
736: Cell *x, *y, *z = 0;
737:
738: x = execute(a[0]);
739: y = execute(a[1]);
740: if (a[2] != 0)
741: z = execute(a[2]);
742: s = getsval(x);
743: k = strlen(s) + 1;
744: if (k <= 1) {
745: tempfree(x);
746: tempfree(y);
747: if (a[2] != 0) {
748: tempfree(z);
749: }
750: x = gettemp();
751: setsval(x, "");
752: return(x);
753: }
754: m = (int) getfval(y);
755: if (m <= 0)
756: m = 1;
757: else if (m > k)
758: m = k;
759: tempfree(y);
760: if (a[2] != 0) {
761: n = (int) getfval(z);
762: tempfree(z);
763: } else
764: n = k - 1;
765: if (n < 0)
766: n = 0;
767: else if (n > k - m)
768: n = k - m;
769: dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) );
770: y = gettemp();
771: temp = s[n+m-1]; /* with thanks to John Linderman */
772: s[n+m-1] = '\0';
773: setsval(y, s + m - 1);
774: s[n+m-1] = temp;
775: tempfree(x);
776: return(y);
777: }
778:
779: Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */
780: {
781: Cell *x, *y, *z;
782: char *s1, *s2, *p1, *p2, *q;
783: Awkfloat v = 0.0;
784:
785: x = execute(a[0]);
786: s1 = getsval(x);
787: y = execute(a[1]);
788: s2 = getsval(y);
789:
790: z = gettemp();
791: for (p1 = s1; *p1 != '\0'; p1++) {
792: for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
793: ;
794: if (*p2 == '\0') {
795: v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */
796: break;
797: }
798: }
799: tempfree(x);
800: tempfree(y);
801: setfval(z, v);
802: return(z);
803: }
804:
805: #define MAXNUMSIZE 50
806:
807: int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like conversions */
808: {
809: char *fmt;
810: char *p, *t;
811: const char *os;
812: Cell *x;
813: int flag = 0, n;
814: int fmtwd; /* format width */
815: int fmtsz = recsize;
816: char *buf = *pbuf;
817: int bufsize = *pbufsize;
818:
819: os = s;
820: p = buf;
821: if ((fmt = (char *) malloc(fmtsz)) == NULL)
822: FATAL("out of memory in format()");
823: while (*s) {
824: adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format1");
825: if (*s != '%') {
826: *p++ = *s++;
827: continue;
828: }
829: if (*(s+1) == '%') {
830: *p++ = '%';
831: s += 2;
832: continue;
833: }
834: /* have to be real careful in case this is a huge number, eg, %100000d */
835: fmtwd = atoi(s+1);
836: if (fmtwd < 0)
837: fmtwd = -fmtwd;
838: adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format2");
839: for (t = fmt; (*t++ = *s) != '\0'; s++) {
840: if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3"))
841: FATAL("format item %.30s... ran format() out of memory", os);
842: if (isalpha((uschar)*s) && *s != 'l' && *s != 'h' && *s != 'L')
843: break; /* the ansi panoply */
844: if (*s == '*') {
845: x = execute(a);
846: a = a->nnext;
847: sprintf(t-1, "%d", fmtwd=(int) getfval(x));
848: if (fmtwd < 0)
849: fmtwd = -fmtwd;
850: adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
851: t = fmt + strlen(fmt);
852: tempfree(x);
853: }
854: }
855: *t = '\0';
856: if (fmtwd < 0)
857: fmtwd = -fmtwd;
858: adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format4");
859:
860: switch (*s) {
861: case 'f': case 'e': case 'g': case 'E': case 'G':
862: flag = 'f';
863: break;
864: case 'd': case 'i':
865: flag = 'd';
866: if(*(s-1) == 'l') break;
867: *(t-1) = 'l';
868: *t = 'd';
869: *++t = '\0';
870: break;
871: case 'o': case 'x': case 'X': case 'u':
872: flag = *(s-1) == 'l' ? 'd' : 'u';
873: break;
874: case 's':
875: flag = 's';
876: break;
877: case 'c':
878: flag = 'c';
879: break;
880: default:
881: WARNING("weird printf conversion %s", fmt);
882: flag = '?';
883: break;
884: }
885: if (a == NULL)
886: FATAL("not enough args in printf(%s)", os);
887: x = execute(a);
888: a = a->nnext;
889: n = MAXNUMSIZE;
890: if (fmtwd > n)
891: n = fmtwd;
892: adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format5");
893: switch (flag) {
894: case '?': sprintf(p, "%s", fmt); /* unknown, so dump it too */
895: t = getsval(x);
896: n = strlen(t);
897: if (fmtwd > n)
898: n = fmtwd;
899: adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format6");
900: p += strlen(p);
901: sprintf(p, "%s", t);
902: break;
903: case 'f': sprintf(p, fmt, getfval(x)); break;
904: case 'd': sprintf(p, fmt, (long) getfval(x)); break;
905: case 'u': sprintf(p, fmt, (int) getfval(x)); break;
906: case 's':
907: t = getsval(x);
908: n = strlen(t);
909: if (fmtwd > n)
910: n = fmtwd;
911: if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format7"))
912: FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t);
913: sprintf(p, fmt, t);
914: break;
915: case 'c':
916: if (isnum(x)) {
917: if (getfval(x))
918: sprintf(p, fmt, (int) getfval(x));
919: else {
920: *p++ = '\0'; /* explicit null byte */
921: *p = '\0'; /* next output will start here */
922: }
923: } else
924: sprintf(p, fmt, getsval(x)[0]);
925: break;
926: default:
927: FATAL("can't happen: bad conversion %c in format()", flag);
928: }
929: tempfree(x);
930: p += strlen(p);
931: s++;
932: }
933: *p = '\0';
934: free(fmt);
935: for ( ; a; a = a->nnext) /* evaluate any remaining args */
936: execute(a);
937: *pbuf = buf;
938: *pbufsize = bufsize;
939: return p - buf;
940: }
941:
942: Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */
943: {
944: Cell *x;
945: Node *y;
946: char *buf;
947: int bufsz=3*recsize;
948:
949: if ((buf = (char *) malloc(bufsz)) == NULL)
950: FATAL("out of memory in awksprintf");
951: y = a[0]->nnext;
952: x = execute(a[0]);
953: if (format(&buf, &bufsz, getsval(x), y) == -1)
954: FATAL("sprintf string %.30s... too long. can't happen.", buf);
955: tempfree(x);
956: x = gettemp();
957: x->sval = buf;
958: x->tval = STR;
959: return(x);
960: }
961:
962: Cell *awkprintf(Node **a, int n) /* printf */
963: { /* a[0] is list of args, starting with format string */
964: /* a[1] is redirection operator, a[2] is redirection file */
965: FILE *fp;
966: Cell *x;
967: Node *y;
968: char *buf;
969: int len;
970: int bufsz=3*recsize;
971:
972: if ((buf = (char *) malloc(bufsz)) == NULL)
973: FATAL("out of memory in awkprintf");
974: y = a[0]->nnext;
975: x = execute(a[0]);
976: if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
977: FATAL("printf string %.30s... too long. can't happen.", buf);
978: tempfree(x);
979: if (a[1] == NULL) {
980: /* fputs(buf, stdout); */
981: fwrite(buf, len, 1, stdout);
982: if (ferror(stdout))
983: FATAL("write error on stdout");
984: } else {
985: fp = redirect(ptoi(a[1]), a[2]);
986: /* fputs(buf, fp); */
987: fwrite(buf, len, 1, fp);
988: fflush(fp);
989: if (ferror(fp))
990: FATAL("write error on %s", filename(fp));
991: }
992: free(buf);
993: return(True);
994: }
995:
996: Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */
997: {
998: Awkfloat i, j = 0;
999: double v;
1000: Cell *x, *y, *z;
1001:
1002: x = execute(a[0]);
1003: i = getfval(x);
1004: tempfree(x);
1005: if (n != UMINUS) {
1006: y = execute(a[1]);
1007: j = getfval(y);
1008: tempfree(y);
1009: }
1010: z = gettemp();
1011: switch (n) {
1012: case ADD:
1013: i += j;
1014: break;
1015: case MINUS:
1016: i -= j;
1017: break;
1018: case MULT:
1019: i *= j;
1020: break;
1021: case DIVIDE:
1022: if (j == 0)
1023: FATAL("division by zero");
1024: i /= j;
1025: break;
1026: case MOD:
1027: if (j == 0)
1028: FATAL("division by zero in mod");
1029: modf(i/j, &v);
1030: i = i - j * v;
1031: break;
1032: case UMINUS:
1033: i = -i;
1034: break;
1035: case POWER:
1036: if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
1037: i = ipow(i, (int) j);
1038: else
1039: i = errcheck(pow(i, j), "pow");
1040: break;
1041: default: /* can't happen */
1042: FATAL("illegal arithmetic operator %d", n);
1043: }
1044: setfval(z, i);
1045: return(z);
1046: }
1047:
1048: double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */
1049: {
1050: double v;
1051:
1052: if (n <= 0)
1053: return 1;
1054: v = ipow(x, n/2);
1055: if (n % 2 == 0)
1056: return v * v;
1057: else
1058: return x * v * v;
1059: }
1060:
1061: Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */
1062: {
1063: Cell *x, *z;
1064: int k;
1065: Awkfloat xf;
1066:
1067: x = execute(a[0]);
1068: xf = getfval(x);
1069: k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
1070: if (n == PREINCR || n == PREDECR) {
1071: setfval(x, xf + k);
1072: return(x);
1073: }
1074: z = gettemp();
1075: setfval(z, xf);
1076: setfval(x, xf + k);
1077: tempfree(x);
1078: return(z);
1079: }
1080:
1081: Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */
1082: { /* this is subtle; don't muck with it. */
1083: Cell *x, *y;
1084: Awkfloat xf, yf;
1085: double v;
1086:
1087: y = execute(a[1]);
1088: x = execute(a[0]);
1089: if (n == ASSIGN) { /* ordinary assignment */
1090: if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: */
1091: ; /* leave alone unless it's a field */
1092: else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
1093: setsval(x, getsval(y));
1094: x->fval = getfval(y);
1095: x->tval |= NUM;
1096: }
1097: else if (isstr(y))
1098: setsval(x, getsval(y));
1099: else if (isnum(y))
1100: setfval(x, getfval(y));
1101: else
1102: funnyvar(y, "read value of");
1103: tempfree(y);
1104: return(x);
1105: }
1106: xf = getfval(x);
1107: yf = getfval(y);
1108: switch (n) {
1109: case ADDEQ:
1110: xf += yf;
1111: break;
1112: case SUBEQ:
1113: xf -= yf;
1114: break;
1115: case MULTEQ:
1116: xf *= yf;
1117: break;
1118: case DIVEQ:
1119: if (yf == 0)
1120: FATAL("division by zero in /=");
1121: xf /= yf;
1122: break;
1123: case MODEQ:
1124: if (yf == 0)
1125: FATAL("division by zero in %%=");
1126: modf(xf/yf, &v);
1127: xf = xf - yf * v;
1128: break;
1129: case POWEQ:
1130: if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */
1131: xf = ipow(xf, (int) yf);
1132: else
1133: xf = errcheck(pow(xf, yf), "pow");
1134: break;
1135: default:
1136: FATAL("illegal assignment operator %d", n);
1137: break;
1138: }
1139: tempfree(y);
1140: setfval(x, xf);
1141: return(x);
1142: }
1143:
1144: Cell *cat(Node **a, int q) /* a[0] cat a[1] */
1145: {
1146: Cell *x, *y, *z;
1147: int n1, n2;
1148: char *s;
1149:
1150: x = execute(a[0]);
1151: y = execute(a[1]);
1152: getsval(x);
1153: getsval(y);
1154: n1 = strlen(x->sval);
1155: n2 = strlen(y->sval);
1156: s = (char *) malloc(n1 + n2 + 1);
1157: if (s == NULL)
1158: FATAL("out of space concatenating %.15s... and %.15s...",
1159: x->sval, y->sval);
1160: strcpy(s, x->sval);
1161: strcpy(s+n1, y->sval);
1162: tempfree(x);
1163: tempfree(y);
1164: z = gettemp();
1165: z->sval = s;
1166: z->tval = STR;
1167: return(z);
1168: }
1169:
1170: Cell *pastat(Node **a, int n) /* a[0] { a[1] } */
1171: {
1172: Cell *x;
1173:
1174: if (a[0] == 0)
1175: x = execute(a[1]);
1176: else {
1177: x = execute(a[0]);
1178: if (istrue(x)) {
1179: tempfree(x);
1180: x = execute(a[1]);
1181: }
1182: }
1183: return x;
1184: }
1185:
1186: Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */
1187: {
1188: Cell *x;
1189: int pair;
1190:
1191: pair = ptoi(a[3]);
1192: if (pairstack[pair] == 0) {
1193: x = execute(a[0]);
1194: if (istrue(x))
1195: pairstack[pair] = 1;
1196: tempfree(x);
1197: }
1198: if (pairstack[pair] == 1) {
1199: x = execute(a[1]);
1200: if (istrue(x))
1201: pairstack[pair] = 0;
1202: tempfree(x);
1203: x = execute(a[2]);
1204: return(x);
1205: }
1206: return(False);
1207: }
1208:
1209: Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
1210: {
1211: Cell *x = 0, *y, *ap;
1212: char *s;
1213: int sep;
1214: char *t, temp, num[50], *fs = 0;
1215: int n, tempstat, arg3type;
1216:
1217: y = execute(a[0]); /* source string */
1218: s = getsval(y);
1219: arg3type = ptoi(a[3]);
1220: if (a[2] == 0) /* fs string */
1221: fs = *FS;
1222: else if (arg3type == STRING) { /* split(str,arr,"string") */
1223: x = execute(a[2]);
1224: fs = getsval(x);
1225: } else if (arg3type == REGEXPR)
1226: fs = "(regexpr)"; /* split(str,arr,/regexpr/) */
1227: else
1228: FATAL("illegal type of split");
1229: sep = *fs;
1230: ap = execute(a[1]); /* array name */
1231: freesymtab(ap);
1232: dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs) );
1233: ap->tval &= ~STR;
1234: ap->tval |= ARR;
1235: ap->sval = (char *) makesymtab(NSYMTAB);
1236:
1237: n = 0;
1238: if (*s != '\0' && (strlen(fs) > 1 || arg3type == REGEXPR)) { /* reg expr */
1239: fa *pfa;
1240: if (arg3type == REGEXPR) { /* it's ready already */
1241: pfa = (fa *) a[2];
1242: } else {
1243: pfa = makedfa(fs, 1);
1244: }
1245: if (nematch(pfa,s)) {
1246: tempstat = pfa->initstat;
1247: pfa->initstat = 2;
1248: do {
1249: n++;
1250: sprintf(num, "%d", n);
1251: temp = *patbeg;
1252: *patbeg = '\0';
1253: if (is_number(s))
1254: setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
1255: else
1256: setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1257: *patbeg = temp;
1258: s = patbeg + patlen;
1259: if (*(patbeg+patlen-1) == 0 || *s == 0) {
1260: n++;
1261: sprintf(num, "%d", n);
1262: setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
1263: pfa->initstat = tempstat;
1264: goto spdone;
1265: }
1266: } while (nematch(pfa,s));
1267: pfa->initstat = tempstat; /* bwk: has to be here to reset */
1268: /* cf gsub and refldbld */
1269: }
1270: n++;
1271: sprintf(num, "%d", n);
1272: if (is_number(s))
1273: setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
1274: else
1275: setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1276: spdone:
1277: pfa = NULL;
1278: } else if (sep == ' ') {
1279: for (n = 0; ; ) {
1280: while (*s == ' ' || *s == '\t' || *s == '\n')
1281: s++;
1282: if (*s == 0)
1283: break;
1284: n++;
1285: t = s;
1286: do
1287: s++;
1288: while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
1289: temp = *s;
1290: *s = '\0';
1291: sprintf(num, "%d", n);
1292: if (is_number(t))
1293: setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1294: else
1295: setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1296: *s = temp;
1297: if (*s != 0)
1298: s++;
1299: }
1300: } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */
1301: for (n = 0; *s != 0; s++) {
1302: char buf[2];
1303: n++;
1304: sprintf(num, "%d", n);
1305: buf[0] = *s;
1306: buf[1] = 0;
1307: if (isdigit((uschar)buf[0]))
1308: setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval);
1309: else
1310: setsymtab(num, buf, 0.0, STR, (Array *) ap->sval);
1311: }
1312: } else if (*s != 0) {
1313: for (;;) {
1314: n++;
1315: t = s;
1316: while (*s != sep && *s != '\n' && *s != '\0')
1317: s++;
1318: temp = *s;
1319: *s = '\0';
1320: sprintf(num, "%d", n);
1321: if (is_number(t))
1322: setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1323: else
1324: setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1325: *s = temp;
1326: if (*s++ == 0)
1327: break;
1328: }
1329: }
1330: tempfree(ap);
1331: tempfree(y);
1332: if (a[2] != 0 && arg3type == STRING) {
1333: tempfree(x);
1334: }
1335: x = gettemp();
1336: x->tval = NUM;
1337: x->fval = n;
1338: return(x);
1339: }
1340:
1341: Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */
1342: {
1343: Cell *x;
1344:
1345: x = execute(a[0]);
1346: if (istrue(x)) {
1347: tempfree(x);
1348: x = execute(a[1]);
1349: } else {
1350: tempfree(x);
1351: x = execute(a[2]);
1352: }
1353: return(x);
1354: }
1355:
1356: Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */
1357: {
1358: Cell *x;
1359:
1360: x = execute(a[0]);
1361: if (istrue(x)) {
1362: tempfree(x);
1363: x = execute(a[1]);
1364: } else if (a[2] != 0) {
1365: tempfree(x);
1366: x = execute(a[2]);
1367: }
1368: return(x);
1369: }
1370:
1371: Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */
1372: {
1373: Cell *x;
1374:
1375: for (;;) {
1376: x = execute(a[0]);
1377: if (!istrue(x))
1378: return(x);
1379: tempfree(x);
1380: x = execute(a[1]);
1381: if (isbreak(x)) {
1382: x = True;
1383: return(x);
1384: }
1385: if (isnext(x) || isexit(x) || isret(x))
1386: return(x);
1387: tempfree(x);
1388: }
1389: }
1390:
1391: Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */
1392: {
1393: Cell *x;
1394:
1395: for (;;) {
1396: x = execute(a[0]);
1397: if (isbreak(x))
1398: return True;
1399: if (isnext(x) || isexit(x) || isret(x))
1400: return(x);
1401: tempfree(x);
1402: x = execute(a[1]);
1403: if (!istrue(x))
1404: return(x);
1405: tempfree(x);
1406: }
1407: }
1408:
1409: Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */
1410: {
1411: Cell *x;
1412:
1413: x = execute(a[0]);
1414: tempfree(x);
1415: for (;;) {
1416: if (a[1]!=0) {
1417: x = execute(a[1]);
1418: if (!istrue(x)) return(x);
1419: else tempfree(x);
1420: }
1421: x = execute(a[3]);
1422: if (isbreak(x)) /* turn off break */
1423: return True;
1424: if (isnext(x) || isexit(x) || isret(x))
1425: return(x);
1426: tempfree(x);
1427: x = execute(a[2]);
1428: tempfree(x);
1429: }
1430: }
1431:
1432: Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */
1433: {
1434: Cell *x, *vp, *arrayp, *cp, *ncp;
1435: Array *tp;
1436: int i;
1437:
1438: vp = execute(a[0]);
1439: arrayp = execute(a[1]);
1440: if (!isarr(arrayp)) {
1441: return True;
1442: }
1443: tp = (Array *) arrayp->sval;
1444: tempfree(arrayp);
1445: for (i = 0; i < tp->size; i++) { /* this routine knows too much */
1446: for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1447: setsval(vp, cp->nval);
1448: ncp = cp->cnext;
1449: x = execute(a[2]);
1450: if (isbreak(x)) {
1451: tempfree(vp);
1452: return True;
1453: }
1454: if (isnext(x) || isexit(x) || isret(x)) {
1455: tempfree(vp);
1456: return(x);
1457: }
1458: tempfree(x);
1459: }
1460: }
1461: return True;
1462: }
1463:
1464: Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */
1465: {
1466: Cell *x, *y;
1467: Awkfloat u;
1468: int t;
1469: char *p, *buf;
1470: Node *nextarg;
1471: FILE *fp;
1472: void flush_all(void);
1473:
1474: t = ptoi(a[0]);
1475: x = execute(a[1]);
1476: nextarg = a[1]->nnext;
1477: switch (t) {
1478: case FLENGTH:
1479: if (isarr(x))
1480: u = ((Array *) x->sval)->nelem; /* GROT. should be function*/
1481: else
1482: u = strlen(getsval(x));
1483: break;
1484: case FLOG:
1485: u = errcheck(log(getfval(x)), "log"); break;
1486: case FINT:
1487: modf(getfval(x), &u); break;
1488: case FEXP:
1489: u = errcheck(exp(getfval(x)), "exp"); break;
1490: case FSQRT:
1491: u = errcheck(sqrt(getfval(x)), "sqrt"); break;
1492: case FSIN:
1493: u = sin(getfval(x)); break;
1494: case FCOS:
1495: u = cos(getfval(x)); break;
1496: case FATAN:
1497: if (nextarg == 0) {
1498: WARNING("atan2 requires two arguments; returning 1.0");
1499: u = 1.0;
1500: } else {
1501: y = execute(a[1]->nnext);
1502: u = atan2(getfval(x), getfval(y));
1503: tempfree(y);
1504: nextarg = nextarg->nnext;
1505: }
1506: break;
1507: case FSYSTEM:
1508: fflush(stdout); /* in case something is buffered already */
1509: u = (Awkfloat) system(getsval(x)) / 256; /* 256 is unix-dep */
1510: break;
1511: case FRAND:
1512: /* in principle, rand() returns something in 0..RAND_MAX */
1513: u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX;
1514: break;
1515: case FSRAND:
1516: if (isrec(x)) /* no argument provided */
1517: u = time((time_t *)0);
1518: else
1519: u = getfval(x);
1520: srand((unsigned int) u);
1521: break;
1522: case FTOUPPER:
1523: case FTOLOWER:
1524: buf = tostring(getsval(x));
1525: if (t == FTOUPPER) {
1526: for (p = buf; *p; p++)
1527: if (islower((uschar) *p))
1528: *p = toupper((uschar)*p);
1529: } else {
1530: for (p = buf; *p; p++)
1531: if (isupper((uschar) *p))
1532: *p = tolower((uschar)*p);
1533: }
1534: tempfree(x);
1535: x = gettemp();
1536: setsval(x, buf);
1537: free(buf);
1538: return x;
1539: case FFLUSH:
1540: if (isrec(x) || strlen(getsval(x)) == 0) {
1541: flush_all(); /* fflush() or fflush("") -> all */
1542: u = 0;
1543: } else if ((fp = openfile(FFLUSH, getsval(x))) == NULL)
1544: u = EOF;
1545: else
1546: u = fflush(fp);
1547: break;
1548: default: /* can't happen */
1549: FATAL("illegal function type %d", t);
1550: break;
1551: }
1552: tempfree(x);
1553: x = gettemp();
1554: setfval(x, u);
1555: if (nextarg != 0) {
1556: WARNING("warning: function has too many arguments");
1557: for ( ; nextarg; nextarg = nextarg->nnext)
1558: execute(nextarg);
1559: }
1560: return(x);
1561: }
1562:
1563: Cell *printstat(Node **a, int n) /* print a[0] */
1564: {
1565: Node *x;
1566: Cell *y;
1567: FILE *fp;
1568:
1569: if (a[1] == 0) /* a[1] is redirection operator, a[2] is file */
1570: fp = stdout;
1571: else
1572: fp = redirect(ptoi(a[1]), a[2]);
1573: for (x = a[0]; x != NULL; x = x->nnext) {
1574: y = execute(x);
1575: fputs(getpssval(y), fp);
1576: tempfree(y);
1577: if (x->nnext == NULL)
1578: fputs(*ORS, fp);
1579: else
1580: fputs(*OFS, fp);
1581: }
1582: if (a[1] != 0)
1583: fflush(fp);
1584: if (ferror(fp))
1585: FATAL("write error on %s", filename(fp));
1586: return(True);
1587: }
1588:
1589: Cell *nullproc(Node **a, int n)
1590: {
1591: n = n;
1592: a = a;
1593: return 0;
1594: }
1595:
1596:
1597: FILE *redirect(int a, Node *b) /* set up all i/o redirections */
1598: {
1599: FILE *fp;
1600: Cell *x;
1601: char *fname;
1602:
1603: x = execute(b);
1604: fname = getsval(x);
1605: fp = openfile(a, fname);
1606: if (fp == NULL)
1607: FATAL("can't open file %s", fname);
1608: tempfree(x);
1609: return fp;
1610: }
1611:
1612: struct files {
1613: FILE *fp;
1614: const char *fname;
1615: int mode; /* '|', 'a', 'w' => LE/LT, GT */
1616: } files[FOPEN_MAX] ={
1617: { NULL, "/dev/stdin", LT }, /* watch out: don't free this! */
1618: { NULL, "/dev/stdout", GT },
1619: { NULL, "/dev/stderr", GT }
1620: };
1621:
1622: void stdinit(void) /* in case stdin, etc., are not constants */
1623: {
1624: files[0].fp = stdin;
1625: files[1].fp = stdout;
1626: files[2].fp = stderr;
1627: }
1628:
1629: FILE *openfile(int a, const char *us)
1630: {
1631: const char *s = us;
1632: int i, m;
1633: FILE *fp = 0;
1634:
1635: if (*s == '\0')
1636: FATAL("null file name in print or getline");
1637: for (i=0; i < FOPEN_MAX; i++)
1638: if (files[i].fname && strcmp(s, files[i].fname) == 0) {
1639: if (a == files[i].mode || (a==APPEND && files[i].mode==GT))
1640: return files[i].fp;
1641: if (a == FFLUSH)
1642: return files[i].fp;
1643: }
1644: if (a == FFLUSH) /* didn't find it, so don't create it! */
1645: return NULL;
1646:
1647: for (i=0; i < FOPEN_MAX; i++)
1648: if (files[i].fp == 0)
1649: break;
1650: if (i >= FOPEN_MAX)
1651: FATAL("%s makes too many open files", s);
1652: fflush(stdout); /* force a semblance of order */
1653: m = a;
1654: if (a == GT) {
1655: fp = fopen(s, "w");
1656: } else if (a == APPEND) {
1657: fp = fopen(s, "a");
1658: m = GT; /* so can mix > and >> */
1659: } else if (a == '|') { /* output pipe */
1660: fp = popen(s, "w");
1661: } else if (a == LE) { /* input pipe */
1662: fp = popen(s, "r");
1663: } else if (a == LT) { /* getline <file */
1664: fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */
1665: } else /* can't happen */
1666: FATAL("illegal redirection %d", a);
1667: if (fp != NULL) {
1668: files[i].fname = tostring(s);
1669: files[i].fp = fp;
1670: files[i].mode = m;
1671: }
1672: return fp;
1673: }
1674:
1675: const char *filename(FILE *fp)
1676: {
1677: int i;
1678:
1679: for (i = 0; i < FOPEN_MAX; i++)
1680: if (fp == files[i].fp)
1681: return files[i].fname;
1682: return "???";
1683: }
1684:
1685: Cell *closefile(Node **a, int n)
1686: {
1687: Cell *x;
1688: int i, stat;
1689:
1690: n = n;
1691: x = execute(a[0]);
1692: getsval(x);
1693: stat = -1;
1694: for (i = 0; i < FOPEN_MAX; i++) {
1695: if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) {
1696: if (ferror(files[i].fp))
1697: WARNING( "i/o error occurred on %s", files[i].fname );
1698: if (files[i].mode == '|' || files[i].mode == LE)
1699: stat = pclose(files[i].fp);
1700: else
1701: stat = fclose(files[i].fp);
1702: if (stat == EOF)
1703: WARNING( "i/o error occurred closing %s", files[i].fname );
1704: if (i > 2) /* don't do /dev/std... */
1705: xfree(files[i].fname);
1706: files[i].fname = NULL; /* watch out for ref thru this */
1707: files[i].fp = NULL;
1708: }
1709: }
1710: tempfree(x);
1711: x = gettemp();
1712: setfval(x, (Awkfloat) stat);
1713: return(x);
1714: }
1715:
1716: void closeall(void)
1717: {
1718: int i, stat;
1719:
1720: for (i = 0; i < FOPEN_MAX; i++) {
1721: if (files[i].fp) {
1722: if (ferror(files[i].fp))
1723: WARNING( "i/o error occurred on %s", files[i].fname );
1724: if (files[i].mode == '|' || files[i].mode == LE)
1725: stat = pclose(files[i].fp);
1726: else
1727: stat = fclose(files[i].fp);
1728: if (stat == EOF)
1729: WARNING( "i/o error occurred while closing %s", files[i].fname );
1730: }
1731: }
1732: }
1733:
1734: void flush_all(void)
1735: {
1736: int i;
1737:
1738: for (i = 0; i < FOPEN_MAX; i++)
1739: if (files[i].fp)
1740: fflush(files[i].fp);
1741: }
1742:
1743: void backsub(char **pb_ptr, char **sptr_ptr);
1744:
1745: Cell *sub(Node **a, int nnn) /* substitute command */
1746: {
1747: char *sptr, *pb, *q;
1748: Cell *x, *y, *result;
1749: char *t, *buf;
1750: fa *pfa;
1751: int bufsz = recsize;
1752:
1753: if ((buf = (char *) malloc(bufsz)) == NULL)
1754: FATAL("out of memory in sub");
1755: x = execute(a[3]); /* target string */
1756: t = getsval(x);
1757: if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1758: pfa = (fa *) a[1]; /* regular expression */
1759: else {
1760: y = execute(a[1]);
1761: pfa = makedfa(getsval(y), 1);
1762: tempfree(y);
1763: }
1764: y = execute(a[2]); /* replacement string */
1765: result = False;
1766: if (pmatch(pfa, t)) {
1767: sptr = t;
1768: adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub");
1769: pb = buf;
1770: while (sptr < patbeg)
1771: *pb++ = *sptr++;
1772: sptr = getsval(y);
1773: while (*sptr != 0) {
1774: adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub");
1775: if (*sptr == '\\') {
1776: backsub(&pb, &sptr);
1777: } else if (*sptr == '&') {
1778: sptr++;
1779: adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub");
1780: for (q = patbeg; q < patbeg+patlen; )
1781: *pb++ = *q++;
1782: } else
1783: *pb++ = *sptr++;
1784: }
1785: *pb = '\0';
1786: if (pb > buf + bufsz)
1787: FATAL("sub result1 %.30s too big; can't happen", buf);
1788: sptr = patbeg + patlen;
1789: if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
1790: adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
1791: while ((*pb++ = *sptr++) != 0)
1792: ;
1793: }
1794: if (pb > buf + bufsz)
1795: FATAL("sub result2 %.30s too big; can't happen", buf);
1796: setsval(x, buf); /* BUG: should be able to avoid copy */
1797: result = True;;
1798: }
1799: tempfree(x);
1800: tempfree(y);
1801: free(buf);
1802: return result;
1803: }
1804:
1805: Cell *gsub(Node **a, int nnn) /* global substitute */
1806: {
1807: Cell *x, *y;
1808: char *rptr, *sptr, *t, *pb, *q;
1809: char *buf;
1810: fa *pfa;
1811: int mflag, tempstat, num;
1812: int bufsz = recsize;
1813:
1814: if ((buf = (char *) malloc(bufsz)) == NULL)
1815: FATAL("out of memory in gsub");
1816: mflag = 0; /* if mflag == 0, can replace empty string */
1817: num = 0;
1818: x = execute(a[3]); /* target string */
1819: t = getsval(x);
1820: if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1821: pfa = (fa *) a[1]; /* regular expression */
1822: else {
1823: y = execute(a[1]);
1824: pfa = makedfa(getsval(y), 1);
1825: tempfree(y);
1826: }
1827: y = execute(a[2]); /* replacement string */
1828: if (pmatch(pfa, t)) {
1829: tempstat = pfa->initstat;
1830: pfa->initstat = 2;
1831: pb = buf;
1832: rptr = getsval(y);
1833: do {
1834: if (patlen == 0 && *patbeg != 0) { /* matched empty string */
1835: if (mflag == 0) { /* can replace empty */
1836: num++;
1837: sptr = rptr;
1838: while (*sptr != 0) {
1839: adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1840: if (*sptr == '\\') {
1841: backsub(&pb, &sptr);
1842: } else if (*sptr == '&') {
1843: sptr++;
1844: adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1845: for (q = patbeg; q < patbeg+patlen; )
1846: *pb++ = *q++;
1847: } else
1848: *pb++ = *sptr++;
1849: }
1850: }
1851: if (*t == 0) /* at end */
1852: goto done;
1853: adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
1854: *pb++ = *t++;
1855: if (pb > buf + bufsz) /* BUG: not sure of this test */
1856: FATAL("gsub result0 %.30s too big; can't happen", buf);
1857: mflag = 0;
1858: }
1859: else { /* matched nonempty string */
1860: num++;
1861: sptr = t;
1862: adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub");
1863: while (sptr < patbeg)
1864: *pb++ = *sptr++;
1865: sptr = rptr;
1866: while (*sptr != 0) {
1867: adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1868: if (*sptr == '\\') {
1869: backsub(&pb, &sptr);
1870: } else if (*sptr == '&') {
1871: sptr++;
1872: adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1873: for (q = patbeg; q < patbeg+patlen; )
1874: *pb++ = *q++;
1875: } else
1876: *pb++ = *sptr++;
1877: }
1878: t = patbeg + patlen;
1879: if (patlen == 0 || *t == 0 || *(t-1) == 0)
1880: goto done;
1881: if (pb > buf + bufsz)
1882: FATAL("gsub result1 %.30s too big; can't happen", buf);
1883: mflag = 1;
1884: }
1885: } while (pmatch(pfa,t));
1886: sptr = t;
1887: adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
1888: while ((*pb++ = *sptr++) != 0)
1889: ;
1890: done: if (pb < buf + bufsz)
1891: *pb = '\0';
1892: else if (*(pb-1) != '\0')
1893: FATAL("gsub result2 %.30s truncated; can't happen", buf);
1894: setsval(x, buf); /* BUG: should be able to avoid copy + free */
1895: pfa->initstat = tempstat;
1896: }
1897: tempfree(x);
1898: tempfree(y);
1899: x = gettemp();
1900: x->tval = NUM;
1901: x->fval = num;
1902: free(buf);
1903: return(x);
1904: }
1905:
1906: void backsub(char **pb_ptr, char **sptr_ptr) /* handle \\& variations */
1907: { /* sptr[0] == '\\' */
1908: char *pb = *pb_ptr, *sptr = *sptr_ptr;
1909:
1910: if (sptr[1] == '\\') {
1911: if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
1912: *pb++ = '\\';
1913: *pb++ = '&';
1914: sptr += 4;
1915: } else if (sptr[2] == '&') { /* \\& -> \ + matched */
1916: *pb++ = '\\';
1917: sptr += 2;
1918: } else { /* \\x -> \\x */
1919: *pb++ = *sptr++;
1920: *pb++ = *sptr++;
1921: }
1922: } else if (sptr[1] == '&') { /* literal & */
1923: sptr++;
1924: *pb++ = *sptr++;
1925: } else /* literal \ */
1926: *pb++ = *sptr++;
1927:
1928: *pb_ptr = pb;
1929: *sptr_ptr = sptr;
1930: }
CVSweb interface <joel.bertrand@systella.fr>