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 */
1270 fs = getsval(fsloc);
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);
1396 Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */
1411 Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */
1419 } else if (a[2] != NULL) {
1426 Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */
1440 if (isnext(x) || isexit(x) || isret(x))
1446 Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */
1454 if (isnext(x) || isexit(x) || isret(x))
1464 Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */
1473 if (!istrue(x)) return(x);
1477 if (isbreak(x)) /* turn off break */
1479 if (isnext(x) || isexit(x) || isret(x))
1487 Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */
1489 Cell *x, *vp, *arrayp, *cp, *ncp;
1494 arrayp = execute(a[1]);
1495 if (!isarr(arrayp)) {
1498 tp = (Array *) arrayp->sval;
1500 for (i = 0; i < tp->size; i++) { /* this routine knows too much */
1501 for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1502 setsval(vp, cp->nval);
1509 if (isnext(x) || isexit(x) || isret(x)) {
1519 Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */
1528 void flush_all(void);
1533 nextarg = a[1]->nnext;
1537 u = ((Array *) x->sval)->nelem; /* GROT. should be function*/
1539 u = strlen(getsval(x));
1542 u = errcheck(log(getfval(x)), "log"); break;
1544 modf(getfval(x), &u); break;
1546 u = errcheck(exp(getfval(x)), "exp"); break;
1548 u = errcheck(sqrt(getfval(x)), "sqrt"); break;
1550 u = sin(getfval(x)); break;
1552 u = cos(getfval(x)); break;
1554 if (nextarg == NULL) {
1555 WARNING("atan2 requires two arguments; returning 1.0");
1558 y = execute(a[1]->nnext);
1559 u = atan2(getfval(x), getfval(y));
1561 nextarg = nextarg->nnext;
1565 u = ~((int)getfval(x));
1568 if (nextarg == NULL) {
1569 WARNING("and requires two arguments; returning 0");
1573 i = ((int)getfval(x));
1574 while (nextarg != NULL) {
1575 y = execute(nextarg);
1576 i &= (int)getfval(y);
1578 nextarg = nextarg->nnext;
1583 if (nextarg == NULL) {
1584 WARNING("or requires two arguments; returning 0");
1588 i = ((int)getfval(x));
1589 while (nextarg != NULL) {
1590 y = execute(nextarg);
1591 i |= (int)getfval(y);
1593 nextarg = nextarg->nnext;
1598 if (nextarg == NULL) {
1599 WARNING("xor requires two arguments; returning 0");
1603 i = ((int)getfval(x));
1604 while (nextarg != NULL) {
1605 y = execute(nextarg);
1606 i ^= (int)getfval(y);
1608 nextarg = nextarg->nnext;
1613 if (nextarg == NULL) {
1614 WARNING("lshift requires two arguments; returning 0");
1618 y = execute(a[1]->nnext);
1619 u = ((int)getfval(x)) << ((int)getfval(y));
1621 nextarg = nextarg->nnext;
1624 if (nextarg == NULL) {
1625 WARNING("rshift requires two arguments; returning 0");
1629 y = execute(a[1]->nnext);
1630 u = ((int)getfval(x)) >> ((int)getfval(y));
1632 nextarg = nextarg->nnext;
1635 fflush(stdout); /* in case something is buffered already */
1636 status = system(getsval(x));
1639 if (WIFEXITED(status)) {
1640 u = WEXITSTATUS(status);
1641 } else if (WIFSIGNALED(status)) {
1642 u = WTERMSIG(status) + 256;
1644 if (WCOREDUMP(status))
1647 } else /* something else?!? */
1652 /* random() returns numbers in [0..2^31-1]
1653 * in order to get a number in [0, 1), divide it by 2^31
1655 u = (Awkfloat) random() / (0x7fffffffL + 0x1UL);
1658 if (isrec(x)) /* no argument provided */
1659 u = time((time_t *)0);
1663 srandom((unsigned long) u);
1669 buf = tostring(getsval(x));
1670 if (t == FTOUPPER) {
1671 for (p = buf; *p; p++)
1672 if (islower((uschar) *p))
1673 *p = toupper((uschar)*p);
1675 for (p = buf; *p; p++)
1676 if (isupper((uschar) *p))
1677 *p = tolower((uschar)*p);
1685 if (isrec(x) || strlen(getsval(x)) == 0) {
1686 flush_all(); /* fflush() or fflush("") -> all */
1688 } else if ((fp = openfile(FFLUSH, getsval(x))) == NULL)
1693 default: /* can't happen */
1694 FATAL("illegal function type %d", t);
1700 if (nextarg != NULL) {
1701 WARNING("warning: function has too many arguments");
1702 for ( ; nextarg; nextarg = nextarg->nnext)
1708 Cell *printstat(Node **a, int n) /* print a[0] */
1714 if (a[1] == NULL) /* a[1] is redirection operator, a[2] is file */
1717 fp = redirect(ptoi(a[1]), a[2]);
1718 for (x = a[0]; x != NULL; x = x->nnext) {
1720 fputs(getpssval(y), fp);
1722 if (x->nnext == NULL)
1723 fputs(getsval(orsloc), fp);
1725 fputs(getsval(ofsloc), fp);
1730 FATAL("write error on %s", filename(fp));
1734 Cell *nullproc(Node **a, int n)
1740 FILE *redirect(int a, Node *b) /* set up all i/o redirections */
1748 fp = openfile(a, fname);
1750 FATAL("can't open file %s", fname);
1758 int mode; /* '|', 'a', 'w' => LE/LT, GT */
1763 void stdinit(void) /* in case stdin, etc., are not constants */
1766 files = calloc(nfiles, sizeof(*files));
1768 FATAL("can't allocate file memory for %u files", nfiles);
1769 files[0].fp = stdin;
1770 files[0].fname = "/dev/stdin";
1772 files[1].fp = stdout;
1773 files[1].fname = "/dev/stdout";
1775 files[2].fp = stderr;
1776 files[2].fname = "/dev/stderr";
1780 FILE *openfile(int a, const char *us)
1787 FATAL("null file name in print or getline");
1788 for (i=0; i < nfiles; i++)
1789 if (files[i].fname && strcmp(s, files[i].fname) == 0) {
1790 if (a == files[i].mode || (a==APPEND && files[i].mode==GT))
1795 if (a == FFLUSH) /* didn't find it, so don't create it! */
1798 for (i=0; i < nfiles; i++)
1799 if (files[i].fp == NULL)
1803 int nnf = nfiles + FOPEN_MAX;
1804 nf = realloc(files, nnf * sizeof(*nf));
1806 FATAL("cannot grow files for %s and %d files", s, nnf);
1807 memset(&nf[nfiles], 0, FOPEN_MAX * sizeof(*nf));
1811 fflush(stdout); /* force a semblance of order */
1815 } else if (a == APPEND) {
1817 m = GT; /* so can mix > and >> */
1818 } else if (a == '|') { /* output pipe */
1820 } else if (a == LE) { /* input pipe */
1822 } else if (a == LT) { /* getline <file */
1823 fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */
1824 } else /* can't happen */
1825 FATAL("illegal redirection %d", a);
1827 files[i].fname = tostring(s);
1834 const char *filename(FILE *fp)
1838 for (i = 0; i < nfiles; i++)
1839 if (fp == files[i].fp)
1840 return files[i].fname;
1844 Cell *closefile(Node **a, int n)
1852 for (i = 0; i < nfiles; i++) {
1853 if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) {
1854 if (ferror(files[i].fp))
1855 WARNING( "i/o error occurred on %s", files[i].fname );
1856 if (files[i].mode == '|' || files[i].mode == LE)
1857 stat = pclose(files[i].fp);
1859 stat = fclose(files[i].fp);
1861 WARNING( "i/o error occurred closing %s", files[i].fname );
1862 if (i > 2) /* don't do /dev/std... */
1863 xfree(files[i].fname);
1864 files[i].fname = NULL; /* watch out for ref thru this */
1870 setfval(x, (Awkfloat) stat);
1878 for (i = 0; i < FOPEN_MAX; i++) {
1880 if (ferror(files[i].fp))
1881 WARNING( "i/o error occurred on %s", files[i].fname );
1882 if (files[i].mode == '|' || files[i].mode == LE)
1883 stat = pclose(files[i].fp);
1885 stat = fclose(files[i].fp);
1887 WARNING( "i/o error occurred while closing %s", files[i].fname );
1892 void flush_all(void)
1896 for (i = 0; i < nfiles; i++)
1898 fflush(files[i].fp);
1901 void backsub(char **pb_ptr, char **sptr_ptr);
1903 Cell *sub(Node **a, int nnn) /* substitute command */
1905 char *sptr, *pb, *q;
1906 Cell *x, *y, *result;
1909 int bufsz = recsize;
1911 if ((buf = (char *) malloc(bufsz)) == NULL)
1912 FATAL("out of memory in sub");
1913 x = execute(a[3]); /* target string */
1915 if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */
1916 pfa = (fa *) a[1]; /* regular expression */
1919 pfa = makedfa(getsval(y), 1);
1922 y = execute(a[2]); /* replacement string */
1924 if (pmatch(pfa, t)) {
1926 adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub");
1928 while (sptr < patbeg)
1931 while (*sptr != 0) {
1932 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub");
1933 if (*sptr == '\\') {
1934 backsub(&pb, &sptr);
1935 } else if (*sptr == '&') {
1937 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub");
1938 for (q = patbeg; q < patbeg+patlen; )
1944 if (pb > buf + bufsz)
1945 FATAL("sub result1 %.30s too big; can't happen", buf);
1946 sptr = patbeg + patlen;
1947 if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
1948 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
1949 while ((*pb++ = *sptr++) != 0)
1952 if (pb > buf + bufsz)
1953 FATAL("sub result2 %.30s too big; can't happen", buf);
1954 setsval(x, buf); /* BUG: should be able to avoid copy */
1963 Cell *gsub(Node **a, int nnn) /* global substitute */
1966 char *rptr, *sptr, *t, *pb, *q;
1969 int mflag, tempstat, num;
1970 int bufsz = recsize;
1972 if ((buf = (char *) malloc(bufsz)) == NULL)
1973 FATAL("out of memory in gsub");
1974 mflag = 0; /* if mflag == 0, can replace empty string */
1976 x = execute(a[3]); /* target string */
1978 if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */
1979 pfa = (fa *) a[1]; /* regular expression */
1982 pfa = makedfa(getsval(y), 1);
1985 y = execute(a[2]); /* replacement string */
1986 if (pmatch(pfa, t)) {
1987 tempstat = pfa->initstat;
1992 if (patlen == 0 && *patbeg != 0) { /* matched empty string */
1993 if (mflag == 0) { /* can replace empty */
1996 while (*sptr != 0) {
1997 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1998 if (*sptr == '\\') {
1999 backsub(&pb, &sptr);
2000 } else if (*sptr == '&') {
2002 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
2003 for (q = patbeg; q < patbeg+patlen; )
2009 if (*t == 0) /* at end */
2011 adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
2013 if (pb > buf + bufsz) /* BUG: not sure of this test */
2014 FATAL("gsub result0 %.30s too big; can't happen", buf);
2017 else { /* matched nonempty string */
2020 adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub");
2021 while (sptr < patbeg)
2024 while (*sptr != 0) {
2025 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
2026 if (*sptr == '\\') {
2027 backsub(&pb, &sptr);
2028 } else if (*sptr == '&') {
2030 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
2031 for (q = patbeg; q < patbeg+patlen; )
2036 t = patbeg + patlen;
2037 if (patlen == 0 || *t == 0 || *(t-1) == 0)
2039 if (pb > buf + bufsz)
2040 FATAL("gsub result1 %.30s too big; can't happen", buf);
2043 } while (pmatch(pfa,t));
2045 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
2046 while ((*pb++ = *sptr++) != 0)
2048 done: if (pb < buf + bufsz)
2050 else if (*(pb-1) != '\0')
2051 FATAL("gsub result2 %.30s truncated; can't happen", buf);
2052 setsval(x, buf); /* BUG: should be able to avoid copy + free */
2053 pfa->initstat = tempstat;
2064 void backsub(char **pb_ptr, char **sptr_ptr) /* handle \\& variations */
2065 { /* sptr[0] == '\\' */
2066 char *pb = *pb_ptr, *sptr = *sptr_ptr;
2068 if (sptr[1] == '\\') {
2069 if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
2073 } else if (sptr[2] == '&') { /* \\& -> \ + matched */
2076 } else { /* \\x -> \\x */
2080 } else if (sptr[1] == '&') { /* literal & */
2083 } else /* literal \ */