Annotation of src/usr.bin/awk/run.c, Revision 1.54
1.54 ! millert 1: /* $OpenBSD: run.c,v 1.53 2020/06/10 21:03:36 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.53 millert 121: tbuf = realloc(*pbuf, minlen);
122: DPRINTF( ("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, *pbuf, 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.54 ! millert 195: while (getrec(&record, &recsize, true) > 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) {
1.53 millert 242: fp = frame = calloc(nframe += 100, sizeof(*frame));
1.1 tholo 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),
1.53 millert 277: sizeof(*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:
1.53 millert 410: if ((buf = 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.54 ! millert 445: n = getrec(&record, &recsize, true);
1.1 tholo 446: else { /* getline var */
1.54 ! millert 447: n = getrec(&buf, &bufsize, false);
1.13 kstailey 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: {
1.54 ! millert 464: if (!donefld)
1.1 tholo 465: fldbld();
466: return (Cell *) a[0];
467: }
468:
1.53 millert 469: static char *
470: makearraystring(Node *p, const char *func)
1.1 tholo 471: {
1.13 kstailey 472: char *buf;
473: int bufsz = recsize;
1.53 millert 474: size_t blen, seplen;
475:
476: if ((buf = malloc(bufsz)) == NULL) {
477: FATAL("%s: out of memory", func);
478: }
1.13 kstailey 479:
1.53 millert 480: blen = 0;
481: buf[blen] = '\0';
482: seplen = strlen(getsval(subseploc));
483:
484: for (; p; p = p->nnext) {
485: Cell *x = execute(p); /* expr */
486: char *s = getsval(x);
487: size_t nsub = p->nnext ? seplen : 0;
488: size_t slen = strlen(s);
489: size_t tlen = blen + slen + nsub;
490:
491: if (!adjbuf(&buf, &bufsz, tlen + 1, recsize, 0, func)) {
492: FATAL("%s: out of memory %s[%s...]",
493: func, x->nval, buf);
494: }
495: memcpy(buf + blen, s, slen);
496: if (nsub) {
497: memcpy(buf + blen + slen, *SUBSEP, nsub);
498: }
499: buf[tlen] = '\0';
500: blen = tlen;
501: tempfree(x);
502: }
503: return buf;
504: }
505:
506: Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
507: {
508: Cell *x, *z;
509: char *buf;
1.1 tholo 510:
511: x = execute(a[0]); /* Cell* for symbol table */
1.53 millert 512: buf = makearraystring(a[1], __func__);
1.1 tholo 513: if (!isarr(x)) {
1.42 deraadt 514: DPRINTF( ("making %s into an array\n", NN(x->nval)) );
1.1 tholo 515: if (freeable(x))
516: xfree(x->sval);
517: x->tval &= ~(STR|NUM|DONTFREE);
518: x->tval |= ARR;
519: x->sval = (char *) makesymtab(NSYMTAB);
520: }
521: z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
522: z->ctype = OCELL;
523: z->csub = CVAR;
524: tempfree(x);
1.13 kstailey 525: free(buf);
1.1 tholo 526: return(z);
527: }
528:
1.14 millert 529: Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
1.1 tholo 530: {
1.53 millert 531: Cell *x;
1.1 tholo 532:
533: x = execute(a[0]); /* Cell* for symbol table */
1.50 millert 534: if (x == symtabloc) {
535: FATAL("cannot delete SYMTAB or its elements");
536: }
1.1 tholo 537: if (!isarr(x))
1.15 millert 538: return True;
1.51 millert 539: if (a[1] == NULL) { /* delete the elements, not the table */
1.1 tholo 540: freesymtab(x);
541: x->tval &= ~STR;
542: x->tval |= ARR;
543: x->sval = (char *) makesymtab(NSYMTAB);
544: } else {
1.53 millert 545: char *buf = makearraystring(a[1], __func__);
1.1 tholo 546: freeelem(x, buf);
1.13 kstailey 547: free(buf);
1.1 tholo 548: }
549: tempfree(x);
1.15 millert 550: return True;
1.1 tholo 551: }
552:
553: Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
554: {
1.53 millert 555: Cell *ap, *k;
1.13 kstailey 556: char *buf;
1.1 tholo 557:
558: ap = execute(a[1]); /* array name */
559: if (!isarr(ap)) {
1.42 deraadt 560: DPRINTF( ("making %s into an array\n", ap->nval) );
1.1 tholo 561: if (freeable(ap))
562: xfree(ap->sval);
563: ap->tval &= ~(STR|NUM|DONTFREE);
564: ap->tval |= ARR;
565: ap->sval = (char *) makesymtab(NSYMTAB);
566: }
1.53 millert 567: buf = makearraystring(a[0], __func__);
1.1 tholo 568: k = lookup(buf, (Array *) ap->sval);
569: tempfree(ap);
1.13 kstailey 570: free(buf);
1.1 tholo 571: if (k == NULL)
1.15 millert 572: return(False);
1.1 tholo 573: else
1.15 millert 574: return(True);
1.1 tholo 575: }
576:
577:
578: Cell *matchop(Node **a, int n) /* ~ and match() */
579: {
580: Cell *x, *y;
581: char *s, *t;
582: int i;
583: fa *pfa;
1.18 millert 584: int (*mf)(fa *, const char *) = match, mode = 0;
1.1 tholo 585:
586: if (n == MATCHFCN) {
587: mf = pmatch;
588: mode = 1;
589: }
590: x = execute(a[1]); /* a[1] = target text */
591: s = getsval(x);
1.51 millert 592: if (a[0] == NULL) /* a[1] == 0: already-compiled reg expr */
1.1 tholo 593: i = (*mf)((fa *) a[2], s);
594: else {
595: y = execute(a[2]); /* a[2] = regular expr */
596: t = getsval(y);
597: pfa = makedfa(t, mode);
598: i = (*mf)(pfa, s);
599: tempfree(y);
600: }
601: tempfree(x);
602: if (n == MATCHFCN) {
603: int start = patbeg - s + 1;
604: if (patlen < 0)
605: start = 0;
606: setfval(rstartloc, (Awkfloat) start);
607: setfval(rlengthloc, (Awkfloat) patlen);
608: x = gettemp();
609: x->tval = NUM;
610: x->fval = start;
611: return x;
612: } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
1.15 millert 613: return(True);
1.1 tholo 614: else
1.15 millert 615: return(False);
1.1 tholo 616: }
617:
618:
619: Cell *boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */
620: {
621: Cell *x, *y;
622: int i;
623:
624: x = execute(a[0]);
625: i = istrue(x);
626: tempfree(x);
627: switch (n) {
628: case BOR:
1.15 millert 629: if (i) return(True);
1.1 tholo 630: y = execute(a[1]);
631: i = istrue(y);
632: tempfree(y);
1.15 millert 633: if (i) return(True);
634: else return(False);
1.1 tholo 635: case AND:
1.15 millert 636: if ( !i ) return(False);
1.1 tholo 637: y = execute(a[1]);
638: i = istrue(y);
639: tempfree(y);
1.15 millert 640: if (i) return(True);
641: else return(False);
1.1 tholo 642: case NOT:
1.15 millert 643: if (i) return(False);
644: else return(True);
1.1 tholo 645: default: /* can't happen */
1.16 millert 646: FATAL("unknown boolean operator %d", n);
1.1 tholo 647: }
648: return 0; /*NOTREACHED*/
649: }
650:
651: Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */
652: {
653: int i;
654: Cell *x, *y;
655: Awkfloat j;
656:
657: x = execute(a[0]);
658: y = execute(a[1]);
659: if (x->tval&NUM && y->tval&NUM) {
660: j = x->fval - y->fval;
661: i = j<0? -1: (j>0? 1: 0);
662: } else {
663: i = strcmp(getsval(x), getsval(y));
664: }
665: tempfree(x);
666: tempfree(y);
667: switch (n) {
1.15 millert 668: case LT: if (i<0) return(True);
669: else return(False);
670: case LE: if (i<=0) return(True);
671: else return(False);
672: case NE: if (i!=0) return(True);
673: else return(False);
674: case EQ: if (i == 0) return(True);
675: else return(False);
676: case GE: if (i>=0) return(True);
677: else return(False);
678: case GT: if (i>0) return(True);
679: else return(False);
1.1 tholo 680: default: /* can't happen */
1.16 millert 681: FATAL("unknown relational operator %d", n);
1.1 tholo 682: }
683: return 0; /*NOTREACHED*/
684: }
685:
686: void tfree(Cell *a) /* free a tempcell */
687: {
1.13 kstailey 688: if (freeable(a)) {
1.42 deraadt 689: DPRINTF( ("freeing %s %s %o\n", NN(a->nval), NN(a->sval), a->tval) );
1.1 tholo 690: xfree(a->sval);
1.13 kstailey 691: }
1.1 tholo 692: if (a == tmps)
1.16 millert 693: FATAL("tempcell list is curdled");
1.1 tholo 694: a->cnext = tmps;
695: tmps = a;
696: }
697:
698: Cell *gettemp(void) /* get a tempcell */
699: { int i;
700: Cell *x;
701:
702: if (!tmps) {
1.53 millert 703: tmps = calloc(100, sizeof(*tmps));
1.1 tholo 704: if (!tmps)
1.16 millert 705: FATAL("out of space for temporaries");
1.52 millert 706: for (i = 1; i < 100; i++)
1.1 tholo 707: tmps[i-1].cnext = &tmps[i];
1.51 millert 708: tmps[i-1].cnext = NULL;
1.1 tholo 709: }
710: x = tmps;
711: tmps = x->cnext;
712: *x = tempcell;
713: return(x);
714: }
715:
716: Cell *indirect(Node **a, int n) /* $( a[0] ) */
717: {
1.25 millert 718: Awkfloat val;
1.1 tholo 719: Cell *x;
720: int m;
721: char *s;
722:
723: x = execute(a[0]);
1.25 millert 724: val = getfval(x); /* freebsd: defend against super large field numbers */
725: if ((Awkfloat)INT_MAX < val)
726: FATAL("trying to access out of range field %s", x->nval);
727: m = (int) val;
1.14 millert 728: if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */
1.16 millert 729: FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
1.13 kstailey 730: /* BUG: can x->nval ever be null??? */
1.1 tholo 731: tempfree(x);
732: x = fieldadr(m);
1.13 kstailey 733: x->ctype = OCELL; /* BUG? why are these needed? */
1.1 tholo 734: x->csub = CFLD;
735: return(x);
736: }
737:
738: Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */
739: {
740: int k, m, n;
741: char *s;
742: int temp;
1.51 millert 743: Cell *x, *y, *z = NULL;
1.1 tholo 744:
745: x = execute(a[0]);
746: y = execute(a[1]);
1.51 millert 747: if (a[2] != NULL)
1.1 tholo 748: z = execute(a[2]);
749: s = getsval(x);
750: k = strlen(s) + 1;
751: if (k <= 1) {
752: tempfree(x);
753: tempfree(y);
1.51 millert 754: if (a[2] != NULL) {
1.1 tholo 755: tempfree(z);
1.17 millert 756: }
1.1 tholo 757: x = gettemp();
758: setsval(x, "");
759: return(x);
760: }
1.14 millert 761: m = (int) getfval(y);
1.1 tholo 762: if (m <= 0)
763: m = 1;
764: else if (m > k)
765: m = k;
766: tempfree(y);
1.51 millert 767: if (a[2] != NULL) {
1.14 millert 768: n = (int) getfval(z);
1.1 tholo 769: tempfree(z);
770: } else
771: n = k - 1;
772: if (n < 0)
773: n = 0;
774: else if (n > k - m)
775: n = k - m;
1.42 deraadt 776: DPRINTF( ("substr: m=%d, n=%d, s=%s\n", m, n, s) );
1.1 tholo 777: y = gettemp();
778: temp = s[n+m-1]; /* with thanks to John Linderman */
779: s[n+m-1] = '\0';
780: setsval(y, s + m - 1);
781: s[n+m-1] = temp;
782: tempfree(x);
783: return(y);
784: }
785:
786: Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */
787: {
788: Cell *x, *y, *z;
789: char *s1, *s2, *p1, *p2, *q;
790: Awkfloat v = 0.0;
791:
792: x = execute(a[0]);
793: s1 = getsval(x);
794: y = execute(a[1]);
795: s2 = getsval(y);
796:
797: z = gettemp();
798: for (p1 = s1; *p1 != '\0'; p1++) {
799: for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
800: ;
801: if (*p2 == '\0') {
802: v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */
803: break;
804: }
805: }
806: tempfree(x);
807: tempfree(y);
808: setfval(z, v);
809: return(z);
810: }
811:
1.13 kstailey 812: #define MAXNUMSIZE 50
813:
1.18 millert 814: int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like conversions */
1.1 tholo 815: {
1.13 kstailey 816: char *fmt;
1.18 millert 817: char *p, *t;
818: const char *os;
1.1 tholo 819: Cell *x;
1.10 kstailey 820: int flag = 0, n;
1.13 kstailey 821: int fmtwd; /* format width */
822: int fmtsz = recsize;
823: char *buf = *pbuf;
824: int bufsize = *pbufsize;
1.53 millert 825: #define FMTSZ(a) (fmtsz - ((a) - fmt))
826: #define BUFSZ(a) (bufsize - ((a) - buf))
1.1 tholo 827:
1.54 ! millert 828: static bool first = true;
! 829: static bool have_a_format = false;
1.47 millert 830:
831: if (first) {
832: char buf[100];
833:
834: snprintf(buf, sizeof(buf), "%a", 42.0);
835: have_a_format = (strcmp(buf, "0x1.5p+5") == 0);
1.54 ! millert 836: first = false;
1.47 millert 837: }
838:
1.1 tholo 839: os = s;
840: p = buf;
1.53 millert 841: if ((fmt = malloc(fmtsz)) == NULL)
1.16 millert 842: FATAL("out of memory in format()");
1.1 tholo 843: while (*s) {
1.30 millert 844: adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format1");
1.1 tholo 845: if (*s != '%') {
846: *p++ = *s++;
847: continue;
848: }
849: if (*(s+1) == '%') {
850: *p++ = '%';
851: s += 2;
852: continue;
853: }
1.13 kstailey 854: /* have to be real careful in case this is a huge number, eg, %100000d */
855: fmtwd = atoi(s+1);
856: if (fmtwd < 0)
857: fmtwd = -fmtwd;
1.30 millert 858: adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format2");
1.13 kstailey 859: for (t = fmt; (*t++ = *s) != '\0'; s++) {
1.30 millert 860: if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3"))
1.16 millert 861: FATAL("format item %.30s... ran format() out of memory", os);
1.17 millert 862: if (isalpha((uschar)*s) && *s != 'l' && *s != 'h' && *s != 'L')
1.1 tholo 863: break; /* the ansi panoply */
1.48 millert 864: if (*s == '$') {
865: FATAL("'$' not permitted in awk formats");
866: }
1.1 tholo 867: if (*s == '*') {
1.49 millert 868: if (a == NULL) {
1.27 deraadt 869: FATAL("not enough args in printf(%s)", os);
1.49 millert 870: }
1.1 tholo 871: x = execute(a);
872: a = a->nnext;
1.53 millert 873: snprintf(t - 1, FMTSZ(t - 1),
874: "%d", fmtwd=(int) getfval(x));
1.13 kstailey 875: if (fmtwd < 0)
876: fmtwd = -fmtwd;
877: adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
1.1 tholo 878: t = fmt + strlen(fmt);
879: tempfree(x);
880: }
881: }
882: *t = '\0';
1.13 kstailey 883: if (fmtwd < 0)
884: fmtwd = -fmtwd;
1.30 millert 885: adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format4");
1.1 tholo 886: switch (*s) {
1.47 millert 887: case 'a': case 'A':
888: if (have_a_format)
889: flag = *s;
890: else
891: flag = 'f';
892: break;
1.1 tholo 893: case 'f': case 'e': case 'g': case 'E': case 'G':
1.18 millert 894: flag = 'f';
1.1 tholo 895: break;
896: case 'd': case 'i':
1.18 millert 897: flag = 'd';
1.1 tholo 898: if(*(s-1) == 'l') break;
1.53 millert 899: *(t-1) = 'j';
1.1 tholo 900: *t = 'd';
901: *++t = '\0';
902: break;
903: case 'o': case 'x': case 'X': case 'u':
1.18 millert 904: flag = *(s-1) == 'l' ? 'd' : 'u';
1.53 millert 905: *(t-1) = 'l';
906: *t = *s;
907: *++t = '\0';
1.1 tholo 908: break;
909: case 's':
1.18 millert 910: flag = 's';
1.1 tholo 911: break;
912: case 'c':
1.18 millert 913: flag = 'c';
1.1 tholo 914: break;
915: default:
1.16 millert 916: WARNING("weird printf conversion %s", fmt);
1.18 millert 917: flag = '?';
1.1 tholo 918: break;
919: }
920: if (a == NULL)
1.16 millert 921: FATAL("not enough args in printf(%s)", os);
1.1 tholo 922: x = execute(a);
923: a = a->nnext;
1.13 kstailey 924: n = MAXNUMSIZE;
925: if (fmtwd > n)
926: n = fmtwd;
1.30 millert 927: adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format5");
1.1 tholo 928: switch (flag) {
1.21 tedu 929: case '?': /* unknown, so dump it too */
1.53 millert 930: snprintf(p, BUFSZ(p), "%s", fmt);
1.13 kstailey 931: t = getsval(x);
932: n = strlen(t);
933: if (fmtwd > n)
934: n = fmtwd;
1.30 millert 935: adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format6");
1.5 kstailey 936: p += strlen(p);
1.53 millert 937: snprintf(p, BUFSZ(p), "%s", t);
1.1 tholo 938: break;
1.47 millert 939: case 'a':
940: case 'A':
1.53 millert 941: case 'f': snprintf(p, BUFSZ(p), fmt, getfval(x)); break;
942: case 'd': snprintf(p, BUFSZ(p), fmt, (long) getfval(x)); break;
943: case 'u': snprintf(p, BUFSZ(p), fmt, (int) getfval(x)); break;
1.18 millert 944: case 's':
1.1 tholo 945: t = getsval(x);
946: n = strlen(t);
1.13 kstailey 947: if (fmtwd > n)
948: n = fmtwd;
1.30 millert 949: if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format7"))
1.16 millert 950: FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t);
1.53 millert 951: snprintf(p, BUFSZ(p), fmt, t);
1.1 tholo 952: break;
1.18 millert 953: case 'c':
1.13 kstailey 954: if (isnum(x)) {
1.36 millert 955: if ((int)getfval(x))
1.53 millert 956: snprintf(p, BUFSZ(p), fmt, (int) getfval(x));
1.18 millert 957: else {
958: *p++ = '\0'; /* explicit null byte */
959: *p = '\0'; /* next output will start here */
960: }
1.13 kstailey 961: } else
1.53 millert 962: snprintf(p, BUFSZ(p), fmt, getsval(x)[0]);
1.1 tholo 963: break;
1.18 millert 964: default:
965: FATAL("can't happen: bad conversion %c in format()", flag);
1.1 tholo 966: }
967: tempfree(x);
1.5 kstailey 968: p += strlen(p);
1.1 tholo 969: s++;
970: }
971: *p = '\0';
1.13 kstailey 972: free(fmt);
1.1 tholo 973: for ( ; a; a = a->nnext) /* evaluate any remaining args */
974: execute(a);
1.13 kstailey 975: *pbuf = buf;
976: *pbufsize = bufsize;
977: return p - buf;
1.1 tholo 978: }
979:
980: Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */
981: {
982: Cell *x;
983: Node *y;
1.13 kstailey 984: char *buf;
985: int bufsz=3*recsize;
1.1 tholo 986:
1.53 millert 987: if ((buf = malloc(bufsz)) == NULL)
1.16 millert 988: FATAL("out of memory in awksprintf");
1.1 tholo 989: y = a[0]->nnext;
990: x = execute(a[0]);
1.13 kstailey 991: if (format(&buf, &bufsz, getsval(x), y) == -1)
1.16 millert 992: FATAL("sprintf string %.30s... too long. can't happen.", buf);
1.1 tholo 993: tempfree(x);
994: x = gettemp();
1.13 kstailey 995: x->sval = buf;
1.1 tholo 996: x->tval = STR;
997: return(x);
998: }
999:
1000: Cell *awkprintf(Node **a, int n) /* printf */
1001: { /* a[0] is list of args, starting with format string */
1002: /* a[1] is redirection operator, a[2] is redirection file */
1003: FILE *fp;
1004: Cell *x;
1005: Node *y;
1.13 kstailey 1006: char *buf;
1.9 kstailey 1007: int len;
1.13 kstailey 1008: int bufsz=3*recsize;
1.1 tholo 1009:
1.53 millert 1010: if ((buf = malloc(bufsz)) == NULL)
1.16 millert 1011: FATAL("out of memory in awkprintf");
1.1 tholo 1012: y = a[0]->nnext;
1013: x = execute(a[0]);
1.13 kstailey 1014: if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
1.16 millert 1015: FATAL("printf string %.30s... too long. can't happen.", buf);
1.1 tholo 1016: tempfree(x);
1017: if (a[1] == NULL) {
1.13 kstailey 1018: /* fputs(buf, stdout); */
1.9 kstailey 1019: fwrite(buf, len, 1, stdout);
1.8 kstailey 1020: if (ferror(stdout))
1.16 millert 1021: FATAL("write error on stdout");
1.1 tholo 1022: } else {
1.15 millert 1023: fp = redirect(ptoi(a[1]), a[2]);
1.13 kstailey 1024: /* fputs(buf, fp); */
1.9 kstailey 1025: fwrite(buf, len, 1, fp);
1.8 kstailey 1026: fflush(fp);
1027: if (ferror(fp))
1.16 millert 1028: FATAL("write error on %s", filename(fp));
1.1 tholo 1029: }
1.13 kstailey 1030: free(buf);
1.15 millert 1031: return(True);
1.1 tholo 1032: }
1033:
1034: Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */
1035: {
1036: Awkfloat i, j = 0;
1037: double v;
1038: Cell *x, *y, *z;
1039:
1040: x = execute(a[0]);
1041: i = getfval(x);
1042: tempfree(x);
1.47 millert 1043: if (n != UMINUS && n != UPLUS) {
1.1 tholo 1044: y = execute(a[1]);
1045: j = getfval(y);
1046: tempfree(y);
1047: }
1048: z = gettemp();
1049: switch (n) {
1050: case ADD:
1051: i += j;
1052: break;
1053: case MINUS:
1054: i -= j;
1055: break;
1056: case MULT:
1057: i *= j;
1058: break;
1059: case DIVIDE:
1060: if (j == 0)
1.16 millert 1061: FATAL("division by zero");
1.1 tholo 1062: i /= j;
1063: break;
1064: case MOD:
1065: if (j == 0)
1.16 millert 1066: FATAL("division by zero in mod");
1.1 tholo 1067: modf(i/j, &v);
1068: i = i - j * v;
1069: break;
1070: case UMINUS:
1071: i = -i;
1072: break;
1.47 millert 1073: case UPLUS: /* handled by getfval(), above */
1074: break;
1.1 tholo 1075: case POWER:
1076: if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
1.12 millert 1077: i = ipow(i, (int) j);
1.45 guenther 1078: else {
1079: errno = 0;
1.1 tholo 1080: i = errcheck(pow(i, j), "pow");
1.45 guenther 1081: }
1.1 tholo 1082: break;
1083: default: /* can't happen */
1.16 millert 1084: FATAL("illegal arithmetic operator %d", n);
1.1 tholo 1085: }
1086: setfval(z, i);
1087: return(z);
1088: }
1089:
1090: double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */
1091: {
1092: double v;
1093:
1094: if (n <= 0)
1095: return 1;
1096: v = ipow(x, n/2);
1097: if (n % 2 == 0)
1098: return v * v;
1099: else
1100: return x * v * v;
1101: }
1102:
1103: Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */
1104: {
1105: Cell *x, *z;
1106: int k;
1107: Awkfloat xf;
1108:
1109: x = execute(a[0]);
1110: xf = getfval(x);
1111: k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
1112: if (n == PREINCR || n == PREDECR) {
1113: setfval(x, xf + k);
1114: return(x);
1115: }
1116: z = gettemp();
1117: setfval(z, xf);
1118: setfval(x, xf + k);
1119: tempfree(x);
1120: return(z);
1121: }
1122:
1123: Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */
1124: { /* this is subtle; don't muck with it. */
1125: Cell *x, *y;
1126: Awkfloat xf, yf;
1127: double v;
1128:
1129: y = execute(a[1]);
1130: x = execute(a[0]);
1131: if (n == ASSIGN) { /* ordinary assignment */
1.49 millert 1132: if (x == y && !(x->tval & (FLD|REC)) && x != nfloc)
1133: ; /* self-assignment: leave alone unless it's a field or NF */
1.1 tholo 1134: else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
1135: setsval(x, getsval(y));
1136: x->fval = getfval(y);
1137: x->tval |= NUM;
1138: }
1.13 kstailey 1139: else if (isstr(y))
1.1 tholo 1140: setsval(x, getsval(y));
1.13 kstailey 1141: else if (isnum(y))
1.1 tholo 1142: setfval(x, getfval(y));
1143: else
1144: funnyvar(y, "read value of");
1145: tempfree(y);
1146: return(x);
1147: }
1148: xf = getfval(x);
1149: yf = getfval(y);
1150: switch (n) {
1151: case ADDEQ:
1152: xf += yf;
1153: break;
1154: case SUBEQ:
1155: xf -= yf;
1156: break;
1157: case MULTEQ:
1158: xf *= yf;
1159: break;
1160: case DIVEQ:
1161: if (yf == 0)
1.16 millert 1162: FATAL("division by zero in /=");
1.1 tholo 1163: xf /= yf;
1164: break;
1165: case MODEQ:
1166: if (yf == 0)
1.16 millert 1167: FATAL("division by zero in %%=");
1.1 tholo 1168: modf(xf/yf, &v);
1169: xf = xf - yf * v;
1170: break;
1171: case POWEQ:
1172: if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */
1.12 millert 1173: xf = ipow(xf, (int) yf);
1.45 guenther 1174: else {
1175: errno = 0;
1.1 tholo 1176: xf = errcheck(pow(xf, yf), "pow");
1.45 guenther 1177: }
1.1 tholo 1178: break;
1179: default:
1.16 millert 1180: FATAL("illegal assignment operator %d", n);
1.1 tholo 1181: break;
1182: }
1183: tempfree(y);
1184: setfval(x, xf);
1185: return(x);
1186: }
1187:
1188: Cell *cat(Node **a, int q) /* a[0] cat a[1] */
1189: {
1190: Cell *x, *y, *z;
1191: int n1, n2;
1.49 millert 1192: char *s = NULL;
1193: int ssz = 0;
1.1 tholo 1194:
1195: x = execute(a[0]);
1.49 millert 1196: n1 = strlen(getsval(x));
1197:
1.1 tholo 1198: y = execute(a[1]);
1.49 millert 1199: n2 = strlen(getsval(y));
1.53 millert 1200:
1201: adjbuf(&s, &ssz, n1 + n2 + 1, recsize, 0, "cat");
1202: memcpy(s, x->sval, n1);
1203: memcpy(s + n1, y->sval, n2);
1204: s[n1 + n2] = '\0';
1.49 millert 1205:
1.31 millert 1206: tempfree(x);
1.1 tholo 1207: tempfree(y);
1.49 millert 1208:
1.1 tholo 1209: z = gettemp();
1210: z->sval = s;
1211: z->tval = STR;
1.49 millert 1212:
1.1 tholo 1213: return(z);
1214: }
1215:
1216: Cell *pastat(Node **a, int n) /* a[0] { a[1] } */
1217: {
1218: Cell *x;
1219:
1.51 millert 1220: if (a[0] == NULL)
1.1 tholo 1221: x = execute(a[1]);
1222: else {
1223: x = execute(a[0]);
1224: if (istrue(x)) {
1225: tempfree(x);
1226: x = execute(a[1]);
1227: }
1228: }
1229: return x;
1230: }
1231:
1232: Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */
1233: {
1234: Cell *x;
1235: int pair;
1236:
1.15 millert 1237: pair = ptoi(a[3]);
1.1 tholo 1238: if (pairstack[pair] == 0) {
1239: x = execute(a[0]);
1240: if (istrue(x))
1241: pairstack[pair] = 1;
1242: tempfree(x);
1243: }
1244: if (pairstack[pair] == 1) {
1245: x = execute(a[1]);
1246: if (istrue(x))
1247: pairstack[pair] = 0;
1248: tempfree(x);
1249: x = execute(a[2]);
1250: return(x);
1251: }
1.15 millert 1252: return(False);
1.1 tholo 1253: }
1254:
1255: Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
1256: {
1.51 millert 1257: Cell *x = NULL, *y, *ap;
1.53 millert 1258: const char *s, *origs, *t;
1.51 millert 1259: char *fs = NULL, *origfs = NULL;
1.1 tholo 1260: int sep;
1.53 millert 1261: char temp, num[50];
1.15 millert 1262: int n, tempstat, arg3type;
1.1 tholo 1263:
1264: y = execute(a[0]); /* source string */
1.43 fcambus 1265: origs = s = strdup(getsval(y));
1.44 fcambus 1266: if (s == NULL)
1267: FATAL("out of space in split");
1.15 millert 1268: arg3type = ptoi(a[3]);
1.51 millert 1269: if (a[2] == NULL) /* fs string */
1.49 millert 1270: fs = getsval(fsloc);
1.15 millert 1271: else if (arg3type == STRING) { /* split(str,arr,"string") */
1.1 tholo 1272: x = execute(a[2]);
1.49 millert 1273: origfs = fs = strdup(getsval(x));
1274: if (fs == NULL)
1275: FATAL("out of space in split");
1276: tempfree(x);
1.15 millert 1277: } else if (arg3type == REGEXPR)
1.13 kstailey 1278: fs = "(regexpr)"; /* split(str,arr,/regexpr/) */
1.1 tholo 1279: else
1.16 millert 1280: FATAL("illegal type of split");
1.1 tholo 1281: sep = *fs;
1282: ap = execute(a[1]); /* array name */
1283: freesymtab(ap);
1.42 deraadt 1284: DPRINTF( ("split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs) );
1.1 tholo 1285: ap->tval &= ~STR;
1286: ap->tval |= ARR;
1287: ap->sval = (char *) makesymtab(NSYMTAB);
1288:
1289: n = 0;
1.33 millert 1290: if (arg3type == REGEXPR && strlen((char*)((fa*)a[2])->restr) == 0) {
1291: /* split(s, a, //); have to arrange that it looks like empty sep */
1292: arg3type = 0;
1293: fs = "";
1294: sep = 0;
1295: }
1.25 millert 1296: if (*s != '\0' && (strlen(fs) > 1 || arg3type == REGEXPR)) { /* reg expr */
1.1 tholo 1297: fa *pfa;
1.15 millert 1298: if (arg3type == REGEXPR) { /* it's ready already */
1.1 tholo 1299: pfa = (fa *) a[2];
1300: } else {
1301: pfa = makedfa(fs, 1);
1302: }
1303: if (nematch(pfa,s)) {
1304: tempstat = pfa->initstat;
1305: pfa->initstat = 2;
1306: do {
1307: n++;
1.53 millert 1308: snprintf(num, sizeof(num), "%d", n);
1.1 tholo 1309: temp = *patbeg;
1.53 millert 1310: setptr(patbeg, '\0');
1.14 millert 1311: if (is_number(s))
1.13 kstailey 1312: setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
1.1 tholo 1313: else
1314: setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1.53 millert 1315: setptr(patbeg, temp);
1.1 tholo 1316: s = patbeg + patlen;
1317: if (*(patbeg+patlen-1) == 0 || *s == 0) {
1318: n++;
1.53 millert 1319: snprintf(num, sizeof(num), "%d", n);
1.1 tholo 1320: setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
1321: pfa->initstat = tempstat;
1322: goto spdone;
1323: }
1324: } while (nematch(pfa,s));
1.25 millert 1325: pfa->initstat = tempstat; /* bwk: has to be here to reset */
1326: /* cf gsub and refldbld */
1.1 tholo 1327: }
1328: n++;
1.53 millert 1329: snprintf(num, sizeof(num), "%d", n);
1.14 millert 1330: if (is_number(s))
1.13 kstailey 1331: setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
1.1 tholo 1332: else
1333: setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1334: spdone:
1335: pfa = NULL;
1336: } else if (sep == ' ') {
1337: for (n = 0; ; ) {
1338: while (*s == ' ' || *s == '\t' || *s == '\n')
1339: s++;
1340: if (*s == 0)
1341: break;
1342: n++;
1343: t = s;
1344: do
1345: s++;
1346: while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
1347: temp = *s;
1.53 millert 1348: setptr(s, '\0');
1349: snprintf(num, sizeof(num), "%d", n);
1.14 millert 1350: if (is_number(t))
1.13 kstailey 1351: setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1.1 tholo 1352: else
1353: setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1.53 millert 1354: setptr(s, temp);
1.1 tholo 1355: if (*s != 0)
1356: s++;
1357: }
1358: } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */
1359: for (n = 0; *s != 0; s++) {
1360: char buf[2];
1361: n++;
1.53 millert 1362: snprintf(num, sizeof(num), "%d", n);
1.1 tholo 1363: buf[0] = *s;
1364: buf[1] = 0;
1.17 millert 1365: if (isdigit((uschar)buf[0]))
1.1 tholo 1366: setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval);
1367: else
1368: setsymtab(num, buf, 0.0, STR, (Array *) ap->sval);
1369: }
1370: } else if (*s != 0) {
1371: for (;;) {
1372: n++;
1373: t = s;
1374: while (*s != sep && *s != '\n' && *s != '\0')
1375: s++;
1376: temp = *s;
1.53 millert 1377: setptr(s, '\0');
1378: snprintf(num, sizeof(num), "%d", n);
1.14 millert 1379: if (is_number(t))
1.13 kstailey 1380: setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1.1 tholo 1381: else
1382: setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1.53 millert 1383: setptr(s, temp);
1.1 tholo 1384: if (*s++ == 0)
1385: break;
1386: }
1387: }
1388: tempfree(ap);
1389: tempfree(y);
1.53 millert 1390: xfree(origs);
1391: xfree(origfs);
1.1 tholo 1392: x = gettemp();
1393: x->tval = NUM;
1394: x->fval = n;
1395: return(x);
1396: }
1397:
1398: Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */
1399: {
1400: Cell *x;
1401:
1402: x = execute(a[0]);
1403: if (istrue(x)) {
1404: tempfree(x);
1405: x = execute(a[1]);
1406: } else {
1407: tempfree(x);
1408: x = execute(a[2]);
1409: }
1410: return(x);
1411: }
1412:
1413: Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */
1414: {
1415: Cell *x;
1416:
1417: x = execute(a[0]);
1418: if (istrue(x)) {
1419: tempfree(x);
1420: x = execute(a[1]);
1.51 millert 1421: } else if (a[2] != NULL) {
1.1 tholo 1422: tempfree(x);
1423: x = execute(a[2]);
1424: }
1425: return(x);
1426: }
1427:
1428: Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */
1429: {
1430: Cell *x;
1431:
1432: for (;;) {
1433: x = execute(a[0]);
1434: if (!istrue(x))
1435: return(x);
1436: tempfree(x);
1437: x = execute(a[1]);
1438: if (isbreak(x)) {
1.15 millert 1439: x = True;
1.1 tholo 1440: return(x);
1441: }
1442: if (isnext(x) || isexit(x) || isret(x))
1443: return(x);
1444: tempfree(x);
1445: }
1446: }
1447:
1448: Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */
1449: {
1450: Cell *x;
1451:
1452: for (;;) {
1453: x = execute(a[0]);
1454: if (isbreak(x))
1.15 millert 1455: return True;
1.17 millert 1456: if (isnext(x) || isexit(x) || isret(x))
1.1 tholo 1457: return(x);
1458: tempfree(x);
1459: x = execute(a[1]);
1460: if (!istrue(x))
1461: return(x);
1462: tempfree(x);
1463: }
1464: }
1465:
1466: Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */
1467: {
1468: Cell *x;
1469:
1470: x = execute(a[0]);
1471: tempfree(x);
1472: for (;;) {
1.51 millert 1473: if (a[1]!=NULL) {
1.1 tholo 1474: x = execute(a[1]);
1475: if (!istrue(x)) return(x);
1476: else tempfree(x);
1477: }
1478: x = execute(a[3]);
1479: if (isbreak(x)) /* turn off break */
1.15 millert 1480: return True;
1.1 tholo 1481: if (isnext(x) || isexit(x) || isret(x))
1482: return(x);
1483: tempfree(x);
1484: x = execute(a[2]);
1485: tempfree(x);
1486: }
1487: }
1488:
1489: Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */
1490: {
1491: Cell *x, *vp, *arrayp, *cp, *ncp;
1492: Array *tp;
1493: int i;
1494:
1495: vp = execute(a[0]);
1496: arrayp = execute(a[1]);
1497: if (!isarr(arrayp)) {
1.15 millert 1498: return True;
1.1 tholo 1499: }
1500: tp = (Array *) arrayp->sval;
1501: tempfree(arrayp);
1502: for (i = 0; i < tp->size; i++) { /* this routine knows too much */
1503: for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1504: setsval(vp, cp->nval);
1505: ncp = cp->cnext;
1506: x = execute(a[2]);
1507: if (isbreak(x)) {
1508: tempfree(vp);
1.15 millert 1509: return True;
1.1 tholo 1510: }
1511: if (isnext(x) || isexit(x) || isret(x)) {
1512: tempfree(vp);
1513: return(x);
1514: }
1515: tempfree(x);
1516: }
1517: }
1.15 millert 1518: return True;
1.1 tholo 1519: }
1520:
1521: Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */
1522: {
1523: Cell *x, *y;
1524: Awkfloat u;
1525: int t;
1.33 millert 1526: Awkfloat tmp;
1.13 kstailey 1527: char *p, *buf;
1.1 tholo 1528: Node *nextarg;
1529: FILE *fp;
1.47 millert 1530: int status = 0;
1.1 tholo 1531:
1.15 millert 1532: t = ptoi(a[0]);
1.1 tholo 1533: x = execute(a[1]);
1534: nextarg = a[1]->nnext;
1535: switch (t) {
1536: case FLENGTH:
1.18 millert 1537: if (isarr(x))
1538: u = ((Array *) x->sval)->nelem; /* GROT. should be function*/
1539: else
1540: u = strlen(getsval(x));
1541: break;
1.1 tholo 1542: case FLOG:
1.45 guenther 1543: errno = 0;
1.1 tholo 1544: u = errcheck(log(getfval(x)), "log"); break;
1545: case FINT:
1546: modf(getfval(x), &u); break;
1547: case FEXP:
1.45 guenther 1548: errno = 0;
1.1 tholo 1549: u = errcheck(exp(getfval(x)), "exp"); break;
1550: case FSQRT:
1.45 guenther 1551: errno = 0;
1.1 tholo 1552: u = errcheck(sqrt(getfval(x)), "sqrt"); break;
1553: case FSIN:
1554: u = sin(getfval(x)); break;
1555: case FCOS:
1556: u = cos(getfval(x)); break;
1557: case FATAN:
1.51 millert 1558: if (nextarg == NULL) {
1.16 millert 1559: WARNING("atan2 requires two arguments; returning 1.0");
1.1 tholo 1560: u = 1.0;
1561: } else {
1562: y = execute(a[1]->nnext);
1563: u = atan2(getfval(x), getfval(y));
1564: tempfree(y);
1565: nextarg = nextarg->nnext;
1566: }
1.29 pyr 1567: break;
1568: case FCOMPL:
1569: u = ~((int)getfval(x));
1570: break;
1571: case FAND:
1572: if (nextarg == 0) {
1573: WARNING("and requires two arguments; returning 0");
1574: u = 0;
1575: break;
1576: }
1577: y = execute(a[1]->nnext);
1578: u = ((int)getfval(x)) & ((int)getfval(y));
1579: tempfree(y);
1580: nextarg = nextarg->nnext;
1581: break;
1582: case FFOR:
1583: if (nextarg == 0) {
1584: WARNING("or requires two arguments; returning 0");
1585: u = 0;
1586: break;
1587: }
1588: y = execute(a[1]->nnext);
1589: u = ((int)getfval(x)) | ((int)getfval(y));
1590: tempfree(y);
1591: nextarg = nextarg->nnext;
1592: break;
1593: case FXOR:
1594: if (nextarg == 0) {
1.41 ajacouto 1595: WARNING("xor requires two arguments; returning 0");
1.29 pyr 1596: u = 0;
1597: break;
1598: }
1599: y = execute(a[1]->nnext);
1600: u = ((int)getfval(x)) ^ ((int)getfval(y));
1601: tempfree(y);
1602: nextarg = nextarg->nnext;
1603: break;
1604: case FLSHIFT:
1605: if (nextarg == 0) {
1.41 ajacouto 1606: WARNING("lshift requires two arguments; returning 0");
1.29 pyr 1607: u = 0;
1608: break;
1609: }
1610: y = execute(a[1]->nnext);
1611: u = ((int)getfval(x)) << ((int)getfval(y));
1612: tempfree(y);
1613: nextarg = nextarg->nnext;
1614: break;
1615: case FRSHIFT:
1616: if (nextarg == 0) {
1.41 ajacouto 1617: WARNING("rshift requires two arguments; returning 0");
1.29 pyr 1618: u = 0;
1619: break;
1620: }
1621: y = execute(a[1]->nnext);
1622: u = ((int)getfval(x)) >> ((int)getfval(y));
1623: tempfree(y);
1624: nextarg = nextarg->nnext;
1.1 tholo 1625: break;
1626: case FSYSTEM:
1627: fflush(stdout); /* in case something is buffered already */
1.47 millert 1628: status = system(getsval(x));
1629: u = status;
1630: if (status != -1) {
1631: if (WIFEXITED(status)) {
1632: u = WEXITSTATUS(status);
1633: } else if (WIFSIGNALED(status)) {
1634: u = WTERMSIG(status) + 256;
1635: #ifdef WCOREDUMP
1636: if (WCOREDUMP(status))
1637: u += 256;
1638: #endif
1639: } else /* something else?!? */
1640: u = 0;
1641: }
1.1 tholo 1642: break;
1643: case FRAND:
1.51 millert 1644: /* random() returns numbers in [0..2^31-1]
1645: * in order to get a number in [0, 1), divide it by 2^31
1646: */
1647: u = (Awkfloat) random() / (0x7fffffffL + 0x1UL);
1.1 tholo 1648: break;
1649: case FSRAND:
1.39 deraadt 1650: if (isrec(x)) { /* no argument provided */
1651: u = time(NULL);
1652: tmp = u;
1653: srandom((unsigned int) u);
1654: } else {
1.33 millert 1655: u = getfval(x);
1656: tmp = u;
1.37 deraadt 1657: srandom_deterministic((unsigned int) u);
1.24 millert 1658: }
1.39 deraadt 1659: u = srand_seed;
1660: srand_seed = tmp;
1.1 tholo 1661: break;
1662: case FTOUPPER:
1663: case FTOLOWER:
1.13 kstailey 1664: buf = tostring(getsval(x));
1.1 tholo 1665: if (t == FTOUPPER) {
1666: for (p = buf; *p; p++)
1.17 millert 1667: if (islower((uschar) *p))
1.25 millert 1668: *p = toupper((uschar)*p);
1.1 tholo 1669: } else {
1670: for (p = buf; *p; p++)
1.17 millert 1671: if (isupper((uschar) *p))
1.25 millert 1672: *p = tolower((uschar)*p);
1.1 tholo 1673: }
1674: tempfree(x);
1675: x = gettemp();
1676: setsval(x, buf);
1.13 kstailey 1677: free(buf);
1.1 tholo 1678: return x;
1679: case FFLUSH:
1.18 millert 1680: if (isrec(x) || strlen(getsval(x)) == 0) {
1681: flush_all(); /* fflush() or fflush("") -> all */
1682: u = 0;
1683: } else if ((fp = openfile(FFLUSH, getsval(x))) == NULL)
1.1 tholo 1684: u = EOF;
1685: else
1686: u = fflush(fp);
1687: break;
1688: default: /* can't happen */
1.16 millert 1689: FATAL("illegal function type %d", t);
1.1 tholo 1690: break;
1691: }
1692: tempfree(x);
1693: x = gettemp();
1694: setfval(x, u);
1.51 millert 1695: if (nextarg != NULL) {
1.16 millert 1696: WARNING("warning: function has too many arguments");
1.1 tholo 1697: for ( ; nextarg; nextarg = nextarg->nnext)
1698: execute(nextarg);
1699: }
1700: return(x);
1701: }
1702:
1703: Cell *printstat(Node **a, int n) /* print a[0] */
1704: {
1705: Node *x;
1706: Cell *y;
1707: FILE *fp;
1708:
1.51 millert 1709: if (a[1] == NULL) /* a[1] is redirection operator, a[2] is file */
1.1 tholo 1710: fp = stdout;
1711: else
1.15 millert 1712: fp = redirect(ptoi(a[1]), a[2]);
1.1 tholo 1713: for (x = a[0]; x != NULL; x = x->nnext) {
1714: y = execute(x);
1.18 millert 1715: fputs(getpssval(y), fp);
1.1 tholo 1716: tempfree(y);
1717: if (x->nnext == NULL)
1.49 millert 1718: fputs(getsval(orsloc), fp);
1.1 tholo 1719: else
1.49 millert 1720: fputs(getsval(ofsloc), fp);
1.1 tholo 1721: }
1.51 millert 1722: if (a[1] != NULL)
1.1 tholo 1723: fflush(fp);
1724: if (ferror(fp))
1.16 millert 1725: FATAL("write error on %s", filename(fp));
1.15 millert 1726: return(True);
1.1 tholo 1727: }
1728:
1729: Cell *nullproc(Node **a, int n)
1730: {
1731: return 0;
1732: }
1733:
1734:
1735: FILE *redirect(int a, Node *b) /* set up all i/o redirections */
1736: {
1737: FILE *fp;
1738: Cell *x;
1739: char *fname;
1740:
1741: x = execute(b);
1742: fname = getsval(x);
1743: fp = openfile(a, fname);
1744: if (fp == NULL)
1.16 millert 1745: FATAL("can't open file %s", fname);
1.1 tholo 1746: tempfree(x);
1747: return fp;
1748: }
1749:
1750: struct files {
1751: FILE *fp;
1.18 millert 1752: const char *fname;
1.1 tholo 1753: int mode; /* '|', 'a', 'w' => LE/LT, GT */
1.33 millert 1754: } *files;
1755:
1756: int nfiles;
1.1 tholo 1757:
1.16 millert 1758: void stdinit(void) /* in case stdin, etc., are not constants */
1759: {
1.33 millert 1760: nfiles = FOPEN_MAX;
1761: files = calloc(nfiles, sizeof(*files));
1762: if (files == NULL)
1763: FATAL("can't allocate file memory for %u files", nfiles);
1764: files[0].fp = stdin;
1765: files[0].fname = "/dev/stdin";
1766: files[0].mode = LT;
1767: files[1].fp = stdout;
1768: files[1].fname = "/dev/stdout";
1769: files[1].mode = GT;
1770: files[2].fp = stderr;
1771: files[2].fname = "/dev/stderr";
1772: files[2].mode = GT;
1.16 millert 1773: }
1774:
1.18 millert 1775: FILE *openfile(int a, const char *us)
1.1 tholo 1776: {
1.18 millert 1777: const char *s = us;
1.1 tholo 1778: int i, m;
1.51 millert 1779: FILE *fp = NULL;
1.1 tholo 1780:
1781: if (*s == '\0')
1.16 millert 1782: FATAL("null file name in print or getline");
1.33 millert 1783: for (i=0; i < nfiles; i++)
1.13 kstailey 1784: if (files[i].fname && strcmp(s, files[i].fname) == 0) {
1.1 tholo 1785: if (a == files[i].mode || (a==APPEND && files[i].mode==GT))
1786: return files[i].fp;
1.13 kstailey 1787: if (a == FFLUSH)
1788: return files[i].fp;
1789: }
1790: if (a == FFLUSH) /* didn't find it, so don't create it! */
1791: return NULL;
1792:
1.33 millert 1793: for (i=0; i < nfiles; i++)
1.51 millert 1794: if (files[i].fp == NULL)
1.1 tholo 1795: break;
1.33 millert 1796: if (i >= nfiles) {
1797: struct files *nf;
1798: int nnf = nfiles + FOPEN_MAX;
1.35 doug 1799: nf = reallocarray(files, nnf, sizeof(*nf));
1.33 millert 1800: if (nf == NULL)
1801: FATAL("cannot grow files for %s and %d files", s, nnf);
1802: memset(&nf[nfiles], 0, FOPEN_MAX * sizeof(*nf));
1803: nfiles = nnf;
1804: files = nf;
1805: }
1.1 tholo 1806: fflush(stdout); /* force a semblance of order */
1807: m = a;
1808: if (a == GT) {
1809: fp = fopen(s, "w");
1810: } else if (a == APPEND) {
1811: fp = fopen(s, "a");
1812: m = GT; /* so can mix > and >> */
1813: } else if (a == '|') { /* output pipe */
1814: fp = popen(s, "w");
1815: } else if (a == LE) { /* input pipe */
1816: fp = popen(s, "r");
1817: } else if (a == LT) { /* getline <file */
1818: fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */
1819: } else /* can't happen */
1.16 millert 1820: FATAL("illegal redirection %d", a);
1.1 tholo 1821: if (fp != NULL) {
1822: files[i].fname = tostring(s);
1823: files[i].fp = fp;
1824: files[i].mode = m;
1825: }
1826: return fp;
1827: }
1828:
1.18 millert 1829: const char *filename(FILE *fp)
1.1 tholo 1830: {
1831: int i;
1832:
1.33 millert 1833: for (i = 0; i < nfiles; i++)
1.1 tholo 1834: if (fp == files[i].fp)
1835: return files[i].fname;
1836: return "???";
1837: }
1838:
1839: Cell *closefile(Node **a, int n)
1840: {
1841: Cell *x;
1842: int i, stat;
1843:
1844: x = execute(a[0]);
1845: getsval(x);
1.17 millert 1846: stat = -1;
1.33 millert 1847: for (i = 0; i < nfiles; i++) {
1.1 tholo 1848: if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) {
1849: if (ferror(files[i].fp))
1.16 millert 1850: WARNING( "i/o error occurred on %s", files[i].fname );
1.1 tholo 1851: if (files[i].mode == '|' || files[i].mode == LE)
1852: stat = pclose(files[i].fp);
1853: else
1854: stat = fclose(files[i].fp);
1855: if (stat == EOF)
1.16 millert 1856: WARNING( "i/o error occurred closing %s", files[i].fname );
1.1 tholo 1857: if (i > 2) /* don't do /dev/std... */
1858: xfree(files[i].fname);
1859: files[i].fname = NULL; /* watch out for ref thru this */
1860: files[i].fp = NULL;
1861: }
1.17 millert 1862: }
1.1 tholo 1863: tempfree(x);
1.17 millert 1864: x = gettemp();
1865: setfval(x, (Awkfloat) stat);
1866: return(x);
1.1 tholo 1867: }
1868:
1869: void closeall(void)
1870: {
1871: int i, stat;
1872:
1.17 millert 1873: for (i = 0; i < FOPEN_MAX; i++) {
1.1 tholo 1874: if (files[i].fp) {
1875: if (ferror(files[i].fp))
1.16 millert 1876: WARNING( "i/o error occurred on %s", files[i].fname );
1.1 tholo 1877: if (files[i].mode == '|' || files[i].mode == LE)
1878: stat = pclose(files[i].fp);
1879: else
1880: stat = fclose(files[i].fp);
1881: if (stat == EOF)
1.16 millert 1882: WARNING( "i/o error occurred while closing %s", files[i].fname );
1.1 tholo 1883: }
1.17 millert 1884: }
1.18 millert 1885: }
1886:
1887: void flush_all(void)
1888: {
1889: int i;
1890:
1.33 millert 1891: for (i = 0; i < nfiles; i++)
1.18 millert 1892: if (files[i].fp)
1893: fflush(files[i].fp);
1.1 tholo 1894: }
1895:
1.53 millert 1896: void backsub(char **pb_ptr, const char **sptr_ptr);
1.1 tholo 1897:
1898: Cell *sub(Node **a, int nnn) /* substitute command */
1899: {
1.53 millert 1900: const char *sptr, *q;
1.1 tholo 1901: Cell *x, *y, *result;
1.53 millert 1902: char *t, *buf, *pb;
1.1 tholo 1903: fa *pfa;
1.13 kstailey 1904: int bufsz = recsize;
1.1 tholo 1905:
1.53 millert 1906: if ((buf = malloc(bufsz)) == NULL)
1.16 millert 1907: FATAL("out of memory in sub");
1.1 tholo 1908: x = execute(a[3]); /* target string */
1909: t = getsval(x);
1.51 millert 1910: if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */
1.1 tholo 1911: pfa = (fa *) a[1]; /* regular expression */
1912: else {
1913: y = execute(a[1]);
1914: pfa = makedfa(getsval(y), 1);
1915: tempfree(y);
1916: }
1917: y = execute(a[2]); /* replacement string */
1.15 millert 1918: result = False;
1.1 tholo 1919: if (pmatch(pfa, t)) {
1.13 kstailey 1920: sptr = t;
1921: adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub");
1.1 tholo 1922: pb = buf;
1923: while (sptr < patbeg)
1924: *pb++ = *sptr++;
1925: sptr = getsval(y);
1.13 kstailey 1926: while (*sptr != 0) {
1927: adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub");
1928: if (*sptr == '\\') {
1929: backsub(&pb, &sptr);
1.1 tholo 1930: } else if (*sptr == '&') {
1931: sptr++;
1.13 kstailey 1932: adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub");
1.1 tholo 1933: for (q = patbeg; q < patbeg+patlen; )
1934: *pb++ = *q++;
1935: } else
1936: *pb++ = *sptr++;
1.13 kstailey 1937: }
1.1 tholo 1938: *pb = '\0';
1.13 kstailey 1939: if (pb > buf + bufsz)
1.16 millert 1940: FATAL("sub result1 %.30s too big; can't happen", buf);
1.1 tholo 1941: sptr = patbeg + patlen;
1.13 kstailey 1942: if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
1943: adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
1.1 tholo 1944: while ((*pb++ = *sptr++) != 0)
1945: ;
1.13 kstailey 1946: }
1947: if (pb > buf + bufsz)
1.16 millert 1948: FATAL("sub result2 %.30s too big; can't happen", buf);
1.13 kstailey 1949: setsval(x, buf); /* BUG: should be able to avoid copy */
1.23 millert 1950: result = True;
1.1 tholo 1951: }
1952: tempfree(x);
1953: tempfree(y);
1.13 kstailey 1954: free(buf);
1.1 tholo 1955: return result;
1956: }
1957:
1958: Cell *gsub(Node **a, int nnn) /* global substitute */
1959: {
1960: Cell *x, *y;
1.53 millert 1961: char *rptr, *pb;
1962: const char *q, *t, *sptr;
1.13 kstailey 1963: char *buf;
1.1 tholo 1964: fa *pfa;
1965: int mflag, tempstat, num;
1.13 kstailey 1966: int bufsz = recsize;
1.1 tholo 1967:
1.53 millert 1968: if ((buf = malloc(bufsz)) == NULL)
1.16 millert 1969: FATAL("out of memory in gsub");
1.1 tholo 1970: mflag = 0; /* if mflag == 0, can replace empty string */
1971: num = 0;
1972: x = execute(a[3]); /* target string */
1973: t = getsval(x);
1.51 millert 1974: if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */
1.1 tholo 1975: pfa = (fa *) a[1]; /* regular expression */
1976: else {
1977: y = execute(a[1]);
1978: pfa = makedfa(getsval(y), 1);
1979: tempfree(y);
1980: }
1981: y = execute(a[2]); /* replacement string */
1982: if (pmatch(pfa, t)) {
1983: tempstat = pfa->initstat;
1984: pfa->initstat = 2;
1985: pb = buf;
1986: rptr = getsval(y);
1987: do {
1988: if (patlen == 0 && *patbeg != 0) { /* matched empty string */
1989: if (mflag == 0) { /* can replace empty */
1990: num++;
1991: sptr = rptr;
1.13 kstailey 1992: while (*sptr != 0) {
1993: adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1994: if (*sptr == '\\') {
1995: backsub(&pb, &sptr);
1.1 tholo 1996: } else if (*sptr == '&') {
1997: sptr++;
1.13 kstailey 1998: adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1.1 tholo 1999: for (q = patbeg; q < patbeg+patlen; )
2000: *pb++ = *q++;
2001: } else
2002: *pb++ = *sptr++;
1.13 kstailey 2003: }
1.1 tholo 2004: }
2005: if (*t == 0) /* at end */
2006: goto done;
1.13 kstailey 2007: adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
1.1 tholo 2008: *pb++ = *t++;
1.13 kstailey 2009: if (pb > buf + bufsz) /* BUG: not sure of this test */
1.16 millert 2010: FATAL("gsub result0 %.30s too big; can't happen", buf);
1.1 tholo 2011: mflag = 0;
2012: }
2013: else { /* matched nonempty string */
2014: num++;
2015: sptr = t;
1.13 kstailey 2016: adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub");
2017: while (sptr < patbeg)
1.1 tholo 2018: *pb++ = *sptr++;
2019: sptr = rptr;
1.13 kstailey 2020: while (*sptr != 0) {
2021: adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
2022: if (*sptr == '\\') {
2023: backsub(&pb, &sptr);
1.1 tholo 2024: } else if (*sptr == '&') {
2025: sptr++;
1.13 kstailey 2026: adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1.1 tholo 2027: for (q = patbeg; q < patbeg+patlen; )
2028: *pb++ = *q++;
2029: } else
2030: *pb++ = *sptr++;
1.13 kstailey 2031: }
1.1 tholo 2032: t = patbeg + patlen;
2033: if (patlen == 0 || *t == 0 || *(t-1) == 0)
2034: goto done;
1.13 kstailey 2035: if (pb > buf + bufsz)
1.16 millert 2036: FATAL("gsub result1 %.30s too big; can't happen", buf);
1.1 tholo 2037: mflag = 1;
2038: }
2039: } while (pmatch(pfa,t));
2040: sptr = t;
1.13 kstailey 2041: adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
1.1 tholo 2042: while ((*pb++ = *sptr++) != 0)
2043: ;
1.31 millert 2044: done: if (pb < buf + bufsz)
2045: *pb = '\0';
2046: else if (*(pb-1) != '\0')
2047: FATAL("gsub result2 %.30s truncated; can't happen", buf);
1.13 kstailey 2048: setsval(x, buf); /* BUG: should be able to avoid copy + free */
1.1 tholo 2049: pfa->initstat = tempstat;
2050: }
2051: tempfree(x);
2052: tempfree(y);
2053: x = gettemp();
2054: x->tval = NUM;
2055: x->fval = num;
1.13 kstailey 2056: free(buf);
1.1 tholo 2057: return(x);
1.13 kstailey 2058: }
2059:
1.53 millert 2060: void backsub(char **pb_ptr, const char **sptr_ptr) /* handle \\& variations */
1.13 kstailey 2061: { /* sptr[0] == '\\' */
1.53 millert 2062: char *pb = *pb_ptr;
2063: const char *sptr = *sptr_ptr;
1.13 kstailey 2064:
2065: if (sptr[1] == '\\') {
2066: if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
2067: *pb++ = '\\';
2068: *pb++ = '&';
2069: sptr += 4;
2070: } else if (sptr[2] == '&') { /* \\& -> \ + matched */
2071: *pb++ = '\\';
2072: sptr += 2;
2073: } else { /* \\x -> \\x */
2074: *pb++ = *sptr++;
2075: *pb++ = *sptr++;
2076: }
2077: } else if (sptr[1] == '&') { /* literal & */
2078: sptr++;
2079: *pb++ = *sptr++;
2080: } else /* literal \ */
2081: *pb++ = *sptr++;
2082:
2083: *pb_ptr = pb;
2084: *sptr_ptr = sptr;
1.1 tholo 2085: }