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