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