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