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 ****************************************************************/
33 extern int pairstack[];
35 Node *winner = nil; /* root of parse tree */
36 Cell *tmps; /* free temporary cells for execution */
38 static Cell truecell ={ OBOOL, BTRUE, 0, 0, 1.0, NUM };
39 Cell *True = &truecell;
40 static Cell falsecell ={ OBOOL, BFALSE, 0, 0, 0.0, NUM };
41 Cell *False = &falsecell;
42 static Cell breakcell ={ OJUMP, JBREAK, 0, 0, 0.0, NUM };
43 Cell *jbreak = &breakcell;
44 static Cell contcell ={ OJUMP, JCONT, 0, 0, 0.0, NUM };
45 Cell *jcont = &contcell;
46 static Cell nextcell ={ OJUMP, JNEXT, 0, 0, 0.0, NUM };
47 Cell *jnext = &nextcell;
48 static Cell nextfilecell ={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM };
49 Cell *jnextfile = &nextfilecell;
50 static Cell exitcell ={ OJUMP, JEXIT, 0, 0, 0.0, NUM };
51 Cell *jexit = &exitcell;
52 static Cell retcell ={ OJUMP, JRET, 0, 0, 0.0, NUM };
53 Cell *jret = &retcell;
54 static Cell tempcell ={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE };
56 Node *curnode = nil; /* the node being executed, for debugging */
68 execl("/bin/rc", "rc", "-c", s, nil);
77 FATAL("Out of memory");
78 if(status->pid == pid)
83 if(status->msg[0] != '\0') {
91 /* buffer memory management */
92 int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,
94 /* pbuf: address of pointer to buffer being managed
95 * psiz: address of buffer size variable
96 * minlen: minimum length of buffer needed
97 * quantum: buffer size quantum
98 * pbptr: address of movable pointer into buffer, or 0 if none
99 * whatrtn: name of the calling routine if failure should cause fatal error
101 * return 0 for realloc failure, !=0 for success
104 if (minlen > *psiz) {
106 int rminlen = quantum ? minlen % quantum : 0;
107 int boff = pbptr ? *pbptr - *pbuf : 0;
108 /* round up to next multiple of quantum */
110 minlen += quantum - rminlen;
111 tbuf = (char *) realloc(*pbuf, minlen);
114 FATAL("out of memory in %s", whatrtn);
120 *pbptr = tbuf + boff;
125 void run(Node *a) /* execution of parse tree starts here */
127 extern void stdinit(void);
134 Cell *execute(Node *u) /* execute a node of the parse tree */
137 Cell *(*proc)(Node **, int);
143 for (a = u; ; a = a->nnext) {
146 x = (Cell *) (a->narg[0]);
147 if (isfld(x) && !donefld)
149 else if (isrec(x) && !donerec)
154 if (notlegal(nobj)) /* probably a Cell* but too risky to print */
155 FATAL("illegal statement");
156 proc = proctab[nobj-FIRSTTOKEN];
157 x = (*proc)(a->narg, nobj);
158 if (isfld(x) && !donefld)
160 else if (isrec(x) && !donerec)
174 Cell *program(Node **a, int) /* execute an awk program */
175 { /* a[0] = BEGIN, a[1] = body, a[2] = END */
178 if (setjmp(env) != 0)
180 if (a[0]) { /* BEGIN */
185 FATAL("illegal break, continue, next or nextfile from BEGIN");
190 while (getrec(&record, &recsize, 1) > 0) {
198 if (setjmp(env) != 0) /* handles exit within END */
200 if (a[2]) { /* END */
202 if (isbreak(x) || isnext(x) || iscont(x))
203 FATAL("illegal break, continue, next or nextfile from END");
211 struct Frame { /* stack frame for awk function calls */
212 int nargs; /* number of arguments in this call */
213 Cell *fcncell; /* pointer to Cell for function */
214 Cell **args; /* pointer to array of arguments after execute */
215 Cell *retval; /* return value */
218 #define NARGS 50 /* max args in a call */
220 struct Frame *frame = nil; /* base of stack frames; dynamically allocated */
221 int nframe = 0; /* number of frames allocated */
222 struct Frame *fp = nil; /* frame pointer. bottom level unused */
224 Cell *call(Node **a, int) /* function call. very kludgy and fragile */
226 static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE };
229 Cell *args[NARGS], *oargs[NARGS]; /* BUG: fixed size arrays */
233 fcn = execute(a[0]); /* the function itself */
236 FATAL("calling undefined function %s", s);
238 fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
240 FATAL("out of space for stack frames calling %s", s);
242 for (ncall = 0, x = a[1]; x != nil; x = x->nnext) /* args in call */
244 ndef = (int) fcn->fval; /* args in defn */
245 dprint( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) );
247 WARNING("function %s called with %d args, uses only %d",
249 if (ncall + ndef > NARGS)
250 FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS);
251 for (i = 0, x = a[1]; x != nil; i++, x = x->nnext) { /* get call args */
252 dprint( ("evaluate args[%d], fp=%d:\n", i, (int) (fp-frame)) );
255 dprint( ("args[%d]: %s %f <%s>, t=%o\n",
256 i, y->nval, y->fval, isarr(y) ? "(array)" : y->sval, y->tval) );
258 FATAL("can't use function %s as argument in %s", y->nval, s);
260 args[i] = y; /* arrays by ref */
262 args[i] = copycell(y);
266 for ( ; i < ndef; i++) { /* add null args for ones not provided */
268 *args[i] = newcopycell;
270 fp++; /* now ok to up frame */
271 if (fp >= frame + nframe) {
272 int dfp = fp - frame; /* old index */
273 frame = (struct Frame *)
274 realloc((char *) frame, (nframe += 100) * sizeof(struct Frame));
276 FATAL("out of space for stack frames in %s", s);
281 fp->nargs = ndef; /* number defined with (excess are locals) */
282 fp->retval = gettemp();
284 dprint( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) );
285 y = execute((Node *)(fcn->sval)); /* execute body */
286 dprint( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) );
288 for (i = 0; i < ndef; i++) {
289 Cell *t = fp->args[i];
291 if (t->csub == CCOPY) {
298 oargs[i]->tval = t->tval;
299 oargs[i]->tval &= ~(STR|NUM|DONTFREE);
300 oargs[i]->sval = t->sval;
305 } else if (t != y) { /* kludge to prevent freeing twice */
313 if (isexit(y) || isnext(y) || isnextfile(y))
316 tfree(y); /* this can free twice! */
317 z = fp->retval; /* return value */
318 dprint( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );
323 Cell *copycell(Cell *x) /* make a copy of a cell in a temp */
328 y->csub = CCOPY; /* prevents freeing until call is over */
329 y->nval = x->nval; /* BUG? */
330 y->sval = x->sval ? tostring(x->sval) : nil;
332 y->tval = x->tval & ~(CON|FLD|REC|DONTFREE); /* copy is not constant or field */
333 /* is DONTFREE right? */
337 Cell *arg(Node **a, int n) /* nth argument of a function */
340 n = ptoi(a[0]); /* argument number, counting from 0 */
341 dprint( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );
343 FATAL("argument #%d of function %s was not supplied",
344 n+1, fp->fcncell->nval);
348 Cell *jump(Node **a, int n) /* break, continue, next, nextfile, return */
356 if((y->tval & (NUM|STR)) == STR) {
357 exitstatus = getsval(y);
358 } else if((int) getfval(y) != 0) {
359 exitstatus = "error";
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);
390 default: /* can't happen */
391 FATAL("illegal jump type %d", n);
393 return 0; /* not reached */
396 Cell *getline(Node **a, int n) /* get next line from specific input */
397 { /* a[0] is variable, a[1] is operator, a[2] is filename */
399 extern Cell **fldtab;
402 int bufsize = recsize;
405 if ((buf = (char *) malloc(bufsize)) == nil)
406 FATAL("out of memory in getline");
408 Bflush(&stdout); /* in case someone is waiting for a prompt */
410 if (a[1] != nil) { /* getline < file */
411 x = execute(a[2]); /* filename */
413 if (mode == '|') /* input pipe */
414 mode = LE; /* arbitrary flag */
415 fp = openfile(mode, getsval(x));
421 n = readrec(&buf, &bufsize, fp);
424 } else if (a[0] != nil) { /* getline var <file */
429 } else { /* getline <file */
430 setsval(fldtab[0], buf);
431 if (is_number(fldtab[0]->sval)) {
432 fldtab[0]->fval = atof(fldtab[0]->sval);
433 fldtab[0]->tval |= NUM;
436 } else { /* bare getline; use current input */
437 if (a[0] == nil) /* getline */
438 n = getrec(&record, &recsize, 1);
439 else { /* getline var */
440 n = getrec(&buf, &bufsize, 0);
447 setfval(r, (Awkfloat) n);
452 Cell *getnf(Node **a, int) /* get NF */
456 return (Cell *) a[0];
459 Cell *array(Node **a, int) /* a[0] is symtab, a[1] is list of subscripts */
466 int nsub = strlen(*SUBSEP);
468 if ((buf = (char *) malloc(bufsz)) == nil)
469 FATAL("out of memory in array");
471 x = execute(a[0]); /* Cell* for symbol table */
473 for (np = a[1]; np; np = np->nnext) {
474 y = execute(np); /* subscript */
476 if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))
477 FATAL("out of memory for %s[%s...]", x->nval, buf);
480 strcat(buf, *SUBSEP);
485 dprint( ("making %s into an array\n", x->nval) );
488 x->tval &= ~(STR|NUM|DONTFREE);
490 x->sval = (char *) makesymtab(NSYMTAB);
492 z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
501 Cell *awkdelete(Node **a, int) /* a[0] is symtab, a[1] is list of subscripts */
506 int nsub = strlen(*SUBSEP);
508 x = execute(a[0]); /* Cell* for symbol table */
511 if (a[1] == 0) { /* delete the elements, not the table */
515 x->sval = (char *) makesymtab(NSYMTAB);
519 if ((buf = (char *) malloc(bufsz)) == nil)
520 FATAL("out of memory in adelete");
522 for (np = a[1]; np; np = np->nnext) {
523 y = execute(np); /* subscript */
525 if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))
526 FATAL("out of memory deleting %s[%s...]", x->nval, buf);
529 strcat(buf, *SUBSEP);
541 Cell *intest(Node **a, int) /* a[0] is index (list), a[1] is symtab */
548 int nsub = strlen(*SUBSEP);
550 ap = execute(a[1]); /* array name */
552 dprint( ("making %s into an array\n", ap->nval) );
555 ap->tval &= ~(STR|NUM|DONTFREE);
557 ap->sval = (char *) makesymtab(NSYMTAB);
559 if ((buf = (char *) malloc(bufsz)) == nil) {
560 FATAL("out of memory in intest");
563 for (p = a[0]; p; p = p->nnext) {
564 x = execute(p); /* expr */
566 if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, 0))
567 FATAL("out of memory deleting %s[%s...]", x->nval, buf);
572 strcat(buf, *SUBSEP);
574 k = lookup(buf, (Array *) ap->sval);
585 Cell *matchop(Node **a, int n) /* ~ and match() */
592 x = execute(a[1]); /* a[1] = target text */
594 if (a[0] == 0) /* a[1] == 0: already-compiled reg expr */
597 y = execute(a[2]); /* a[2] = regular expr */
610 int start = utfnlen(s, patbeg-s)+1;
613 setfval(rstartloc, (Awkfloat) start);
614 setfval(rlengthloc, (Awkfloat) utfnlen(patbeg, patlen));
619 } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
626 Cell *boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */
645 if ( !i ) return(False);
653 if (i) return(False);
655 default: /* can't happen */
656 FATAL("unknown boolean operator %d", n);
658 return 0; /*NOTREACHED*/
661 Cell *relop(Node **a, int n) /* a[0 < a[1], etc. */
669 if (x->tval&NUM && y->tval&NUM) {
670 j = x->fval - y->fval;
671 i = j<0? -1: (j>0? 1: 0);
673 i = strcmp(getsval(x), getsval(y));
680 case LT: if (i<0) return(True);
682 case LE: if (i<=0) return(True);
684 case NE: if (i!=0) return(True);
686 case EQ: if (i == 0) return(True);
688 case GE: if (i>=0) return(True);
690 case GT: if (i>0) return(True);
692 default: /* can't happen */
693 FATAL("unknown relational operator %d", n);
695 return 0; /*NOTREACHED*/
698 void tfree(Cell *a) /* free a tempcell */
701 dprint( ("freeing %s %s %o\n", a->nval, a->sval, a->tval) );
705 FATAL("tempcell list is curdled");
710 Cell *gettemp(void) /* get a tempcell */
715 tmps = (Cell *) calloc(100, sizeof(Cell));
717 FATAL("out of space for temporaries");
718 for(i = 1; i < 100; i++)
719 tmps[i-1].cnext = &tmps[i];
728 Cell *indirect(Node **a, int) /* $( a[0] ) */
735 m = (int) getfval(x);
736 if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */
737 FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
738 /* BUG: can x->nval ever be null??? */
742 x->ctype = OCELL; /* BUG? why are these needed? */
747 Cell *substr(Node **a, int) /* substr(a[0], a[1], a[2]) */
760 k = utfnlen(s, strlen(s)) + 1;
774 m = (int) getfval(y);
782 n = (int) getfval(z);
791 dprint( ("substr: m=%d, n=%d, s=%s\n", m, n, s) );
794 s += chartorune(&r, s);
795 for (p = s; *p && n--; p += chartorune(&r, p))
797 temp = *p; /* with thanks to John Linderman */
806 Cell *sindex(Node **a, int) /* index(a[0], a[1]) */
809 char *s1, *s2, *p1, *p2, *q;
818 for (p1 = s1; *p1 != '\0'; p1++) {
819 for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
822 v = (Awkfloat) utfnlen(s1, p1-s1) + 1; /* origin 1 */
834 #define MAXNUMSIZE 50
836 int format(char **pbuf, int *pbufsize, char *s, Node *a) /* printf-like conversions */
842 int fmtwd; /* format width */
845 int bufsize = *pbufsize;
849 if ((fmt = (char *) malloc(fmtsz)) == nil)
850 FATAL("out of memory in format()");
852 adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format");
862 /* have to be real careful in case this is a huge number, eg, %100000d */
866 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
867 for (t = fmt; (*t++ = *s) != '\0'; s++) {
868 if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, 0))
869 FATAL("format item %.30s... ran format() out of memory", os);
870 if (isalpha(*s) && *s != 'l' && *s != 'h' && *s != 'L')
871 break; /* the ansi panoply */
875 sprint(t-1, "%d", fmtwd=(int) getfval(x));
878 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
879 t = fmt + strlen(fmt);
887 adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
890 case 'f': case 'e': case 'g': case 'E': case 'G':
895 if(*(s-1) == 'l') break;
901 flag = *(s-1) == 'l' ? 2 : 3;
906 case 'o': case 'x': case 'X':
907 flag = *(s-1) == 'l' ? 2 : 3;
919 WARNING("weird printf conversion %s", fmt);
924 FATAL("not enough args in printf(%s)", os);
930 adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format");
932 case 0: sprint(p, "%s", fmt); /* unknown, so dump it too */
937 adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format");
941 case 1: sprint(p, fmt, getfval(x)); break;
942 case 2: sprint(p, fmt, (long) getfval(x)); break;
943 case 3: sprint(p, fmt, (int) getfval(x)); break;
949 if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, 0))
950 FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t);
956 *p++ = (uchar)getfval(x);
963 if((*p = getsval(x)[0]) != '\0')
976 for ( ; a; a = a->nnext) /* evaluate any remaining args */
983 Cell *awksprintf(Node **a, int) /* sprint(a[0]) */
990 if ((buf = (char *) malloc(bufsz)) == nil)
991 FATAL("out of memory in awksprint");
994 if (format(&buf, &bufsz, getsval(x), y) == -1)
995 FATAL("sprint string %.30s... too long. can't happen.", buf);
1004 Cell *awkprintf(Node **a, int) /* printf */
1005 { /* a[0] is list of args, starting with format string */
1006 /* a[1] is redirection operator, a[2] is redirection file */
1012 int bufsz=3*recsize;
1014 if ((buf = (char *) malloc(bufsz)) == nil)
1015 FATAL("out of memory in awkprintf");
1018 if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
1019 FATAL("printf string %.30s... too long. can't happen.", buf);
1022 fp = a[1]? redirect(ptoi(a[1]), a[2]): &stdout;
1023 if(Bwrite(fp, buf, len) < 0)
1024 FATAL("write error on %s", filename(fp));
1025 if(fp != &stdout) Bflush(fp);
1030 Cell *arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */
1059 FATAL("division by zero");
1064 FATAL("division by zero in mod");
1072 if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
1073 i = ipow(i, (int) j);
1075 i = errcheck(pow(i, j), "pow");
1077 default: /* can't happen */
1078 FATAL("illegal arithmetic operator %d", n);
1084 double ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */
1097 Cell *incrdecr(Node **a, int n) /* a[0]++, etc. */
1105 k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
1106 if (n == PREINCR || n == PREDECR) {
1118 Cell *assign(Node **a, int n) /* a[0] = a[1], a[0] += a[1], etc. */
1119 { /* this is subtle; don't muck with it. */
1126 if (n == ASSIGN) { /* ordinary assignment */
1127 if (x == y && !(x->tval & (FLD|REC))) /* self-assignment: */
1128 goto Free; /* leave alone unless it's a field */
1129 if ((y->tval & (STR|NUM)) == (STR|NUM)) {
1130 setsval(x, getsval(y));
1131 x->fval = getfval(y);
1135 setsval(x, getsval(y));
1137 setfval(x, getfval(y));
1139 funnyvar(y, "read value of");
1159 FATAL("division by zero in /=");
1164 FATAL("division by zero in %%=");
1169 if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */
1170 xf = ipow(xf, (int) yf);
1172 xf = errcheck(pow(xf, yf), "pow");
1175 FATAL("illegal assignment operator %d", n);
1184 Cell *cat(Node **a, int) /* a[0] cat a[1] */
1194 n1 = strlen(x->sval);
1195 n2 = strlen(y->sval);
1196 s = (char *) malloc(n1 + n2 + 1);
1198 FATAL("out of space concatenating %.15s... and %.15s...",
1201 strcpy(s+n1, y->sval);
1212 Cell *pastat(Node **a, int) /* a[0] { a[1] } */
1229 Cell *dopa2(Node **a, int) /* a[0], a[1] { a[2] } */
1235 if (pairstack[pair] == 0) {
1238 pairstack[pair] = 1;
1242 if (pairstack[pair] == 1) {
1245 pairstack[pair] = 0;
1254 Cell *split(Node **a, int) /* split(a[0], a[1], a[2]); a[3] is type */
1256 Cell *x = 0, *y, *ap;
1257 char *s, *t, *fs = 0;
1259 int n, nb, sep, arg3type;
1261 y = execute(a[0]); /* source string */
1263 arg3type = ptoi(a[3]);
1264 if (a[2] == 0) /* fs string */
1266 else if (arg3type == STRING) { /* split(str,arr,"string") */
1269 } else if (arg3type == REGEXPR)
1270 fs = "(regexpr)"; /* split(str,arr,/regexpr/) */
1272 FATAL("illegal type of split");
1274 ap = execute(a[1]); /* array name */
1276 y->tval |= DONTFREE; /* split(a[x], a); */
1279 dprint( ("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs) );
1282 ap->sval = (char *) makesymtab(NSYMTAB);
1285 if ((*s != '\0' && strlen(fs) > 1) || arg3type == REGEXPR) { /* reg expr */
1287 if (arg3type == REGEXPR) { /* it's ready already */
1293 if (nematch(p,s,t)) {
1296 sprint(num, "%d", n);
1300 setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1302 setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1304 t = patbeg + patlen;
1305 if (t[-1] == 0 || *t == 0) {
1307 sprint(num, "%d", n);
1308 setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
1311 } while (nematch(p,s,t));
1314 sprint(num, "%d", n);
1316 setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1318 setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1322 } else if (sep == ' ') {
1324 while (*s == ' ' || *s == '\t' || *s == '\n')
1332 while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
1335 sprint(num, "%d", n);
1337 setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1339 setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1344 } else if (sep == 0) { /* new: split(s, a, "") => 1 char/elem */
1345 for (n = 0; *s != 0; s += nb) {
1350 snprint(num, sizeof num, "%d", n);
1351 nb = chartorune(&r, s);
1352 memmove(buf, s, nb);
1354 if (isdigit(buf[0]))
1355 setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval);
1357 setsymtab(num, buf, 0.0, STR, (Array *) ap->sval);
1359 } else if (*s != 0) {
1363 while (*s != sep && *s != '\n' && *s != '\0')
1367 sprint(num, "%d", n);
1369 setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1371 setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1381 if (a[2] != 0 && arg3type == STRING)
1390 Cell *condexpr(Node **a, int) /* a[0] ? a[1] : a[2] */
1407 Cell *ifstat(Node **a, int) /* if (a[0]) a[1]; else a[2] */
1416 } else if (a[2] != 0) {
1424 Cell *whilestat(Node **a, int) /* while (a[0]) a[1] */
1439 if (isnext(x) || isexit(x) || isret(x))
1446 Cell *dostat(Node **a, int) /* do a[0]; while(a[1]) */
1454 if (isnext(x) || isnextfile(x) || isexit(x) || isret(x))
1466 Cell *forstat(Node **a, int) /* for (a[0]; a[1]; a[2]) a[3] */
1482 if (isbreak(x)) /* turn off break */
1484 if (isnext(x) || isexit(x) || isret(x))
1494 Cell *instat(Node **a, int) /* for (a[0] in a[1]) a[2] */
1496 Cell *x, *vp, *arrayp, *cp, *ncp;
1501 arrayp = execute(a[1]);
1502 if (!isarr(arrayp)) {
1505 tp = (Array *) arrayp->sval;
1508 for (i = 0; i < tp->size; i++) { /* this routine knows too much */
1509 for (cp = tp->tab[i]; cp != nil; cp = ncp) {
1510 setsval(vp, cp->nval);
1518 if (isnext(x) || isexit(x) || isret(x)) {
1530 Cell *bltin(Node **a, int) /* builtin functions. a[0] is type, a[1] is arg list */
1540 void flush_all(void);
1544 nextarg = a[1]->nnext;
1548 u = ((Array *) x->sval)->nelemt; /* GROT. should be function*/
1551 u = (Awkfloat) utfnlen(p, strlen(p));
1555 u = errcheck(log(getfval(x)), "log"); break;
1557 modf(getfval(x), &u); break;
1559 u = errcheck(exp(getfval(x)), "exp"); break;
1561 u = errcheck(sqrt(getfval(x)), "sqrt"); break;
1563 u = sin(getfval(x)); break;
1565 u = cos(getfval(x)); break;
1568 WARNING("atan2 requires two arguments; returning 1.0");
1571 y = execute(a[1]->nnext);
1572 u = atan2(getfval(x), getfval(y));
1575 nextarg = nextarg->nnext;
1579 Bflush(&stdout); /* in case something is buffered already */
1580 u = (Awkfloat) system(getsval(x));
1586 if (isrec(x)) /* no argument provided */
1587 u = (Awkfloat) (truerand() >> 1);
1590 srand((unsigned int) u);
1594 buf = tostring(getsval(x));
1595 if (t == FTOUPPER) {
1596 for (p = buf; *p; p++)
1600 for (p = buf; *p; p++)
1611 if (isrec(x) || strlen(getsval(x)) == 0) {
1612 flush_all(); /* fflush() or fflush("") -> all */
1614 } else if ((fp = openfile(FFLUSH, getsval(x))) == nil)
1620 wc = (int)getfval(x);
1621 mbc[runetochar(mbc, &wc)] = 0;
1627 default: /* can't happen */
1628 FATAL("illegal function type %d", t);
1636 WARNING("warning: function has too many arguments");
1637 for ( ; nextarg; nextarg = nextarg->nnext)
1643 Cell *printstat(Node **a, int) /* print a[0] */
1650 if (a[1] == 0) /* a[1] is redirection operator, a[2] is file */
1653 fp = redirect(ptoi(a[1]), a[2]);
1654 for (x = a[0]; x != nil; x = x->nnext) {
1656 Bwrite(fp, getsval(y), strlen(getsval(y)));
1659 if (x->nnext == nil)
1660 r = Bprint(fp, "%s", *ORS);
1662 r = Bprint(fp, "%s", *OFS);
1664 FATAL("write error on %s", filename(fp));
1667 FATAL("write error on %s", filename(fp));
1671 Cell *nullproc(Node **, int)
1677 Biobuf *redirect(int a, Node *b) /* set up all i/o redirections */
1685 fp = openfile(a, fname);
1687 FATAL("can't open file %s", fname);
1696 int mode; /* '|', 'a', 'w' => LE/LT, GT */
1697 } files[FOPEN_MAX] ={
1698 { nil, "/dev/stdin", LT }, /* watch out: don't free this! */
1699 { nil, "/dev/stdout", GT },
1700 { nil, "/dev/stderr", GT }
1703 void stdinit(void) /* in case stdin, etc., are not constants */
1705 files[0].fp = &stdin;
1706 files[1].fp = &stdout;
1707 files[2].fp = &stderr;
1710 Biobuf *openfile(int a, char *us)
1717 FATAL("null file name in print or getline");
1718 for (i=0; i < FOPEN_MAX; i++)
1719 if (files[i].fname && strcmp(s, files[i].fname) == 0) {
1720 if (a == files[i].mode || (a==APPEND && files[i].mode==GT))
1725 if (a == FFLUSH) /* didn't find it, so don't create it! */
1728 for (i=0; i < FOPEN_MAX; i++)
1729 if (files[i].fp == 0)
1732 FATAL("%s makes too many open files", s);
1733 Bflush(&stdout); /* force a semblance of order */
1736 fp = Bopen(s, OWRITE);
1737 } else if (a == APPEND) {
1738 fd = open(s, OWRITE);
1740 fd = create(s, OWRITE, 0666);
1742 fp = Bfdopen(fd, OWRITE);
1745 m = GT; /* so can mix > and >> */
1747 } else if (a == '|') { /* output pipe */
1748 fp = popen(s, OWRITE);
1749 } else if (a == LE) { /* input pipe */
1750 fp = popen(s, OREAD);
1751 } else if (a == LT) { /* getline <file */
1752 fp = strcmp(s, "-") == 0 ? &stdin : Bopen(s, OREAD); /* "-" is stdin */
1753 } else /* can't happen */
1754 FATAL("illegal redirection %d", a);
1756 files[i].fname = tostring(s);
1763 char *filename(Biobuf *fp)
1767 for (i = 0; i < FOPEN_MAX; i++)
1768 if (fp == files[i].fp)
1769 return files[i].fname;
1773 Cell *closefile(Node **a, int)
1780 for (i = 0; i < FOPEN_MAX; i++)
1781 if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) {
1782 if (files[i].mode == '|' || files[i].mode == LE)
1783 stat = pclose(files[i].fp);
1785 stat = Bterm(files[i].fp);
1787 WARNING( "i/o error occurred closing %s", files[i].fname );
1788 if (i > 2) /* don't do /dev/std... */
1789 xfree(files[i].fname);
1790 files[i].fname = nil; /* watch out for ref thru this */
1802 for (i = 0; i < FOPEN_MAX; i++)
1804 if (files[i].mode == '|' || files[i].mode == LE)
1805 stat = pclose(files[i].fp);
1807 stat = Bterm(files[i].fp);
1809 WARNING( "i/o error occurred while closing %s", files[i].fname );
1813 void flush_all(void)
1817 for (i = 0; i < FOPEN_MAX; i++)
1819 Bflush(files[i].fp);
1822 void backsub(char **pb_ptr, char **sptr_ptr);
1824 Cell *sub(Node **a, int) /* substitute command */
1826 char *sptr, *pb, *q;
1827 Cell *x, *y, *result;
1830 int bufsz = recsize;
1832 if ((buf = (char *) malloc(bufsz)) == nil)
1833 FATAL("out of memory in sub");
1834 x = execute(a[3]); /* target string */
1836 if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1837 p = (void *) a[1]; /* regular expression */
1840 p = compre(getsval(y));
1844 y = execute(a[2]); /* replacement string */
1846 if (pmatch(p, t, t)) {
1848 adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub");
1850 while (sptr < patbeg)
1853 while (*sptr != 0) {
1854 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub");
1855 if (*sptr == '\\') {
1856 backsub(&pb, &sptr);
1857 } else if (*sptr == '&') {
1859 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub");
1860 for (q = patbeg; q < patbeg+patlen; )
1866 if (pb > buf + bufsz)
1867 FATAL("sub result1 %.30s too big; can't happen", buf);
1868 sptr = patbeg + patlen;
1869 if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
1870 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
1871 while ((*pb++ = *sptr++) != 0)
1874 if (pb > buf + bufsz)
1875 FATAL("sub result2 %.30s too big; can't happen", buf);
1876 setsval(x, buf); /* BUG: should be able to avoid copy */
1887 Cell *gsub(Node **a, int) /* global substitute */
1890 char *rptr, *sptr, *t, *pb, *c, *s;
1894 int bufsz = recsize;
1896 if ((buf = (char *)malloc(bufsz)) == nil)
1897 FATAL("out of memory in gsub");
1898 mflag = 0; /* if mflag == 0, can replace empty string */
1900 x = execute(a[3]); /* target string */
1902 if (a[0] == 0) /* 0 => a[1] is already-compiled regexpr */
1903 p = (void *) a[1]; /* regular expression */
1911 y = execute(a[2]); /* replacement string */
1912 if (pmatch(p, t, c)) {
1916 if (patlen == 0 && *patbeg != 0) { /* matched empty string */
1917 if (mflag == 0) { /* can replace empty */
1920 while (*sptr != 0) {
1921 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1922 if (*sptr == '\\') {
1923 backsub(&pb, &sptr);
1924 } else if (*sptr == '&') {
1927 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1928 for (q = patbeg; q < patbeg+patlen; )
1934 if (*c == 0) /* at end */
1936 adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
1938 if (pb > buf + bufsz) /* BUG: not sure of this test */
1939 FATAL("gsub result0 %.30s too big; can't happen", buf);
1942 else { /* matched nonempty string */
1945 adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub");
1946 while (sptr < patbeg)
1949 while (*sptr != 0) {
1950 adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1951 if (*sptr == '\\') {
1952 backsub(&pb, &sptr);
1953 } else if (*sptr == '&') {
1956 adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1957 for (q = patbeg; q < patbeg+patlen; )
1962 c = patbeg + patlen;
1963 if ((c[-1] == 0) || (*c == 0))
1965 if (pb > buf + bufsz)
1966 FATAL("gsub result1 %.30s too big; can't happen", buf);
1969 } while (pmatch(p, t, c));
1971 adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
1972 while ((*pb++ = *sptr++) != 0)
1974 done: if (pb > buf + bufsz)
1975 FATAL("gsub result2 %.30s too big; can't happen", buf);
1977 setsval(x, buf); /* BUG: should be able to avoid copy + free */
1990 void backsub(char **pb_ptr, char **sptr_ptr) /* handle \\& variations */
1991 { /* sptr[0] == '\\' */
1992 char *pb = *pb_ptr, *sptr = *sptr_ptr;
1994 if (sptr[1] == '\\') {
1995 if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
1999 } else if (sptr[2] == '&') { /* \\& -> \ + matched */
2002 } else { /* \\x -> \\x */
2006 } else if (sptr[1] == '&') { /* literal & */
2009 } else /* literal \ */