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$");
40 #define tempfree(x) if (istemp(x)) tfree(x); else
45 void tempfree(Cell *p) {
46 if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) {
47 WARNING("bad csub %d in Cell %d %s",
48 p->csub, p->ctype, p->sval);
55 /* do we really need these? */
57 /* #ifndef FOPEN_MAX */
58 /* #define FOPEN_MAX _NFILE */
62 /* #ifndef FOPEN_MAX */
63 /* #define FOPEN_MAX 40 */ /* max number of open files */
66 /* #ifndef RAND_MAX */
67 /* #define RAND_MAX 32767 */ /* all that ansi guarantees */
71 extern int pairstack[];
72 extern Awkfloat srand_seed;
74 Node *winner = NULL; /* root of parse tree */
75 Cell *tmps; /* free temporary cells for execution */
77 static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM };
78 Cell *True = &truecell;
79 static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM };
80 Cell *False = &falsecell;
81 static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM };
82 Cell *jbreak = &breakcell;
83 static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM };
84 Cell *jcont = &contcell;
85 static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM };
86 Cell *jnext = &nextcell;
87 static Cell nextfilecell ={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM };
88 Cell *jnextfile = &nextfilecell;
89 static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM };
90 Cell *jexit = &exitcell;
91 static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM };
92 Cell *jret = &retcell;
93 static Cell tempcell ={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE };
95 Node *curnode = NULL; /* the node being executed, for debugging */
97 /* buffer memory management */
98 int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,
100 /* pbuf: address of pointer to buffer being managed
101 * psiz: address of buffer size variable
102 * minlen: minimum length of buffer needed
103 * quantum: buffer size quantum
104 * pbptr: address of movable pointer into buffer, or 0 if none
105 * whatrtn: name of the calling routine if failure should cause fatal error
107 * return 0 for realloc failure, !=0 for success
110 if (minlen > *psiz) {
112 int rminlen = quantum ? minlen % quantum : 0;
113 int boff = pbptr ? *pbptr - *pbuf : 0;
114 /* round up to next multiple of quantum */
116 minlen += quantum - rminlen;
117 tbuf = (char *) realloc(*pbuf, minlen);
118 dprintf( ("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, *pbuf, tbuf) );
121 FATAL("out of memory in %s", whatrtn);
127 *pbptr = tbuf + boff;
132 void run(Node *a) /* execution of parse tree starts here */
134 extern void stdinit(void);
141 Cell *execute(Node *u) /* execute a node of the parse tree */
143 Cell *(*proc)(Node **, int);
149 for (a = u; ; a = a->nnext) {
152 x = (Cell *) (a->narg[0]);
153 if (isfld(x) && !donefld)
155 else if (isrec(x) && !donerec)
159 if (notlegal(a->nobj)) /* probably a Cell* but too risky to print */
160 FATAL("illegal statement");
161 proc = proctab[a->nobj-FIRSTTOKEN];
162 x = (*proc)(a->narg, a->nobj);
163 if (isfld(x) && !donefld)
165 else if (isrec(x) && !donerec)
171 if (a->nnext == NULL)
178 Cell *program(Node **a, int n) /* execute an awk program */
179 { /* a[0] = BEGIN, a[1] = body, a[2] = END */
182 if (setjmp(env) != 0)
184 if (a[0]) { /* BEGIN */
189 FATAL("illegal break, continue, next or nextfile from BEGIN");
193 while (getrec(&record, &recsize, 1) > 0) {
200 if (setjmp(env) != 0) /* handles exit within END */
202 if (a[2]) { /* END */
204 if (isbreak(x) || isnext(x) || iscont(x))
205 FATAL("illegal break, continue, next or nextfile from END");
212 struct Frame { /* stack frame for awk function calls */
213 int nargs; /* number of arguments in this call */
214 Cell *fcncell; /* pointer to Cell for function */
215 Cell **args; /* pointer to array of arguments after execute */
216 Cell *retval; /* return value */
219 #define NARGS 50 /* max args in a call */
221 struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */
222 int nframe = 0; /* number of frames allocated */
223 struct Frame *fp = NULL; /* frame pointer. bottom level unused */
225 Cell *call(Node **a, int n) /* function call. very kludgy and fragile */
227 static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE };
229 int freed = 0; /* handles potential double freeing when fcn & param share a tempcell */
231 Cell *args[NARGS], *oargs[NARGS]; /* BUG: fixed size arrays */
235 fcn = execute(a[0]); /* the function itself */
238 FATAL("calling undefined function %s", s);
240 fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
242 FATAL("out of space for stack frames calling %s", s);
244 for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */
246 ndef = (int) fcn->fval; /* args in defn */
247 dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) );
249 WARNING("function %s called with %d args, uses only %d",
251 if (ncall + ndef > NARGS)
252 FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS);
253 for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) { /* get call args */
254 dprintf( ("evaluate args[%d], fp=%d:\n", i, (int) (fp-frame)) );
257 dprintf( ("args[%d]: %s %f <%s>, t=%o\n",
258 i, NN(y->nval), y->fval, isarr(y) ? "(array)" : NN(y->sval), y->tval) );
260 FATAL("can't use function %s as argument in %s", y->nval, s);
262 args[i] = y; /* arrays by ref */
264 args[i] = copycell(y);
267 for ( ; i < ndef; i++) { /* add null args for ones not provided */
269 *args[i] = newcopycell;
271 fp++; /* now ok to up frame */
272 if (fp >= frame + nframe) {
273 int dfp = fp - frame; /* old index */
274 frame = (struct Frame *)
275 realloc((char *) frame, (nframe += 100) * sizeof(struct Frame));
277 FATAL("out of space for stack frames in %s", s);
282 fp->nargs = ndef; /* number defined with (excess are locals) */
283 fp->retval = gettemp();
285 dprintf( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) );
286 y = execute((Node *)(fcn->sval)); /* execute body */
287 dprintf( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) );
289 for (i = 0; i < ndef; i++) {
290 Cell *t = fp->args[i];
292 if (t->csub == CCOPY) {
298 oargs[i]->tval = t->tval;
299 oargs[i]->tval &= ~(STR|NUM|DONTFREE);
300 oargs[i]->sval = t->sval;
304 } else if (t != y) { /* kludge to prevent freeing twice */
307 } else if (t == y && t->csub == CCOPY) {
314 if (isexit(y) || isnext(y))
317 tempfree(y); /* don't free twice! */
319 z = fp->retval; /* return value */
320 dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );
325 Cell *copycell(Cell *x) /* make a copy of a cell in a temp */
330 y->csub = CCOPY; /* prevents freeing until call is over */
331 y->nval = x->nval; /* BUG? */
333 y->sval = tostring(x->sval);
335 y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */
336 /* is DONTFREE right? */
340 Cell *arg(Node **a, int n) /* nth argument of a function */
343 n = ptoi(a[0]); /* argument number, counting from 0 */
344 dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );
346 FATAL("argument #%d of function %s was not supplied",
347 n+1, fp->fcncell->nval);
351 Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */
359 errorflag = (int) getfval(y);
366 if ((y->tval & (STR|NUM)) == (STR|NUM)) {
367 setsval(fp->retval, getsval(y));
368 fp->retval->fval = getfval(y);
369 fp->retval->tval |= NUM;
371 else if (y->tval & STR)
372 setsval(fp->retval, getsval(y));
373 else if (y->tval & NUM)
374 setfval(fp->retval, getfval(y));
375 else /* can't happen */
376 FATAL("bad type variable %d", y->tval);
389 default: /* can't happen */
390 FATAL("illegal jump type %d", n);
392 return 0; /* not reached */
395 Cell *awkgetline(Node **a, int n) /* get next line from specific input */
396 { /* a[0] is variable, a[1] is operator, a[2] is filename */
398 extern Cell **fldtab;
401 int bufsize = recsize;
404 if ((buf = (char *) malloc(bufsize)) == NULL)
405 FATAL("out of memory in getline");
407 fflush(stdout); /* in case someone is waiting for a prompt */
409 if (a[1] != NULL) { /* getline < file */
410 x = execute(a[2]); /* filename */
412 if (mode == '|') /* input pipe */
413 mode = LE; /* arbitrary flag */
414 fp = openfile(mode, getsval(x));
419 n = readrec(&buf, &bufsize, fp);
422 } else if (a[0] != NULL) { /* getline var <file */
426 } else { /* getline <file */
427 setsval(fldtab[0], buf);
428 if (is_number(fldtab[0]->sval)) {
429 fldtab[0]->fval = atof(fldtab[0]->sval);
430 fldtab[0]->tval |= NUM;
433 } else { /* bare getline; use current input */
434 if (a[0] == NULL) /* getline */
435 n = getrec(&record, &recsize, 1);
436 else { /* getline var */
437 n = getrec(&buf, &bufsize, 0);
443 setfval(r, (Awkfloat) n);
448 Cell *getnf(Node **a, int n) /* get NF */
452 return (Cell *) a[0];
455 Cell *array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
462 int nsub = strlen(*SUBSEP);
464 if ((buf = (char *) malloc(bufsz)) == NULL)
465 FATAL("out of memory in array");
467 x = execute(a[0]); /* Cell* for symbol table */
469 for (np = a[1]; np; np = np->nnext) {
470 y = execute(np); /* subscript */
472 if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "array"))
473 FATAL("out of memory for %s[%s...]", x->nval, buf);
476 strcat(buf, *SUBSEP);
480 dprintf( ("making %s into an array\n", NN(x->nval)) );
483 x->tval &= ~(STR|NUM|DONTFREE);
485 x->sval = (char *) makesymtab(NSYMTAB);
487 z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
495 Cell *awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
500 int nsub = strlen(*SUBSEP);
502 x = execute(a[0]); /* Cell* for symbol table */
505 if (a[1] == NULL) { /* delete the elements, not the table */
509 x->sval = (char *) makesymtab(NSYMTAB);
513 if ((buf = (char *) malloc(bufsz)) == NULL)
514 FATAL("out of memory in adelete");
516 for (np = a[1]; np; np = np->nnext) {
517 y = execute(np); /* subscript */
519 if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "awkdelete"))
520 FATAL("out of memory deleting %s[%s...]", x->nval, buf);
523 strcat(buf, *SUBSEP);
533 Cell *intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
540 int nsub = strlen(*SUBSEP);
542 ap = execute(a[1]); /* array name */
544 dprintf( ("making %s into an array\n", ap->nval) );
547 ap->tval &= ~(STR|NUM|DONTFREE);
549 ap->sval = (char *) makesymtab(NSYMTAB);
551 if ((buf = (char *) malloc(bufsz)) == NULL) {
552 FATAL("out of memory in intest");
555 for (p = a[0]; p; p = p->nnext) {
556 x = execute(p); /* expr */
558 if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "intest"))
559 FATAL("out of memory deleting %s[%s...]", x->nval, buf);
563 strcat(buf, *SUBSEP);
565 k = lookup(buf, (Array *) ap->sval);
575 Cell *matchop(Node **a, int n) /* ~ and match() */
581 int (*mf)(fa *, const char *) = match, mode = 0;
587 x = execute(a[1]); /* a[1] = target text */
589 if (a[0] == NULL) /* a[1] == 0: already-compiled reg expr */
590 i = (*mf)((fa *) a[2], s);
592 y = execute(a[2]); /* a[2] = regular expr */
594 pfa = makedfa(t, mode);
600 int start = patbeg - s + 1;
603 setfval(rstartloc, (Awkfloat) start);
604 setfval(rlengthloc, (Awkfloat) patlen);
609 } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
616 Cell *boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */
633 if ( !i ) return(False);
640 if (i) return(False);
642 default: /* can't happen */
643 FATAL("unknown boolean operator %d", n);
645 return 0; /*NOTREACHED*/
648 Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */
656 if (x->tval&NUM && y->tval&NUM) {
657 j = x->fval - y->fval;
658 i = j<0? -1: (j>0? 1: 0);
660 i = strcoll(getsval(x), getsval(y));
665 case LT: if (i<0) return(True);
667 case LE: if (i<=0) return(True);
669 case NE: if (i!=0) return(True);
671 case EQ: if (i == 0) return(True);
673 case GE: if (i>=0) return(True);
675 case GT: if (i>0) return(True);
677 default: /* can't happen */
678 FATAL("unknown relational operator %d", n);
680 return 0; /*NOTREACHED*/
683 void tfree(Cell *a) /* free a tempcell */
686 dprintf( ("freeing %s %s %o\n", NN(a->nval), NN(a->sval), a->tval) );
690 FATAL("tempcell list is curdled");
695 Cell *gettemp(void) /* get a tempcell */
700 tmps = (Cell *) calloc(100, sizeof(Cell));
702 FATAL("out of space for temporaries");
703 for(i = 1; i < 100; i++)
704 tmps[i-1].cnext = &tmps[i];
705 tmps[i-1].cnext = NULL;
713 Cell *indirect(Node **a, int n) /* $( a[0] ) */
721 val = getfval(x); /* freebsd: defend against super large field numbers */
722 if ((Awkfloat)INT_MAX < val)
723 FATAL("trying to access out of range field %s", x->nval);
725 if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */
726 FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
727 /* BUG: can x->nval ever be null??? */
730 x->ctype = OCELL; /* BUG? why are these needed? */
735 Cell *substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */
740 Cell *x, *y, *z = NULL;
758 m = (int) getfval(y);
765 n = (int) getfval(z);
773 dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) );
775 temp = s[n+m-1]; /* with thanks to John Linderman */
777 setsval(y, s + m - 1);
783 Cell *sindex(Node **a, int nnn) /* index(a[0], a[1]) */
786 char *s1, *s2, *p1, *p2, *q;
795 for (p1 = s1; *p1 != '\0'; p1++) {
796 for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
799 v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */
809 #define MAXNUMSIZE 50
811 int format(char **pbuf, int *pbufsize, const char *s, Node *a) /* printf-like conversions */
818 int fmtwd; /* format width */
821 int bufsize = *pbufsize;
825 if ((fmt = (char *) malloc(fmtsz)) == NULL)
826 FATAL("out of memory in format()");
828 adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format1");
838 /* have to be real careful in case this is a huge number, eg, %100000d */
842 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format2");
843 for (t = fmt; (*t++ = *s) != '\0'; s++) {
844 if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3"))
845 FATAL("format item %.30s... ran format() out of memory", os);
846 if (isalpha((uschar)*s) && *s != 'l' && *s != 'h' && *s != 'L')
847 break; /* the ansi panoply */
851 sprintf(t-1, "%d", fmtwd=(int) getfval(x));
854 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
855 t = fmt + strlen(fmt);
862 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format4");
865 case 'f': case 'e': case 'g': case 'E': case 'G':
870 if(*(s-1) == 'l') break;
875 case 'o': case 'x': case 'X': case 'u':
876 flag = *(s-1) == 'l' ? 'd' : 'u';
885 WARNING("weird printf conversion %s", fmt);
890 FATAL("not enough args in printf(%s)", os);
896 adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format5");
898 case '?': sprintf(p, "%s", fmt); /* unknown, so dump it too */
903 adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format6");
907 case 'f': sprintf(p, fmt, getfval(x)); break;
908 case 'd': sprintf(p, fmt, (long) getfval(x)); break;
909 case 'u': sprintf(p, fmt, (int) getfval(x)); break;
915 if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format7"))
916 FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t);
922 sprintf(p, fmt, (int) getfval(x));
924 *p++ = '\0'; /* explicit null byte */
925 *p = '\0'; /* next output will start here */
928 sprintf(p, fmt, getsval(x)[0]);
931 FATAL("can't happen: bad conversion %c in format()", flag);
939 for ( ; a; a = a->nnext) /* evaluate any remaining args */
946 Cell *awksprintf(Node **a, int n) /* sprintf(a[0]) */
953 if ((buf = (char *) malloc(bufsz)) == NULL)
954 FATAL("out of memory in awksprintf");
957 if (format(&buf, &bufsz, getsval(x), y) == -1)
958 FATAL("sprintf string %.30s... too long. can't happen.", buf);
966 Cell *awkprintf(Node **a, int n) /* printf */
967 { /* a[0] is list of args, starting with format string */
968 /* a[1] is redirection operator, a[2] is redirection file */
976 if ((buf = (char *) malloc(bufsz)) == NULL)
977 FATAL("out of memory in awkprintf");
980 if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
981 FATAL("printf string %.30s... too long. can't happen.", buf);
984 /* fputs(buf, stdout); */
985 fwrite(buf, len, 1, stdout);
987 FATAL("write error on stdout");
989 fp = redirect(ptoi(a[1]), a[2]);
990 /* fputs(buf, fp); */
991 fwrite(buf, len, 1, fp);
994 FATAL("write error on %s", filename(fp));
1000 Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */
1027 FATAL("division by zero");
1032 FATAL("division by zero in mod");
1040 if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
1041 i = ipow(i, (int) j);
1043 i = errcheck(pow(i, j), "pow");
1045 default: /* can't happen */
1046 FATAL("illegal arithmetic operator %d", n);
1052 double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */
1065 Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */
1073 k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
1074 if (n == PREINCR || n == PREDECR) {
1085 Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */
1086 { /* this is subtle; don't muck with it. */
1093 if (n == ASSIGN) { /* ordinary assignment */
1094 if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: */
1095 ; /* leave alone unless it's a field */
1096 else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
1097 setsval(x, getsval(y));
1098 x->fval = getfval(y);
1102 setsval(x, getsval(y));
1104 setfval(x, getfval(y));
1106 funnyvar(y, "read value of");
1124 FATAL("division by zero in /=");
1129 FATAL("division by zero in %%=");
1134 if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */
1135 xf = ipow(xf, (int) yf);
1137 xf = errcheck(pow(xf, yf), "pow");
1140 FATAL("illegal assignment operator %d", n);
1148 Cell *cat(Node **a, int q) /* a[0] cat a[1] */
1158 n1 = strlen(x->sval);
1159 n2 = strlen(y->sval);
1160 s = (char *) malloc(n1 + n2 + 1);
1162 FATAL("out of space concatenating %.15s... and %.15s...",
1165 strcpy(s+n1, y->sval);
1174 Cell *pastat(Node **a, int n) /* a[0] { a[1] } */
1190 Cell *dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */
1196 if (pairstack[pair] == 0) {
1199 pairstack[pair] = 1;
1202 if (pairstack[pair] == 1) {
1205 pairstack[pair] = 0;
1213 Cell *split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
1215 Cell *x = NULL, *y, *ap;
1218 char *t, temp, num[50], *fs = NULL;
1219 int n, tempstat, arg3type;
1221 y = execute(a[0]); /* source string */
1222 origs = s = strdup(getsval(y));
1223 arg3type = ptoi(a[3]);
1224 if (a[2] == NULL) /* fs string */
1226 else if (arg3type == STRING) { /* split(str,arr,"string") */
1229 } else if (arg3type == REGEXPR)
1230 fs = "(regexpr)"; /* split(str,arr,/regexpr/) */
1232 FATAL("illegal type of split");
1234 ap = execute(a[1]); /* array name */
1236 dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs) );
1239 ap->sval = (char *) makesymtab(NSYMTAB);
1242 if (arg3type == REGEXPR && strlen((char*)((fa*)a[2])->restr) == 0) {
1243 /* split(s, a, //); have to arrange that it looks like empty sep */
1248 if (*s != '\0' && (strlen(fs) > 1 || arg3type == REGEXPR)) { /* reg expr */
1250 if (arg3type == REGEXPR) { /* it's ready already */
1253 pfa = makedfa(fs, 1);
1255 if (nematch(pfa,s)) {
1256 tempstat = pfa->initstat;
1260 sprintf(num, "%d", n);
1264 setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
1266 setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1268 s = patbeg + patlen;
1269 if (*(patbeg+patlen-1) == 0 || *s == 0) {
1271 sprintf(num, "%d", n);
1272 setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
1273 pfa->initstat = tempstat;
1276 } while (nematch(pfa,s));
1277 pfa->initstat = tempstat; /* bwk: has to be here to reset */
1278 /* cf gsub and refldbld */
1281 sprintf(num, "%d", n);
1283 setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
1285 setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1288 } else if (sep == ' ') {
1290 while (*s == ' ' || *s == '\t' || *s == '\n')
1298 while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
1301 sprintf(num, "%d", n);
1303 setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1305 setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1310 } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */
1311 for (n = 0; *s != 0; s++) {
1314 sprintf(num, "%d", n);
1317 if (isdigit((uschar)buf[0]))
1318 setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval);
1320 setsymtab(num, buf, 0.0, STR, (Array *) ap->sval);
1322 } else if (*s != 0) {
1326 while (*s != sep && *s != '\n' && *s != '\0')
1330 sprintf(num, "%d", n);
1332 setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1334 setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1343 if (a[2] != NULL && arg3type == STRING) {
1352 Cell *condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */
1367 Cell *ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */
1375 } else if (a[2] != NULL) {
1382 Cell *whilestat(Node **a, int n) /* while (a[0]) a[1] */
1396 if (isnext(x) || isexit(x) || isret(x))
1402 Cell *dostat(Node **a, int n) /* do a[0]; while(a[1]) */
1410 if (isnext(x) || isexit(x) || isret(x))
1420 Cell *forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */
1429 if (!istrue(x)) return(x);
1433 if (isbreak(x)) /* turn off break */
1435 if (isnext(x) || isexit(x) || isret(x))
1443 Cell *instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */
1445 Cell *x, *vp, *arrayp, *cp, *ncp;
1450 arrayp = execute(a[1]);
1451 if (!isarr(arrayp)) {
1454 tp = (Array *) arrayp->sval;
1456 for (i = 0; i < tp->size; i++) { /* this routine knows too much */
1457 for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1458 setsval(vp, cp->nval);
1465 if (isnext(x) || isexit(x) || isret(x)) {
1475 Cell *bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */
1484 void flush_all(void);
1488 nextarg = a[1]->nnext;
1492 u = ((Array *) x->sval)->nelem; /* GROT. should be function*/
1494 u = strlen(getsval(x));
1497 u = errcheck(log(getfval(x)), "log"); break;
1499 modf(getfval(x), &u); break;
1501 u = errcheck(exp(getfval(x)), "exp"); break;
1503 u = errcheck(sqrt(getfval(x)), "sqrt"); break;
1505 u = sin(getfval(x)); break;
1507 u = cos(getfval(x)); break;
1509 if (nextarg == NULL) {
1510 WARNING("atan2 requires two arguments; returning 1.0");
1513 y = execute(a[1]->nnext);
1514 u = atan2(getfval(x), getfval(y));
1516 nextarg = nextarg->nnext;
1520 u = ~((int)getfval(x));
1523 if (nextarg == NULL) {
1524 WARNING("and requires two arguments; returning 0");
1528 i = ((int)getfval(x));
1529 while (nextarg != NULL) {
1530 y = execute(nextarg);
1531 i &= (int)getfval(y);
1533 nextarg = nextarg->nnext;
1538 if (nextarg == NULL) {
1539 WARNING("or requires two arguments; returning 0");
1543 i = ((int)getfval(x));
1544 while (nextarg != NULL) {
1545 y = execute(nextarg);
1546 i |= (int)getfval(y);
1548 nextarg = nextarg->nnext;
1553 if (nextarg == NULL) {
1554 WARNING("xor requires two arguments; returning 0");
1558 i = ((int)getfval(x));
1559 while (nextarg != NULL) {
1560 y = execute(nextarg);
1561 i ^= (int)getfval(y);
1563 nextarg = nextarg->nnext;
1568 if (nextarg == NULL) {
1569 WARNING("lshift requires two arguments; returning 0");
1573 y = execute(a[1]->nnext);
1574 u = ((int)getfval(x)) << ((int)getfval(y));
1576 nextarg = nextarg->nnext;
1579 if (nextarg == NULL) {
1580 WARNING("rshift requires two arguments; returning 0");
1584 y = execute(a[1]->nnext);
1585 u = ((int)getfval(x)) >> ((int)getfval(y));
1587 nextarg = nextarg->nnext;
1590 fflush(stdout); /* in case something is buffered already */
1591 u = (Awkfloat) system(getsval(x)) / 256; /* 256 is unix-dep */
1594 /* random() returns numbers in [0..2^31-1]
1595 * in order to get a number in [0, 1), divide it by 2^31
1597 u = (Awkfloat) random() / (0x7fffffffL + 0x1UL);
1600 if (isrec(x)) /* no argument provided */
1601 u = time((time_t *)0);
1605 srandom((unsigned long) u);
1611 buf = tostring(getsval(x));
1612 if (t == FTOUPPER) {
1613 for (p = buf; *p; p++)
1614 if (islower((uschar) *p))
1615 *p = toupper((uschar)*p);
1617 for (p = buf; *p; p++)
1618 if (isupper((uschar) *p))
1619 *p = tolower((uschar)*p);
1627 if (isrec(x) || strlen(getsval(x)) == 0) {
1628 flush_all(); /* fflush() or fflush("") -> all */
1630 } else if ((fp = openfile(FFLUSH, getsval(x))) == NULL)
1635 default: /* can't happen */
1636 FATAL("illegal function type %d", t);
1642 if (nextarg != NULL) {
1643 WARNING("warning: function has too many arguments");
1644 for ( ; nextarg; nextarg = nextarg->nnext)
1650 Cell *printstat(Node **a, int n) /* print a[0] */
1656 if (a[1] == NULL) /* a[1] is redirection operator, a[2] is file */
1659 fp = redirect(ptoi(a[1]), a[2]);
1660 for (x = a[0]; x != NULL; x = x->nnext) {
1662 fputs(getpssval(y), fp);
1664 if (x->nnext == NULL)
1672 FATAL("write error on %s", filename(fp));
1676 Cell *nullproc(Node **a, int n)
1684 FILE *redirect(int a, Node *b) /* set up all i/o redirections */
1692 fp = openfile(a, fname);
1694 FATAL("can't open file %s", fname);
1702 int mode; /* '|', 'a', 'w' => LE/LT, GT */
1707 void stdinit(void) /* in case stdin, etc., are not constants */
1710 files = calloc(nfiles, sizeof(*files));
1712 FATAL("can't allocate file memory for %u files", nfiles);
1713 files[0].fp = stdin;
1714 files[0].fname = "/dev/stdin";
1716 files[1].fp = stdout;
1717 files[1].fname = "/dev/stdout";
1719 files[2].fp = stderr;
1720 files[2].fname = "/dev/stderr";
1724 FILE *openfile(int a, const char *us)
1731 FATAL("null file name in print or getline");
1732 for (i=0; i < nfiles; i++)
1733 if (files[i].fname && strcmp(s, files[i].fname) == 0) {
1734 if (a == files[i].mode || (a==APPEND && files[i].mode==GT))
1739 if (a == FFLUSH) /* didn't find it, so don't create it! */
1742 for (i=0; i < nfiles; i++)
1743 if (files[i].fp == NULL)
1747 int nnf = nfiles + FOPEN_MAX;
1748 nf = realloc(files, nnf * sizeof(*nf));
1750 FATAL("cannot grow files for %s and %d files", s, nnf);
1751 memset(&nf[nfiles], 0, FOPEN_MAX * sizeof(*nf));
1755 fflush(stdout); /* force a semblance of order */
1759 } else if (a == APPEND) {
1761 m = GT; /* so can mix > and >> */
1762 } else if (a == '|') { /* output pipe */
1764 } else if (a == LE) { /* input pipe */
1766 } else if (a == LT) { /* getline <file */
1767 fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r"); /* "-" is stdin */
1768 } else /* can't happen */
1769 FATAL("illegal redirection %d", a);
1771 files[i].fname = tostring(s);
1778 const char *filename(FILE *fp)
1782 for (i = 0; i < nfiles; i++)
1783 if (fp == files[i].fp)
1784 return files[i].fname;
1788 Cell *closefile(Node **a, int n)
1797 for (i = 0; i < nfiles; i++) {
1798 if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) {
1799 if (ferror(files[i].fp))
1800 WARNING( "i/o error occurred on %s", files[i].fname );
1801 if (files[i].mode == '|' || files[i].mode == LE)
1802 stat = pclose(files[i].fp);
1804 stat = fclose(files[i].fp);
1806 WARNING( "i/o error occurred closing %s", files[i].fname );
1807 if (i > 2) /* don't do /dev/std... */
1808 xfree(files[i].fname);
1809 files[i].fname = NULL; /* watch out for ref thru this */
1815 setfval(x, (Awkfloat) stat);
1823 for (i = 0; i < FOPEN_MAX; i++) {
1825 if (ferror(files[i].fp))
1826 WARNING( "i/o error occurred on %s", files[i].fname );
1827 if (files[i].mode == '|' || files[i].mode == LE)
1828 stat = pclose(files[i].fp);
1830 stat = fclose(files[i].fp);
1832 WARNING( "i/o error occurred while closing %s", files[i].fname );
1837 void flush_all(void)
1841 for (i = 0; i < nfiles; i++)
1843 fflush(files[i].fp);
1846 void backsub(char **pb_ptr, char **sptr_ptr);
1848 Cell *sub(Node **a, int nnn) /* substitute command */
1850 char *sptr, *pb, *q;
1851 Cell *x, *y, *result;
1854 int bufsz = recsize;
1856 if ((buf = (char *) malloc(bufsz)) == NULL)
1857 FATAL("out of memory in sub");
1858 x = execute(a[3]); /* target string */
1860 if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */
1861 pfa = (fa *) a[1]; /* regular expression */
1864 pfa = makedfa(getsval(y), 1);
1867 y = execute(a[2]); /* replacement string */
1869 if (pmatch(pfa, t)) {
1871 adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub");
1873 while (sptr < patbeg)
1876 while (*sptr != 0) {
1877 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub");
1878 if (*sptr == '\\') {
1879 backsub(&pb, &sptr);
1880 } else if (*sptr == '&') {
1882 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub");
1883 for (q = patbeg; q < patbeg+patlen; )
1889 if (pb > buf + bufsz)
1890 FATAL("sub result1 %.30s too big; can't happen", buf);
1891 sptr = patbeg + patlen;
1892 if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
1893 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
1894 while ((*pb++ = *sptr++) != 0)
1897 if (pb > buf + bufsz)
1898 FATAL("sub result2 %.30s too big; can't happen", buf);
1899 setsval(x, buf); /* BUG: should be able to avoid copy */
1908 Cell *gsub(Node **a, int nnn) /* global substitute */
1911 char *rptr, *sptr, *t, *pb, *q;
1914 int mflag, tempstat, num;
1915 int bufsz = recsize;
1917 if ((buf = (char *) malloc(bufsz)) == NULL)
1918 FATAL("out of memory in gsub");
1919 mflag = 0; /* if mflag == 0, can replace empty string */
1921 x = execute(a[3]); /* target string */
1923 if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */
1924 pfa = (fa *) a[1]; /* regular expression */
1927 pfa = makedfa(getsval(y), 1);
1930 y = execute(a[2]); /* replacement string */
1931 if (pmatch(pfa, t)) {
1932 tempstat = pfa->initstat;
1937 if (patlen == 0 && *patbeg != 0) { /* matched empty string */
1938 if (mflag == 0) { /* can replace empty */
1941 while (*sptr != 0) {
1942 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1943 if (*sptr == '\\') {
1944 backsub(&pb, &sptr);
1945 } else if (*sptr == '&') {
1947 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1948 for (q = patbeg; q < patbeg+patlen; )
1954 if (*t == 0) /* at end */
1956 adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
1958 if (pb > buf + bufsz) /* BUG: not sure of this test */
1959 FATAL("gsub result0 %.30s too big; can't happen", buf);
1962 else { /* matched nonempty string */
1965 adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub");
1966 while (sptr < patbeg)
1969 while (*sptr != 0) {
1970 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1971 if (*sptr == '\\') {
1972 backsub(&pb, &sptr);
1973 } else if (*sptr == '&') {
1975 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1976 for (q = patbeg; q < patbeg+patlen; )
1981 t = patbeg + patlen;
1982 if (patlen == 0 || *t == 0 || *(t-1) == 0)
1984 if (pb > buf + bufsz)
1985 FATAL("gsub result1 %.30s too big; can't happen", buf);
1988 } while (pmatch(pfa,t));
1990 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
1991 while ((*pb++ = *sptr++) != 0)
1993 done: if (pb < buf + bufsz)
1995 else if (*(pb-1) != '\0')
1996 FATAL("gsub result2 %.30s truncated; can't happen", buf);
1997 setsval(x, buf); /* BUG: should be able to avoid copy + free */
1998 pfa->initstat = tempstat;
2009 void backsub(char **pb_ptr, char **sptr_ptr) /* handle \\& variations */
2010 { /* sptr[0] == '\\' */
2011 char *pb = *pb_ptr, *sptr = *sptr_ptr;
2013 if (sptr[1] == '\\') {
2014 if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
2018 } else if (sptr[2] == '&') { /* \\& -> \ + matched */
2021 } else { /* \\x -> \\x */
2025 } else if (sptr[1] == '&') { /* literal & */
2028 } else /* literal \ */