1 /****************************************************************
2 Copyright (C) Lucent Technologies 1997
5 Permission to use, copy, modify, and distribute this software and
6 its documentation for any purpose and without fee is hereby
7 granted, provided that the above copyright notice appear in all
8 copies and that both that the copyright notice and this
9 permission notice and warranty disclaimer appear in supporting
10 documentation, and that the name Lucent Technologies or any of
11 its entities not be used in advertising or publicity pertaining
12 to distribution of the software without specific, written prior
15 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
23 ****************************************************************/
25 #include <sys/cdefs.h>
26 __FBSDID("$FreeBSD$");
37 #include <sys/types.h>
42 #define tempfree(x) if (istemp(x)) tfree(x); else
47 void tempfree(Cell *p) {
48 if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) {
49 WARNING("bad csub %d in Cell %d %s",
50 p->csub, p->ctype, p->sval);
57 /* do we really need these? */
59 /* #ifndef FOPEN_MAX */
60 /* #define FOPEN_MAX _NFILE */
64 /* #ifndef FOPEN_MAX */
65 /* #define FOPEN_MAX 40 */ /* max number of open files */
68 /* #ifndef RAND_MAX */
69 /* #define RAND_MAX 32767 */ /* all that ansi guarantees */
73 extern int pairstack[];
74 extern Awkfloat srand_seed;
76 Node *winner = NULL; /* root of parse tree */
77 Cell *tmps; /* free temporary cells for execution */
79 static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM, NULL };
80 Cell *True = &truecell;
81 static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM, NULL };
82 Cell *False = &falsecell;
83 static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM, NULL };
84 Cell *jbreak = &breakcell;
85 static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM, NULL };
86 Cell *jcont = &contcell;
87 static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM, NULL };
88 Cell *jnext = &nextcell;
89 static Cell nextfilecell ={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM, NULL };
90 Cell *jnextfile = &nextfilecell;
91 static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM, NULL };
92 Cell *jexit = &exitcell;
93 static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM, NULL };
94 Cell *jret = &retcell;
95 static Cell tempcell ={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE, NULL };
97 Node *curnode = NULL; /* the node being executed, for debugging */
99 /* buffer memory management */
100 int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,
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
109 * return 0 for realloc failure, !=0 for success
112 if (minlen > *psiz) {
114 int rminlen = quantum ? minlen % quantum : 0;
115 int boff = pbptr ? *pbptr - *pbuf : 0;
116 /* round up to next multiple of quantum */
118 minlen += quantum - rminlen;
119 tbuf = (char *) realloc(*pbuf, minlen);
120 dprintf( ("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, (void *) *pbuf, (void *) tbuf) );
123 FATAL("out of memory in %s", whatrtn);
129 *pbptr = tbuf + boff;
134 void run(Node *a) /* execution of parse tree starts here */
136 extern void stdinit(void);
143 Cell *execute(Node *u) /* execute a node of the parse tree */
145 Cell *(*proc)(Node **, int);
151 for (a = u; ; a = a->nnext) {
154 x = (Cell *) (a->narg[0]);
155 if (isfld(x) && !donefld)
157 else if (isrec(x) && !donerec)
161 if (notlegal(a->nobj)) /* probably a Cell* but too risky to print */
162 FATAL("illegal statement");
163 proc = proctab[a->nobj-FIRSTTOKEN];
164 x = (*proc)(a->narg, a->nobj);
165 if (isfld(x) && !donefld)
167 else if (isrec(x) && !donerec)
173 if (a->nnext == NULL)
180 Cell *program(Node **a, int n) /* execute an awk program */
181 { /* a[0] = BEGIN, a[1] = body, a[2] = END */
184 if (setjmp(env) != 0)
186 if (a[0]) { /* BEGIN */
191 FATAL("illegal break, continue, next or nextfile from BEGIN");
195 while (getrec(&record, &recsize, 1) > 0) {
202 if (setjmp(env) != 0) /* handles exit within END */
204 if (a[2]) { /* END */
206 if (isbreak(x) || isnext(x) || iscont(x))
207 FATAL("illegal break, continue, next or nextfile from END");
214 struct Frame { /* stack frame for awk function calls */
215 int nargs; /* number of arguments in this call */
216 Cell *fcncell; /* pointer to Cell for function */
217 Cell **args; /* pointer to array of arguments after execute */
218 Cell *retval; /* return value */
221 #define NARGS 50 /* max args in a call */
223 struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */
224 int nframe = 0; /* number of frames allocated */
225 struct Frame *fp = NULL; /* frame pointer. bottom level unused */
227 Cell *call(Node **a, int n) /* function call. very kludgy and fragile */
229 static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE, NULL };
231 int freed = 0; /* handles potential double freeing when fcn & param share a tempcell */
233 Cell *args[NARGS], *oargs[NARGS]; /* BUG: fixed size arrays */
237 fcn = execute(a[0]); /* the function itself */
240 FATAL("calling undefined function %s", s);
242 fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
244 FATAL("out of space for stack frames calling %s", s);
246 for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */
248 ndef = (int) fcn->fval; /* args in defn */
249 dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) );
251 WARNING("function %s called with %d args, uses only %d",
253 if (ncall + ndef > NARGS)
254 FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS);
255 for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */
256 dprintf( ("evaluate args[%d], fp=%d:\n", i, (int) (fp-frame)) );
259 dprintf( ("args[%d]: %s %f <%s>, t=%o\n",
260 i, NN(y->nval), y->fval, isarr(y) ? "(array)" : NN(y->sval), y->tval) );
262 FATAL("can't use function %s as argument in %s", y->nval, s);
264 args[i] = y; /* arrays by ref */
266 args[i] = copycell(y);
269 for ( ; i < ndef; i++) { /* add null args for ones not provided */
271 *args[i] = newcopycell;
273 fp++; /* now ok to up frame */
274 if (fp >= frame + nframe) {
275 int dfp = fp - frame; /* old index */
276 frame = (struct Frame *)
277 realloc((char *) frame, (nframe += 100) * sizeof(struct Frame));
279 FATAL("out of space for stack frames in %s", s);
284 fp->nargs = ndef; /* number defined with (excess are locals) */
285 fp->retval = gettemp();
287 dprintf( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) );
288 y = execute((Node *)(fcn->sval)); /* execute body */
289 dprintf( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) );
291 for (i = 0; i < ndef; i++) {
292 Cell *t = fp->args[i];
294 if (t->csub == CCOPY) {
300 oargs[i]->tval = t->tval;
301 oargs[i]->tval &= ~(STR|NUM|DONTFREE);
302 oargs[i]->sval = t->sval;
306 } else if (t != y) { /* kludge to prevent freeing twice */
309 } else if (t == y && t->csub == CCOPY) {
316 if (isexit(y) || isnext(y))
319 tempfree(y); /* don't free twice! */
321 z = fp->retval; /* return value */
322 dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );
327 Cell *copycell(Cell *x) /* make a copy of a cell in a temp */
331 /* copy is not constant or field */
334 y->tval = x->tval & ~(CON|FLD|REC);
335 y->csub = CCOPY; /* prevents freeing until call is over */
336 y->nval = x->nval; /* BUG? */
337 if (isstr(x) /* || x->ctype == OCELL */) {
338 y->sval = tostring(x->sval);
339 y->tval &= ~DONTFREE;
346 Cell *arg(Node **a, int n) /* nth argument of a function */
349 n = ptoi(a[0]); /* argument number, counting from 0 */
350 dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );
352 FATAL("argument #%d of function %s was not supplied",
353 n+1, fp->fcncell->nval);
357 Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */
365 errorflag = (int) getfval(y);
372 if ((y->tval & (STR|NUM)) == (STR|NUM)) {
373 setsval(fp->retval, getsval(y));
374 fp->retval->fval = getfval(y);
375 fp->retval->tval |= NUM;
377 else if (y->tval & STR)
378 setsval(fp->retval, getsval(y));
379 else if (y->tval & NUM)
380 setfval(fp->retval, getfval(y));
381 else /* can't happen */
382 FATAL("bad type variable %d", y->tval);
395 default: /* can't happen */
396 FATAL("illegal jump type %d", n);
398 return 0; /* not reached */
401 Cell *awkgetline(Node **a, int n) /* get next line from specific input */
402 { /* a[0] is variable, a[1] is operator, a[2] is filename */
404 extern Cell **fldtab;
407 int bufsize = recsize;
410 if ((buf = (char *) malloc(bufsize)) == NULL)
411 FATAL("out of memory in getline");
413 fflush(stdout); /* in case someone is waiting for a prompt */
415 if (a[1] != NULL) { /* getline < file */
416 x = execute(a[2]); /* filename */
418 if (mode == '|') /* input pipe */
419 mode = LE; /* arbitrary flag */
420 fp = openfile(mode, getsval(x));
425 n = readrec(&buf, &bufsize, fp);
428 } else if (a[0] != NULL) { /* getline var <file */
431 if (is_number(x->sval)) {
432 x->fval = atof(x->sval);
436 } else { /* getline <file */
437 setsval(fldtab[0], buf);
438 if (is_number(fldtab[0]->sval)) {
439 fldtab[0]->fval = atof(fldtab[0]->sval);
440 fldtab[0]->tval |= NUM;
443 } else { /* bare getline; use current input */
444 if (a[0] == NULL) /* getline */
445 n = getrec(&record, &recsize, 1);
446 else { /* getline var */
447 n = getrec(&buf, &bufsize, 0);
450 if (is_number(x->sval)) {
451 x->fval = atof(x->sval);
457 setfval(r, (Awkfloat) n);
462 Cell *getnf(Node **a, int n) /* get NF */
466 return (Cell *) a[0];
469 Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
478 if ((buf = (char *) malloc(bufsz)) == NULL)
479 FATAL("out of memory in array");
481 x = execute(a[0]); /* Cell* for symbol table */
483 for (np = a[1]; np; np = np->nnext) {
484 y = execute(np); /* subscript */
486 nsub = strlen(getsval(subseploc));
487 if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "array"))
488 FATAL("out of memory for %s[%s...]", x->nval, buf);
491 strcat(buf, *SUBSEP);
495 dprintf( ("making %s into an array\n", NN(x->nval)) );
498 x->tval &= ~(STR|NUM|DONTFREE);
500 x->sval = (char *) makesymtab(NSYMTAB);
502 z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
510 Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
517 x = execute(a[0]); /* Cell* for symbol table */
520 if (a[1] == NULL) { /* delete the elements, not the table */
524 x->sval = (char *) makesymtab(NSYMTAB);
528 if ((buf = (char *) malloc(bufsz)) == NULL)
529 FATAL("out of memory in adelete");
531 for (np = a[1]; np; np = np->nnext) {
532 y = execute(np); /* subscript */
534 nsub = strlen(getsval(subseploc));
535 if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "awkdelete"))
536 FATAL("out of memory deleting %s[%s...]", x->nval, buf);
539 strcat(buf, *SUBSEP);
549 Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
558 ap = execute(a[1]); /* array name */
560 dprintf( ("making %s into an array\n", ap->nval) );
563 ap->tval &= ~(STR|NUM|DONTFREE);
565 ap->sval = (char *) makesymtab(NSYMTAB);
567 if ((buf = (char *) malloc(bufsz)) == NULL) {
568 FATAL("out of memory in intest");
571 for (p = a[0]; p; p = p->nnext) {
572 x = execute(p); /* expr */
574 nsub = strlen(getsval(subseploc));
575 if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "intest"))
576 FATAL("out of memory deleting %s[%s...]", x->nval, buf);
580 strcat(buf, *SUBSEP);
582 k = lookup(buf, (Array *) ap->sval);
592 Cell *matchop(Node **a, int n) /* ~ and match() */
598 int (*mf)(fa *, const char *) = match, mode = 0;
604 x = execute(a[1]); /* a[1] = target text */
606 if (a[0] == NULL) /* a[1] == 0: already-compiled reg expr */
607 i = (*mf)((fa *) a[2], s);
609 y = execute(a[2]); /* a[2] = regular expr */
611 pfa = makedfa(t, mode);
617 int start = patbeg - s + 1;
620 setfval(rstartloc, (Awkfloat) start);
621 setfval(rlengthloc, (Awkfloat) patlen);
626 } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
633 Cell *boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */
650 if ( !i ) return(False);
657 if (i) return(False);
659 default: /* can't happen */
660 FATAL("unknown boolean operator %d", n);
662 return 0; /*NOTREACHED*/
665 Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */
673 if (x->tval&NUM && y->tval&NUM) {
674 j = x->fval - y->fval;
675 i = j<0? -1: (j>0? 1: 0);
677 i = strcoll(getsval(x), getsval(y));
682 case LT: if (i<0) return(True);
684 case LE: if (i<=0) return(True);
686 case NE: if (i!=0) return(True);
688 case EQ: if (i == 0) return(True);
690 case GE: if (i>=0) return(True);
692 case GT: if (i>0) return(True);
694 default: /* can't happen */
695 FATAL("unknown relational operator %d", n);
697 return 0; /*NOTREACHED*/
700 void tfree(Cell *a) /* free a tempcell */
703 dprintf( ("freeing %s %s %o\n", NN(a->nval), NN(a->sval), a->tval) );
707 FATAL("tempcell list is curdled");
712 Cell *gettemp(void) /* get a tempcell */
717 tmps = (Cell *) calloc(100, sizeof(Cell));
719 FATAL("out of space for temporaries");
720 for(i = 1; i < 100; i++)
721 tmps[i-1].cnext = &tmps[i];
722 tmps[i-1].cnext = NULL;
730 Cell *indirect(Node **a, int n) /* $( a[0] ) */
738 val = getfval(x); /* freebsd: defend against super large field numbers */
739 if ((Awkfloat)INT_MAX < val)
740 FATAL("trying to access out of range field %s", x->nval);
742 if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */
743 FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
744 /* BUG: can x->nval ever be null??? */
747 x->ctype = OCELL; /* BUG? why are these needed? */
752 Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */
757 Cell *x, *y, *z = NULL;
775 m = (int) getfval(y);
782 n = (int) getfval(z);
790 dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) );
792 temp = s[n+m-1]; /* with thanks to John Linderman */
794 setsval(y, s + m - 1);
800 Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */
803 char *s1, *s2, *p1, *p2, *q;
812 for (p1 = s1; *p1 != '\0'; p1++) {
813 for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
816 v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */
826 #define MAXNUMSIZE 50
828 int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like conversions */
835 int fmtwd; /* format width */
838 int bufsize = *pbufsize;
840 static int first = 1;
841 static int have_a_format = 0;
846 sprintf(buf, "%a", 42.0);
847 have_a_format = (strcmp(buf, "0x1.5p+5") == 0);
853 if ((fmt = (char *) malloc(fmtsz)) == NULL)
854 FATAL("out of memory in format()");
856 adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format1");
866 /* have to be real careful in case this is a huge number, eg, %100000d */
870 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format2");
871 for (t = fmt; (*t++ = *s) != '\0'; s++) {
872 if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3"))
873 FATAL("format item %.30s... ran format() out of memory", os);
874 if (isalpha((uschar)*s) && *s != 'l' && *s != 'h' && *s != 'L')
875 break; /* the ansi panoply */
877 FATAL("'$' not permitted in awk formats");
881 FATAL("not enough args in printf(%s)", os);
885 sprintf(t-1, "%d", fmtwd=(int) getfval(x));
888 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
889 t = fmt + strlen(fmt);
896 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format4");
904 case 'f': case 'e': case 'g': case 'E': case 'G':
909 if(*(s-1) == 'l') break;
914 case 'o': case 'x': case 'X': case 'u':
915 flag = *(s-1) == 'l' ? 'd' : 'u';
924 WARNING("weird printf conversion %s", fmt);
929 FATAL("not enough args in printf(%s)", os);
935 adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format5");
937 case '?': sprintf(p, "%s", fmt); /* unknown, so dump it too */
942 adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format6");
948 case 'f': sprintf(p, fmt, getfval(x)); break;
949 case 'd': sprintf(p, fmt, (long) getfval(x)); break;
950 case 'u': sprintf(p, fmt, (int) getfval(x)); break;
956 if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format7"))
957 FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t);
963 sprintf(p, fmt, (int) getfval(x));
965 *p++ = '\0'; /* explicit null byte */
966 *p = '\0'; /* next output will start here */
969 sprintf(p, fmt, getsval(x)[0]);
972 FATAL("can't happen: bad conversion %c in format()", flag);
980 for ( ; a; a = a->nnext) /* evaluate any remaining args */
987 Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */
994 if ((buf = (char *) malloc(bufsz)) == NULL)
995 FATAL("out of memory in awksprintf");
998 if (format(&buf, &bufsz, getsval(x), y) == -1)
999 FATAL("sprintf string %.30s... too long. can't happen.", buf);
1007 Cell *awkprintf(Node **a, int n) /* printf */
1008 { /* a[0] is list of args, starting with format string */
1009 /* a[1] is redirection operator, a[2] is redirection file */
1015 int bufsz=3*recsize;
1017 if ((buf = (char *) malloc(bufsz)) == NULL)
1018 FATAL("out of memory in awkprintf");
1021 if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
1022 FATAL("printf string %.30s... too long. can't happen.", buf);
1025 /* fputs(buf, stdout); */
1026 fwrite(buf, len, 1, stdout);
1028 FATAL("write error on stdout");
1030 fp = redirect(ptoi(a[1]), a[2]);
1031 /* fputs(buf, fp); */
1032 fwrite(buf, len, 1, fp);
1035 FATAL("write error on %s", filename(fp));
1041 Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */
1050 if (n != UMINUS && n != UPLUS) {
1068 FATAL("division by zero");
1073 FATAL("division by zero in mod");
1080 case UPLUS: /* handled by getfval(), above */
1083 if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
1084 i = ipow(i, (int) j);
1086 i = errcheck(pow(i, j), "pow");
1088 default: /* can't happen */
1089 FATAL("illegal arithmetic operator %d", n);
1095 double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */
1108 Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */
1116 k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
1117 if (n == PREINCR || n == PREDECR) {
1128 Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */
1129 { /* this is subtle; don't muck with it. */
1136 if (n == ASSIGN) { /* ordinary assignment */
1137 if (x == y && !(x->tval & (FLD|REC)) && x != nfloc)
1138 ; /* self-assignment: leave alone unless it's a field or NF */
1139 else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
1140 setsval(x, getsval(y));
1141 x->fval = getfval(y);
1145 setsval(x, getsval(y));
1147 setfval(x, getfval(y));
1149 funnyvar(y, "read value of");
1167 FATAL("division by zero in /=");
1172 FATAL("division by zero in %%=");
1177 if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */
1178 xf = ipow(xf, (int) yf);
1180 xf = errcheck(pow(xf, yf), "pow");
1183 FATAL("illegal assignment operator %d", n);
1191 Cell *cat(Node **a, int q) /* a[0] cat a[1] */
1199 n1 = strlen(getsval(x));
1200 adjbuf(&s, &ssz, n1 + 1, recsize, 0, "cat1");
1201 (void) strncpy(s, x->sval, ssz);
1204 n2 = strlen(getsval(y));
1205 adjbuf(&s, &ssz, n1 + n2 + 1, recsize, 0, "cat2");
1206 (void) strncpy(s + n1, y->sval, ssz - n1);
1218 Cell *pastat(Node **a, int n) /* a[0] { a[1] } */
1234 Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */
1240 if (pairstack[pair] == 0) {
1243 pairstack[pair] = 1;
1246 if (pairstack[pair] == 1) {
1249 pairstack[pair] = 0;
1257 Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
1259 Cell *x = NULL, *y, *ap;
1261 char *fs = NULL, *origfs = NULL;
1263 char *t, temp, num[50];
1264 int n, tempstat, arg3type;
1266 y = execute(a[0]); /* source string */
1267 origs = s = strdup(getsval(y));
1268 arg3type = ptoi(a[3]);
1269 if (a[2] == NULL) /* fs string */
1271 else if (arg3type == STRING) { /* split(str,arr,"string") */
1273 origfs = fs = strdup(getsval(x));
1275 } else if (arg3type == REGEXPR)
1276 fs = "(regexpr)"; /* split(str,arr,/regexpr/) */
1278 FATAL("illegal type of split");
1280 ap = execute(a[1]); /* array name */
1282 dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs) );
1285 ap->sval = (char *) makesymtab(NSYMTAB);
1288 if (arg3type == REGEXPR && strlen((char*)((fa*)a[2])->restr) == 0) {
1289 /* split(s, a, //); have to arrange that it looks like empty sep */
1294 if (*s != '\0' && (strlen(fs) > 1 || arg3type == REGEXPR)) { /* reg expr */
1296 if (arg3type == REGEXPR) { /* it's ready already */
1299 pfa = makedfa(fs, 1);
1301 if (nematch(pfa,s)) {
1302 tempstat = pfa->initstat;
1306 sprintf(num, "%d", n);
1310 setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
1312 setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1314 s = patbeg + patlen;
1315 if (*(patbeg+patlen-1) == 0 || *s == 0) {
1317 sprintf(num, "%d", n);
1318 setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
1319 pfa->initstat = tempstat;
1322 } while (nematch(pfa,s));
1323 pfa->initstat = tempstat; /* bwk: has to be here to reset */
1324 /* cf gsub and refldbld */
1327 sprintf(num, "%d", n);
1329 setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
1331 setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1334 } else if (sep == ' ') {
1336 while (*s == ' ' || *s == '\t' || *s == '\n')
1344 while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
1347 sprintf(num, "%d", n);
1349 setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1351 setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1356 } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */
1357 for (n = 0; *s != 0; s++) {
1360 sprintf(num, "%d", n);
1363 if (isdigit((uschar)buf[0]))
1364 setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval);
1366 setsymtab(num, buf, 0.0, STR, (Array *) ap->sval);
1368 } else if (*s != 0) {
1372 while (*s != sep && *s != '\n' && *s != '\0')
1376 sprintf(num, "%d", n);
1378 setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1380 setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1390 if (a[2] != NULL && arg3type == STRING) {
1399 Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */
1414 Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */
1422 } else if (a[2] != NULL) {
1429 Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */
1443 if (isnext(x) || isexit(x) || isret(x))
1449 Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */
1457 if (isnext(x) || isexit(x) || isret(x))
1467 Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */
1476 if (!istrue(x)) return(x);
1480 if (isbreak(x)) /* turn off break */
1482 if (isnext(x) || isexit(x) || isret(x))
1490 Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */
1492 Cell *x, *vp, *arrayp, *cp, *ncp;
1497 arrayp = execute(a[1]);
1498 if (!isarr(arrayp)) {
1501 tp = (Array *) arrayp->sval;
1503 for (i = 0; i < tp->size; i++) { /* this routine knows too much */
1504 for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1505 setsval(vp, cp->nval);
1512 if (isnext(x) || isexit(x) || isret(x)) {
1522 Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */
1531 void flush_all(void);
1536 nextarg = a[1]->nnext;
1540 u = ((Array *) x->sval)->nelem; /* GROT. should be function*/
1542 u = strlen(getsval(x));
1545 u = errcheck(log(getfval(x)), "log"); break;
1547 modf(getfval(x), &u); break;
1549 u = errcheck(exp(getfval(x)), "exp"); break;
1551 u = errcheck(sqrt(getfval(x)), "sqrt"); break;
1553 u = sin(getfval(x)); break;
1555 u = cos(getfval(x)); break;
1557 if (nextarg == NULL) {
1558 WARNING("atan2 requires two arguments; returning 1.0");
1561 y = execute(a[1]->nnext);
1562 u = atan2(getfval(x), getfval(y));
1564 nextarg = nextarg->nnext;
1568 u = ~((int)getfval(x));
1571 if (nextarg == NULL) {
1572 WARNING("and requires two arguments; returning 0");
1576 i = ((int)getfval(x));
1577 while (nextarg != NULL) {
1578 y = execute(nextarg);
1579 i &= (int)getfval(y);
1581 nextarg = nextarg->nnext;
1586 if (nextarg == NULL) {
1587 WARNING("or requires two arguments; returning 0");
1591 i = ((int)getfval(x));
1592 while (nextarg != NULL) {
1593 y = execute(nextarg);
1594 i |= (int)getfval(y);
1596 nextarg = nextarg->nnext;
1601 if (nextarg == NULL) {
1602 WARNING("xor requires two arguments; returning 0");
1606 i = ((int)getfval(x));
1607 while (nextarg != NULL) {
1608 y = execute(nextarg);
1609 i ^= (int)getfval(y);
1611 nextarg = nextarg->nnext;
1616 if (nextarg == NULL) {
1617 WARNING("lshift requires two arguments; returning 0");
1621 y = execute(a[1]->nnext);
1622 u = ((int)getfval(x)) << ((int)getfval(y));
1624 nextarg = nextarg->nnext;
1627 if (nextarg == NULL) {
1628 WARNING("rshift requires two arguments; returning 0");
1632 y = execute(a[1]->nnext);
1633 u = ((int)getfval(x)) >> ((int)getfval(y));
1635 nextarg = nextarg->nnext;
1638 fflush(stdout); /* in case something is buffered already */
1639 status = system(getsval(x));
1642 if (WIFEXITED(status)) {
1643 u = WEXITSTATUS(status);
1644 } else if (WIFSIGNALED(status)) {
1645 u = WTERMSIG(status) + 256;
1647 if (WCOREDUMP(status))
1650 } else /* something else?!? */
1655 /* random() returns numbers in [0..2^31-1]
1656 * in order to get a number in [0, 1), divide it by 2^31
1658 u = (Awkfloat) random() / (0x7fffffffL + 0x1UL);
1661 if (isrec(x)) /* no argument provided */
1662 u = time((time_t *)0);
1666 srandom((unsigned long) u);
1672 buf = tostring(getsval(x));
1673 if (t == FTOUPPER) {
1674 for (p = buf; *p; p++)
1675 if (islower((uschar) *p))
1676 *p = toupper((uschar)*p);
1678 for (p = buf; *p; p++)
1679 if (isupper((uschar) *p))
1680 *p = tolower((uschar)*p);
1688 if (isrec(x) || strlen(getsval(x)) == 0) {
1689 flush_all(); /* fflush() or fflush("") -> all */
1691 } else if ((fp = openfile(FFLUSH, getsval(x))) == NULL)
1696 default: /* can't happen */
1697 FATAL("illegal function type %d", t);
1703 if (nextarg != NULL) {
1704 WARNING("warning: function has too many arguments");
1705 for ( ; nextarg; nextarg = nextarg->nnext)
1711 Cell *printstat(Node **a, int n) /* print a[0] */
1717 if (a[1] == NULL) /* a[1] is redirection operator, a[2] is file */
1720 fp = redirect(ptoi(a[1]), a[2]);
1721 for (x = a[0]; x != NULL; x = x->nnext) {
1723 fputs(getpssval(y), fp);
1725 if (x->nnext == NULL)
1726 fputs(getsval(orsloc), fp);
1728 fputs(getsval(ofsloc), fp);
1733 FATAL("write error on %s", filename(fp));
1737 Cell *nullproc(Node **a, int n)
1743 FILE *redirect(int a, Node *b) /* set up all i/o redirections */
1751 fp = openfile(a, fname);
1753 FATAL("can't open file %s", fname);
1761 int mode; /* '|', 'a', 'w' => LE/LT, GT */
1766 void stdinit(void) /* in case stdin, etc., are not constants */
1769 files = calloc(nfiles, sizeof(*files));
1771 FATAL("can't allocate file memory for %u files", nfiles);
1772 files[0].fp = stdin;
1773 files[0].fname = "/dev/stdin";
1775 files[1].fp = stdout;
1776 files[1].fname = "/dev/stdout";
1778 files[2].fp = stderr;
1779 files[2].fname = "/dev/stderr";
1783 FILE *openfile(int a, const char *us)
1790 FATAL("null file name in print or getline");
1791 for (i=0; i < nfiles; i++)
1792 if (files[i].fname && strcmp(s, files[i].fname) == 0) {
1793 if (a == files[i].mode || (a==APPEND && files[i].mode==GT))
1798 if (a == FFLUSH) /* didn't find it, so don't create it! */
1801 for (i=0; i < nfiles; i++)
1802 if (files[i].fp == NULL)
1806 int nnf = nfiles + FOPEN_MAX;
1807 nf = realloc(files, nnf * sizeof(*nf));
1809 FATAL("cannot grow files for %s and %d files", s, nnf);
1810 memset(&nf[nfiles], 0, FOPEN_MAX * sizeof(*nf));
1814 fflush(stdout); /* force a semblance of order */
1818 } else if (a == APPEND) {
1820 m = GT; /* so can mix > and >> */
1821 } else if (a == '|') { /* output pipe */
1823 } else if (a == LE) { /* input pipe */
1825 } else if (a == LT) { /* getline <file */
1826 fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */
1827 } else /* can't happen */
1828 FATAL("illegal redirection %d", a);
1830 files[i].fname = tostring(s);
1837 const char *filename(FILE *fp)
1841 for (i = 0; i < nfiles; i++)
1842 if (fp == files[i].fp)
1843 return files[i].fname;
1847 Cell *closefile(Node **a, int n)
1855 for (i = 0; i < nfiles; i++) {
1856 if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) {
1857 if (ferror(files[i].fp))
1858 WARNING( "i/o error occurred on %s", files[i].fname );
1859 if (files[i].mode == '|' || files[i].mode == LE)
1860 stat = pclose(files[i].fp);
1862 stat = fclose(files[i].fp);
1864 WARNING( "i/o error occurred closing %s", files[i].fname );
1865 if (i > 2) /* don't do /dev/std... */
1866 xfree(files[i].fname);
1867 files[i].fname = NULL; /* watch out for ref thru this */
1873 setfval(x, (Awkfloat) stat);
1881 for (i = 0; i < FOPEN_MAX; i++) {
1883 if (ferror(files[i].fp))
1884 WARNING( "i/o error occurred on %s", files[i].fname );
1885 if (files[i].mode == '|' || files[i].mode == LE)
1886 stat = pclose(files[i].fp);
1888 stat = fclose(files[i].fp);
1890 WARNING( "i/o error occurred while closing %s", files[i].fname );
1895 void flush_all(void)
1899 for (i = 0; i < nfiles; i++)
1901 fflush(files[i].fp);
1904 void backsub(char **pb_ptr, char **sptr_ptr);
1906 Cell *sub(Node **a, int nnn) /* substitute command */
1908 char *sptr, *pb, *q;
1909 Cell *x, *y, *result;
1912 int bufsz = recsize;
1914 if ((buf = (char *) malloc(bufsz)) == NULL)
1915 FATAL("out of memory in sub");
1916 x = execute(a[3]); /* target string */
1918 if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */
1919 pfa = (fa *) a[1]; /* regular expression */
1922 pfa = makedfa(getsval(y), 1);
1925 y = execute(a[2]); /* replacement string */
1927 if (pmatch(pfa, t)) {
1929 adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub");
1931 while (sptr < patbeg)
1934 while (*sptr != 0) {
1935 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub");
1936 if (*sptr == '\\') {
1937 backsub(&pb, &sptr);
1938 } else if (*sptr == '&') {
1940 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub");
1941 for (q = patbeg; q < patbeg+patlen; )
1947 if (pb > buf + bufsz)
1948 FATAL("sub result1 %.30s too big; can't happen", buf);
1949 sptr = patbeg + patlen;
1950 if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
1951 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
1952 while ((*pb++ = *sptr++) != 0)
1955 if (pb > buf + bufsz)
1956 FATAL("sub result2 %.30s too big; can't happen", buf);
1957 setsval(x, buf); /* BUG: should be able to avoid copy */
1966 Cell *gsub(Node **a, int nnn) /* global substitute */
1969 char *rptr, *sptr, *t, *pb, *q;
1972 int mflag, tempstat, num;
1973 int bufsz = recsize;
1975 if ((buf = (char *) malloc(bufsz)) == NULL)
1976 FATAL("out of memory in gsub");
1977 mflag = 0; /* if mflag == 0, can replace empty string */
1979 x = execute(a[3]); /* target string */
1981 if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */
1982 pfa = (fa *) a[1]; /* regular expression */
1985 pfa = makedfa(getsval(y), 1);
1988 y = execute(a[2]); /* replacement string */
1989 if (pmatch(pfa, t)) {
1990 tempstat = pfa->initstat;
1995 if (patlen == 0 && *patbeg != 0) { /* matched empty string */
1996 if (mflag == 0) { /* can replace empty */
1999 while (*sptr != 0) {
2000 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
2001 if (*sptr == '\\') {
2002 backsub(&pb, &sptr);
2003 } else if (*sptr == '&') {
2005 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
2006 for (q = patbeg; q < patbeg+patlen; )
2012 if (*t == 0) /* at end */
2014 adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
2016 if (pb > buf + bufsz) /* BUG: not sure of this test */
2017 FATAL("gsub result0 %.30s too big; can't happen", buf);
2020 else { /* matched nonempty string */
2023 adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub");
2024 while (sptr < patbeg)
2027 while (*sptr != 0) {
2028 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
2029 if (*sptr == '\\') {
2030 backsub(&pb, &sptr);
2031 } else if (*sptr == '&') {
2033 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
2034 for (q = patbeg; q < patbeg+patlen; )
2039 t = patbeg + patlen;
2040 if (patlen == 0 || *t == 0 || *(t-1) == 0)
2042 if (pb > buf + bufsz)
2043 FATAL("gsub result1 %.30s too big; can't happen", buf);
2046 } while (pmatch(pfa,t));
2048 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
2049 while ((*pb++ = *sptr++) != 0)
2051 done: if (pb < buf + bufsz)
2053 else if (*(pb-1) != '\0')
2054 FATAL("gsub result2 %.30s truncated; can't happen", buf);
2055 setsval(x, buf); /* BUG: should be able to avoid copy + free */
2056 pfa->initstat = tempstat;
2067 void backsub(char **pb_ptr, char **sptr_ptr) /* handle \\& variations */
2068 { /* sptr[0] == '\\' */
2069 char *pb = *pb_ptr, *sptr = *sptr_ptr;
2071 if (sptr[1] == '\\') {
2072 if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
2076 } else if (sptr[2] == '&') { /* \\& -> \ + matched */
2079 } else { /* \\x -> \\x */
2083 } else if (sptr[1] == '&') { /* literal & */
2086 } else /* literal \ */