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