17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
583efe03bScf46844 * Common Development and Distribution License (the "License").
683efe03bScf46844 * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate
227c478bd9Sstevel@tonic-gate /*
23*23a1cceaSRoger A. Faulkner * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
261ee2e5faSnakanon /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
271ee2e5faSnakanon /* All Rights Reserved */
287c478bd9Sstevel@tonic-gate
291ee2e5faSnakanon #define tempfree(x, s) if (istemp(x)) tfree(x, s)
301ee2e5faSnakanon
317c478bd9Sstevel@tonic-gate #define execute(p) r_execute(p)
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate #define DEBUG
347c478bd9Sstevel@tonic-gate #include "awk.h"
357c478bd9Sstevel@tonic-gate #include <math.h>
367c478bd9Sstevel@tonic-gate #include "y.tab.h"
377c478bd9Sstevel@tonic-gate #include <stdio.h>
387c478bd9Sstevel@tonic-gate #include <ctype.h>
397c478bd9Sstevel@tonic-gate #include <setjmp.h>
407c478bd9Sstevel@tonic-gate #include <time.h>
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate #ifndef FOPEN_MAX
437c478bd9Sstevel@tonic-gate #define FOPEN_MAX 15 /* max number of open files, from ANSI std. */
447c478bd9Sstevel@tonic-gate #endif
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate
471ee2e5faSnakanon static jmp_buf env;
487c478bd9Sstevel@tonic-gate
491ee2e5faSnakanon static Cell *r_execute(Node *);
501ee2e5faSnakanon static Cell *gettemp(char *), *copycell(Cell *);
511ee2e5faSnakanon static FILE *openfile(int, uchar *), *redirect(int, Node *);
527c478bd9Sstevel@tonic-gate
537c478bd9Sstevel@tonic-gate int paircnt;
547c478bd9Sstevel@tonic-gate Node *winner = NULL;
551ee2e5faSnakanon
561ee2e5faSnakanon static Cell *tmps;
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate static Cell truecell = { OBOOL, BTRUE, 0, 0, 1.0, NUM };
597c478bd9Sstevel@tonic-gate Cell *true = &truecell;
607c478bd9Sstevel@tonic-gate static Cell falsecell = { OBOOL, BFALSE, 0, 0, 0.0, NUM };
617c478bd9Sstevel@tonic-gate Cell *false = &falsecell;
627c478bd9Sstevel@tonic-gate static Cell breakcell = { OJUMP, JBREAK, 0, 0, 0.0, NUM };
637c478bd9Sstevel@tonic-gate Cell *jbreak = &breakcell;
647c478bd9Sstevel@tonic-gate static Cell contcell = { OJUMP, JCONT, 0, 0, 0.0, NUM };
657c478bd9Sstevel@tonic-gate Cell *jcont = &contcell;
667c478bd9Sstevel@tonic-gate static Cell nextcell = { OJUMP, JNEXT, 0, 0, 0.0, NUM };
677c478bd9Sstevel@tonic-gate Cell *jnext = &nextcell;
687c478bd9Sstevel@tonic-gate static Cell exitcell = { OJUMP, JEXIT, 0, 0, 0.0, NUM };
697c478bd9Sstevel@tonic-gate Cell *jexit = &exitcell;
707c478bd9Sstevel@tonic-gate static Cell retcell = { OJUMP, JRET, 0, 0, 0.0, NUM };
717c478bd9Sstevel@tonic-gate Cell *jret = &retcell;
727c478bd9Sstevel@tonic-gate static Cell tempcell = { OCELL, CTEMP, 0, 0, 0.0, NUM };
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate Node *curnode = NULL; /* the node being executed, for debugging */
757c478bd9Sstevel@tonic-gate
761ee2e5faSnakanon static void tfree(Cell *, char *);
771ee2e5faSnakanon static void closeall(void);
781ee2e5faSnakanon static double ipow(double, int);
791ee2e5faSnakanon
801ee2e5faSnakanon void
run(Node * a)811ee2e5faSnakanon run(Node *a)
827c478bd9Sstevel@tonic-gate {
831ee2e5faSnakanon (void) execute(a);
847c478bd9Sstevel@tonic-gate closeall();
857c478bd9Sstevel@tonic-gate }
867c478bd9Sstevel@tonic-gate
871ee2e5faSnakanon static Cell *
r_execute(Node * u)881ee2e5faSnakanon r_execute(Node *u)
897c478bd9Sstevel@tonic-gate {
907c478bd9Sstevel@tonic-gate register Cell *(*proc)();
917c478bd9Sstevel@tonic-gate register Cell *x;
927c478bd9Sstevel@tonic-gate register Node *a;
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate if (u == NULL)
957c478bd9Sstevel@tonic-gate return (true);
967c478bd9Sstevel@tonic-gate for (a = u; ; a = a->nnext) {
977c478bd9Sstevel@tonic-gate curnode = a;
987c478bd9Sstevel@tonic-gate if (isvalue(a)) {
997c478bd9Sstevel@tonic-gate x = (Cell *) (a->narg[0]);
1007c478bd9Sstevel@tonic-gate if ((x->tval & FLD) && !donefld)
1017c478bd9Sstevel@tonic-gate fldbld();
1027c478bd9Sstevel@tonic-gate else if ((x->tval & REC) && !donerec)
1037c478bd9Sstevel@tonic-gate recbld();
1047c478bd9Sstevel@tonic-gate return (x);
1057c478bd9Sstevel@tonic-gate }
1061ee2e5faSnakanon /* probably a Cell* but too risky to print */
1071ee2e5faSnakanon if (notlegal(a->nobj))
1087c478bd9Sstevel@tonic-gate ERROR "illegal statement" FATAL;
1097c478bd9Sstevel@tonic-gate proc = proctab[a->nobj-FIRSTTOKEN];
1107c478bd9Sstevel@tonic-gate x = (*proc)(a->narg, a->nobj);
1117c478bd9Sstevel@tonic-gate if ((x->tval & FLD) && !donefld)
1127c478bd9Sstevel@tonic-gate fldbld();
1137c478bd9Sstevel@tonic-gate else if ((x->tval & REC) && !donerec)
1147c478bd9Sstevel@tonic-gate recbld();
1157c478bd9Sstevel@tonic-gate if (isexpr(a))
1167c478bd9Sstevel@tonic-gate return (x);
1177c478bd9Sstevel@tonic-gate /* a statement, goto next statement */
1187c478bd9Sstevel@tonic-gate if (isjump(x))
1197c478bd9Sstevel@tonic-gate return (x);
1207c478bd9Sstevel@tonic-gate if (a->nnext == (Node *)NULL)
1217c478bd9Sstevel@tonic-gate return (x);
1227c478bd9Sstevel@tonic-gate tempfree(x, "execute");
1237c478bd9Sstevel@tonic-gate }
1247c478bd9Sstevel@tonic-gate }
1257c478bd9Sstevel@tonic-gate
1261ee2e5faSnakanon /*ARGSUSED*/
1271ee2e5faSnakanon Cell *
program(Node ** a,int n)1281ee2e5faSnakanon program(Node **a, int n)
1297c478bd9Sstevel@tonic-gate {
1307c478bd9Sstevel@tonic-gate register Cell *x;
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate if (setjmp(env) != 0)
1337c478bd9Sstevel@tonic-gate goto ex;
1347c478bd9Sstevel@tonic-gate if (a[0]) { /* BEGIN */
1357c478bd9Sstevel@tonic-gate x = execute(a[0]);
1367c478bd9Sstevel@tonic-gate if (isexit(x))
1377c478bd9Sstevel@tonic-gate return (true);
1381ee2e5faSnakanon if (isjump(x)) {
1391ee2e5faSnakanon ERROR "illegal break, continue or next from BEGIN"
1401ee2e5faSnakanon FATAL;
1411ee2e5faSnakanon }
1427c478bd9Sstevel@tonic-gate tempfree(x, "");
1437c478bd9Sstevel@tonic-gate }
1447c478bd9Sstevel@tonic-gate loop:
1457c478bd9Sstevel@tonic-gate if (a[1] || a[2])
1461ee2e5faSnakanon while (getrec(&record, &record_size) > 0) {
1477c478bd9Sstevel@tonic-gate x = execute(a[1]);
1487c478bd9Sstevel@tonic-gate if (isexit(x))
1497c478bd9Sstevel@tonic-gate break;
1507c478bd9Sstevel@tonic-gate tempfree(x, "");
1517c478bd9Sstevel@tonic-gate }
1527c478bd9Sstevel@tonic-gate ex:
1537c478bd9Sstevel@tonic-gate if (setjmp(env) != 0)
1547c478bd9Sstevel@tonic-gate goto ex1;
1557c478bd9Sstevel@tonic-gate if (a[2]) { /* END */
1567c478bd9Sstevel@tonic-gate x = execute(a[2]);
1577c478bd9Sstevel@tonic-gate if (iscont(x)) /* read some more */
1587c478bd9Sstevel@tonic-gate goto loop;
1597c478bd9Sstevel@tonic-gate if (isbreak(x) || isnext(x))
1607c478bd9Sstevel@tonic-gate ERROR "illegal break or next from END" FATAL;
1617c478bd9Sstevel@tonic-gate tempfree(x, "");
1627c478bd9Sstevel@tonic-gate }
1637c478bd9Sstevel@tonic-gate ex1:
1647c478bd9Sstevel@tonic-gate return (true);
1657c478bd9Sstevel@tonic-gate }
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate struct Frame {
1687c478bd9Sstevel@tonic-gate int nargs; /* number of arguments in this call */
1697c478bd9Sstevel@tonic-gate Cell *fcncell; /* pointer to Cell for function */
1707c478bd9Sstevel@tonic-gate Cell **args; /* pointer to array of arguments after execute */
1717c478bd9Sstevel@tonic-gate Cell *retval; /* return value */
1727c478bd9Sstevel@tonic-gate };
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate #define NARGS 30
1757c478bd9Sstevel@tonic-gate
1767c478bd9Sstevel@tonic-gate struct Frame *frame = NULL; /* base of stack frames; dynamically allocated */
1777c478bd9Sstevel@tonic-gate int nframe = 0; /* number of frames allocated */
1787c478bd9Sstevel@tonic-gate struct Frame *fp = NULL; /* frame pointer. bottom level unused */
1797c478bd9Sstevel@tonic-gate
1801ee2e5faSnakanon /*ARGSUSED*/
1811ee2e5faSnakanon Cell *
call(Node ** a,int n)1821ee2e5faSnakanon call(Node **a, int n)
1837c478bd9Sstevel@tonic-gate {
1841ee2e5faSnakanon static Cell newcopycell =
1851ee2e5faSnakanon { OCELL, CCOPY, 0, (uchar *) "", 0.0, NUM|STR|DONTFREE };
1867c478bd9Sstevel@tonic-gate int i, ncall, ndef, freed = 0;
1877c478bd9Sstevel@tonic-gate Node *x;
1887c478bd9Sstevel@tonic-gate Cell *args[NARGS], *oargs[NARGS], *y, *z, *fcn;
1897c478bd9Sstevel@tonic-gate uchar *s;
1907c478bd9Sstevel@tonic-gate
1917c478bd9Sstevel@tonic-gate fcn = execute(a[0]); /* the function itself */
1927c478bd9Sstevel@tonic-gate s = fcn->nval;
1937c478bd9Sstevel@tonic-gate if (!isfunc(fcn))
1947c478bd9Sstevel@tonic-gate ERROR "calling undefined function %s", s FATAL;
1957c478bd9Sstevel@tonic-gate if (frame == NULL) {
1961ee2e5faSnakanon fp = frame = (struct Frame *)calloc(nframe += 100,
1971ee2e5faSnakanon sizeof (struct Frame));
1981ee2e5faSnakanon if (frame == NULL) {
1991ee2e5faSnakanon ERROR "out of space for stack frames calling %s",
2001ee2e5faSnakanon s FATAL;
2011ee2e5faSnakanon }
2027c478bd9Sstevel@tonic-gate }
2037c478bd9Sstevel@tonic-gate for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */
2047c478bd9Sstevel@tonic-gate ncall++;
2057c478bd9Sstevel@tonic-gate ndef = (int)fcn->fval; /* args in defn */
2061ee2e5faSnakanon dprintf(("calling %s, %d args (%d in defn), fp=%d\n",
2071ee2e5faSnakanon s, ncall, ndef, fp-frame));
2081ee2e5faSnakanon if (ncall > ndef) {
2097c478bd9Sstevel@tonic-gate ERROR "function %s called with %d args, uses only %d",
2107c478bd9Sstevel@tonic-gate s, ncall, ndef WARNING;
2111ee2e5faSnakanon }
2121ee2e5faSnakanon if (ncall + ndef > NARGS) {
2131ee2e5faSnakanon ERROR "function %s has %d arguments, limit %d",
2141ee2e5faSnakanon s, ncall+ndef, NARGS FATAL;
2151ee2e5faSnakanon }
2161ee2e5faSnakanon for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) {
2171ee2e5faSnakanon /* get call args */
2187c478bd9Sstevel@tonic-gate dprintf(("evaluate args[%d], fp=%d:\n", i, fp-frame));
2197c478bd9Sstevel@tonic-gate y = execute(x);
2207c478bd9Sstevel@tonic-gate oargs[i] = y;
2217c478bd9Sstevel@tonic-gate dprintf(("args[%d]: %s %f <%s>, t=%o\n",
2221ee2e5faSnakanon i, y->nval, y->fval,
2231ee2e5faSnakanon isarr(y) ? "(array)" : (char *)y->sval, y->tval));
2241ee2e5faSnakanon if (isfunc(y)) {
2251ee2e5faSnakanon ERROR "can't use function %s as argument in %s",
2261ee2e5faSnakanon y->nval, s FATAL;
2271ee2e5faSnakanon }
2287c478bd9Sstevel@tonic-gate if (isarr(y))
2297c478bd9Sstevel@tonic-gate args[i] = y; /* arrays by ref */
2307c478bd9Sstevel@tonic-gate else
2317c478bd9Sstevel@tonic-gate args[i] = copycell(y);
2327c478bd9Sstevel@tonic-gate tempfree(y, "callargs");
2337c478bd9Sstevel@tonic-gate }
2347c478bd9Sstevel@tonic-gate for (; i < ndef; i++) { /* add null args for ones not provided */
2357c478bd9Sstevel@tonic-gate args[i] = gettemp("nullargs");
2367c478bd9Sstevel@tonic-gate *args[i] = newcopycell;
2377c478bd9Sstevel@tonic-gate }
2387c478bd9Sstevel@tonic-gate fp++; /* now ok to up frame */
2397c478bd9Sstevel@tonic-gate if (fp >= frame + nframe) {
2407c478bd9Sstevel@tonic-gate int dfp = fp - frame; /* old index */
2417c478bd9Sstevel@tonic-gate frame = (struct Frame *)
2427c478bd9Sstevel@tonic-gate realloc(frame, (nframe += 100) * sizeof (struct Frame));
2437c478bd9Sstevel@tonic-gate if (frame == NULL)
2447c478bd9Sstevel@tonic-gate ERROR "out of space for stack frames in %s", s FATAL;
2457c478bd9Sstevel@tonic-gate fp = frame + dfp;
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate fp->fcncell = fcn;
2487c478bd9Sstevel@tonic-gate fp->args = args;
2497c478bd9Sstevel@tonic-gate fp->nargs = ndef; /* number defined with (excess are locals) */
2507c478bd9Sstevel@tonic-gate fp->retval = gettemp("retval");
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate dprintf(("start exec of %s, fp=%d\n", s, fp-frame));
2531ee2e5faSnakanon /*LINTED align*/
2547c478bd9Sstevel@tonic-gate y = execute((Node *)(fcn->sval)); /* execute body */
2557c478bd9Sstevel@tonic-gate dprintf(("finished exec of %s, fp=%d\n", s, fp-frame));
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate for (i = 0; i < ndef; i++) {
2587c478bd9Sstevel@tonic-gate Cell *t = fp->args[i];
2597c478bd9Sstevel@tonic-gate if (isarr(t)) {
2607c478bd9Sstevel@tonic-gate if (t->csub == CCOPY) {
2617c478bd9Sstevel@tonic-gate if (i >= ncall) {
2627c478bd9Sstevel@tonic-gate freesymtab(t);
2637c478bd9Sstevel@tonic-gate t->csub = CTEMP;
2647c478bd9Sstevel@tonic-gate } else {
2657c478bd9Sstevel@tonic-gate oargs[i]->tval = t->tval;
2667c478bd9Sstevel@tonic-gate oargs[i]->tval &= ~(STR|NUM|DONTFREE);
2677c478bd9Sstevel@tonic-gate oargs[i]->sval = t->sval;
2687c478bd9Sstevel@tonic-gate tempfree(t, "oargsarr");
2697c478bd9Sstevel@tonic-gate }
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate } else {
2727c478bd9Sstevel@tonic-gate t->csub = CTEMP;
2737c478bd9Sstevel@tonic-gate tempfree(t, "fp->args");
2747c478bd9Sstevel@tonic-gate if (t == y) freed = 1;
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate }
2777c478bd9Sstevel@tonic-gate tempfree(fcn, "call.fcn");
2787c478bd9Sstevel@tonic-gate if (isexit(y) || isnext(y))
2791ee2e5faSnakanon return (y);
2801ee2e5faSnakanon if (!freed)
2811ee2e5faSnakanon tempfree(y, "fcn ret"); /* this can free twice! */
2827c478bd9Sstevel@tonic-gate z = fp->retval; /* return value */
2831ee2e5faSnakanon dprintf(("%s returns %g |%s| %o\n",
2841ee2e5faSnakanon s, getfval(z), getsval(z), z->tval));
2857c478bd9Sstevel@tonic-gate fp--;
2867c478bd9Sstevel@tonic-gate return (z);
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate
2891ee2e5faSnakanon static Cell *
copycell(Cell * x)2901ee2e5faSnakanon copycell(Cell *x) /* make a copy of a cell in a temp */
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate Cell *y;
2937c478bd9Sstevel@tonic-gate
2947c478bd9Sstevel@tonic-gate y = gettemp("copycell");
2957c478bd9Sstevel@tonic-gate y->csub = CCOPY; /* prevents freeing until call is over */
2967c478bd9Sstevel@tonic-gate y->nval = x->nval;
2977c478bd9Sstevel@tonic-gate y->sval = x->sval ? tostring(x->sval) : NULL;
2987c478bd9Sstevel@tonic-gate y->fval = x->fval;
2991ee2e5faSnakanon /* copy is not constant or field is DONTFREE right? */
3001ee2e5faSnakanon y->tval = x->tval & ~(CON|FLD|REC|DONTFREE);
3011ee2e5faSnakanon return (y);
3027c478bd9Sstevel@tonic-gate }
3037c478bd9Sstevel@tonic-gate
3041ee2e5faSnakanon /*ARGSUSED*/
3051ee2e5faSnakanon Cell *
arg(Node ** a,int nnn)3061ee2e5faSnakanon arg(Node **a, int nnn)
3077c478bd9Sstevel@tonic-gate {
3087c478bd9Sstevel@tonic-gate int n;
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate n = (int)a[0]; /* argument number, counting from 0 */
3117c478bd9Sstevel@tonic-gate dprintf(("arg(%d), fp->nargs=%d\n", n, fp->nargs));
3121ee2e5faSnakanon if (n+1 > fp->nargs) {
3137c478bd9Sstevel@tonic-gate ERROR "argument #%d of function %s was not supplied",
3147c478bd9Sstevel@tonic-gate n+1, fp->fcncell->nval FATAL;
3151ee2e5faSnakanon }
3161ee2e5faSnakanon return (fp->args[n]);
3177c478bd9Sstevel@tonic-gate }
3187c478bd9Sstevel@tonic-gate
3191ee2e5faSnakanon Cell *
jump(Node ** a,int n)3201ee2e5faSnakanon jump(Node **a, int n)
3217c478bd9Sstevel@tonic-gate {
3227c478bd9Sstevel@tonic-gate register Cell *y;
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate switch (n) {
3257c478bd9Sstevel@tonic-gate case EXIT:
3267c478bd9Sstevel@tonic-gate if (a[0] != NULL) {
3277c478bd9Sstevel@tonic-gate y = execute(a[0]);
32812809310Snakanon errorflag = (int)getfval(y);
3297c478bd9Sstevel@tonic-gate tempfree(y, "");
3307c478bd9Sstevel@tonic-gate }
3317c478bd9Sstevel@tonic-gate longjmp(env, 1);
3321ee2e5faSnakanon /*NOTREACHED*/
3337c478bd9Sstevel@tonic-gate case RETURN:
3347c478bd9Sstevel@tonic-gate if (a[0] != NULL) {
3357c478bd9Sstevel@tonic-gate y = execute(a[0]);
3367c478bd9Sstevel@tonic-gate if ((y->tval & (STR|NUM)) == (STR|NUM)) {
3371ee2e5faSnakanon (void) setsval(fp->retval, getsval(y));
3387c478bd9Sstevel@tonic-gate fp->retval->fval = getfval(y);
3397c478bd9Sstevel@tonic-gate fp->retval->tval |= NUM;
3401ee2e5faSnakanon } else if (y->tval & STR)
3411ee2e5faSnakanon (void) setsval(fp->retval, getsval(y));
3427c478bd9Sstevel@tonic-gate else if (y->tval & NUM)
3431ee2e5faSnakanon (void) setfval(fp->retval, getfval(y));
3447c478bd9Sstevel@tonic-gate tempfree(y, "");
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate return (jret);
3477c478bd9Sstevel@tonic-gate case NEXT:
3487c478bd9Sstevel@tonic-gate return (jnext);
3497c478bd9Sstevel@tonic-gate case BREAK:
3507c478bd9Sstevel@tonic-gate return (jbreak);
3517c478bd9Sstevel@tonic-gate case CONTINUE:
3527c478bd9Sstevel@tonic-gate return (jcont);
3537c478bd9Sstevel@tonic-gate default: /* can't happen */
3547c478bd9Sstevel@tonic-gate ERROR "illegal jump type %d", n FATAL;
3557c478bd9Sstevel@tonic-gate }
3561ee2e5faSnakanon /*NOTREACHED*/
3571ee2e5faSnakanon return (NULL);
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate
3601ee2e5faSnakanon Cell *
getaline(Node ** a,int n)361*23a1cceaSRoger A. Faulkner getaline(Node **a, int n)
3627c478bd9Sstevel@tonic-gate {
3637c478bd9Sstevel@tonic-gate /* a[0] is variable, a[1] is operator, a[2] is filename */
3647c478bd9Sstevel@tonic-gate register Cell *r, *x;
3651ee2e5faSnakanon uchar *buf;
3667c478bd9Sstevel@tonic-gate FILE *fp;
3671ee2e5faSnakanon size_t len;
3687c478bd9Sstevel@tonic-gate
3691ee2e5faSnakanon (void) fflush(stdout); /* in case someone is waiting for a prompt */
3707c478bd9Sstevel@tonic-gate r = gettemp("");
3717c478bd9Sstevel@tonic-gate if (a[1] != NULL) { /* getline < file */
3727c478bd9Sstevel@tonic-gate x = execute(a[2]); /* filename */
3737c478bd9Sstevel@tonic-gate if ((int)a[1] == '|') /* input pipe */
3747c478bd9Sstevel@tonic-gate a[1] = (Node *)LE; /* arbitrary flag */
3757c478bd9Sstevel@tonic-gate fp = openfile((int)a[1], getsval(x));
3767c478bd9Sstevel@tonic-gate tempfree(x, "");
3771ee2e5faSnakanon buf = NULL;
3787c478bd9Sstevel@tonic-gate if (fp == NULL)
3797c478bd9Sstevel@tonic-gate n = -1;
3807c478bd9Sstevel@tonic-gate else
3811ee2e5faSnakanon n = readrec(&buf, &len, fp);
3821ee2e5faSnakanon if (n > 0) {
3831ee2e5faSnakanon if (a[0] != NULL) { /* getline var <file */
3841ee2e5faSnakanon (void) setsval(execute(a[0]), buf);
3857c478bd9Sstevel@tonic-gate } else { /* getline <file */
3867c478bd9Sstevel@tonic-gate if (!(recloc->tval & DONTFREE))
3877c478bd9Sstevel@tonic-gate xfree(recloc->sval);
3881ee2e5faSnakanon expand_buf(&record, &record_size, len);
3891ee2e5faSnakanon (void) memcpy(record, buf, len);
3901ee2e5faSnakanon record[len] = '\0';
3917c478bd9Sstevel@tonic-gate recloc->sval = record;
3927c478bd9Sstevel@tonic-gate recloc->tval = REC | STR | DONTFREE;
3937c478bd9Sstevel@tonic-gate donerec = 1; donefld = 0;
3947c478bd9Sstevel@tonic-gate }
3951ee2e5faSnakanon }
3961ee2e5faSnakanon if (buf != NULL)
3971ee2e5faSnakanon free(buf);
3987c478bd9Sstevel@tonic-gate } else { /* bare getline; use current input */
3997c478bd9Sstevel@tonic-gate if (a[0] == NULL) /* getline */
4001ee2e5faSnakanon n = getrec(&record, &record_size);
4017c478bd9Sstevel@tonic-gate else { /* getline var */
4021ee2e5faSnakanon init_buf(&buf, &len, LINE_INCR);
4031ee2e5faSnakanon n = getrec(&buf, &len);
4041ee2e5faSnakanon (void) setsval(execute(a[0]), buf);
4051ee2e5faSnakanon free(buf);
4067c478bd9Sstevel@tonic-gate }
4077c478bd9Sstevel@tonic-gate }
4081ee2e5faSnakanon (void) setfval(r, (Awkfloat)n);
4091ee2e5faSnakanon return (r);
4107c478bd9Sstevel@tonic-gate }
4117c478bd9Sstevel@tonic-gate
4121ee2e5faSnakanon /*ARGSUSED*/
4131ee2e5faSnakanon Cell *
getnf(Node ** a,int n)4141ee2e5faSnakanon getnf(Node **a, int n)
4157c478bd9Sstevel@tonic-gate {
4167c478bd9Sstevel@tonic-gate if (donefld == 0)
4177c478bd9Sstevel@tonic-gate fldbld();
4181ee2e5faSnakanon return ((Cell *)a[0]);
4197c478bd9Sstevel@tonic-gate }
4207c478bd9Sstevel@tonic-gate
4211ee2e5faSnakanon /*ARGSUSED*/
4221ee2e5faSnakanon Cell *
array(Node ** a,int n)4231ee2e5faSnakanon array(Node **a, int n)
4247c478bd9Sstevel@tonic-gate {
4257c478bd9Sstevel@tonic-gate register Cell *x, *y, *z;
4267c478bd9Sstevel@tonic-gate register uchar *s;
4277c478bd9Sstevel@tonic-gate register Node *np;
4281ee2e5faSnakanon uchar *buf;
4291ee2e5faSnakanon size_t bsize, tlen, len, slen;
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate x = execute(a[0]); /* Cell* for symbol table */
4321ee2e5faSnakanon init_buf(&buf, &bsize, LINE_INCR);
4331ee2e5faSnakanon buf[0] = '\0';
4341ee2e5faSnakanon tlen = 0;
4351ee2e5faSnakanon slen = strlen((char *)*SUBSEP);
4367c478bd9Sstevel@tonic-gate for (np = a[1]; np; np = np->nnext) {
4377c478bd9Sstevel@tonic-gate y = execute(np); /* subscript */
4387c478bd9Sstevel@tonic-gate s = getsval(y);
4391ee2e5faSnakanon len = strlen((char *)s);
4401ee2e5faSnakanon expand_buf(&buf, &bsize, tlen + len + slen);
4411ee2e5faSnakanon (void) memcpy(&buf[tlen], s, len);
4421ee2e5faSnakanon tlen += len;
4431ee2e5faSnakanon if (np->nnext) {
4441ee2e5faSnakanon (void) memcpy(&buf[tlen], *SUBSEP, slen);
4451ee2e5faSnakanon tlen += slen;
4461ee2e5faSnakanon }
4471ee2e5faSnakanon buf[tlen] = '\0';
4487c478bd9Sstevel@tonic-gate tempfree(y, "");
4497c478bd9Sstevel@tonic-gate }
4507c478bd9Sstevel@tonic-gate if (!isarr(x)) {
4517c478bd9Sstevel@tonic-gate dprintf(("making %s into an array\n", x->nval));
4527c478bd9Sstevel@tonic-gate if (freeable(x))
4537c478bd9Sstevel@tonic-gate xfree(x->sval);
4547c478bd9Sstevel@tonic-gate x->tval &= ~(STR|NUM|DONTFREE);
4557c478bd9Sstevel@tonic-gate x->tval |= ARR;
4567c478bd9Sstevel@tonic-gate x->sval = (uchar *) makesymtab(NSYMTAB);
4577c478bd9Sstevel@tonic-gate }
4581ee2e5faSnakanon /*LINTED align*/
4591ee2e5faSnakanon z = setsymtab(buf, (uchar *)"", 0.0, STR|NUM, (Array *)x->sval);
4607c478bd9Sstevel@tonic-gate z->ctype = OCELL;
4617c478bd9Sstevel@tonic-gate z->csub = CVAR;
4627c478bd9Sstevel@tonic-gate tempfree(x, "");
4631ee2e5faSnakanon free(buf);
4647c478bd9Sstevel@tonic-gate return (z);
4657c478bd9Sstevel@tonic-gate }
4667c478bd9Sstevel@tonic-gate
4671ee2e5faSnakanon /*ARGSUSED*/
4681ee2e5faSnakanon Cell *
delete(Node ** a,int n)4691ee2e5faSnakanon delete(Node **a, int n)
4707c478bd9Sstevel@tonic-gate {
4717c478bd9Sstevel@tonic-gate Cell *x, *y;
4727c478bd9Sstevel@tonic-gate Node *np;
4731ee2e5faSnakanon uchar *buf, *s;
4741ee2e5faSnakanon size_t bsize, tlen, slen, len;
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate x = execute(a[0]); /* Cell* for symbol table */
4777c478bd9Sstevel@tonic-gate if (!isarr(x))
4781ee2e5faSnakanon return (true);
4791ee2e5faSnakanon init_buf(&buf, &bsize, LINE_INCR);
4801ee2e5faSnakanon buf[0] = '\0';
4811ee2e5faSnakanon tlen = 0;
4821ee2e5faSnakanon slen = strlen((char *)*SUBSEP);
4837c478bd9Sstevel@tonic-gate for (np = a[1]; np; np = np->nnext) {
4847c478bd9Sstevel@tonic-gate y = execute(np); /* subscript */
4857c478bd9Sstevel@tonic-gate s = getsval(y);
4861ee2e5faSnakanon len = strlen((char *)s);
4871ee2e5faSnakanon expand_buf(&buf, &bsize, tlen + len + slen);
4881ee2e5faSnakanon (void) memcpy(&buf[tlen], s, len);
4891ee2e5faSnakanon tlen += len;
4901ee2e5faSnakanon if (np->nnext) {
4911ee2e5faSnakanon (void) memcpy(&buf[tlen], *SUBSEP, slen);
4921ee2e5faSnakanon tlen += slen;
4931ee2e5faSnakanon }
4941ee2e5faSnakanon buf[tlen] = '\0';
4957c478bd9Sstevel@tonic-gate tempfree(y, "");
4967c478bd9Sstevel@tonic-gate }
4977c478bd9Sstevel@tonic-gate freeelem(x, buf);
4987c478bd9Sstevel@tonic-gate tempfree(x, "");
4991ee2e5faSnakanon free(buf);
5001ee2e5faSnakanon return (true);
5017c478bd9Sstevel@tonic-gate }
5027c478bd9Sstevel@tonic-gate
5031ee2e5faSnakanon /*ARGSUSED*/
5041ee2e5faSnakanon Cell *
intest(Node ** a,int n)5051ee2e5faSnakanon intest(Node **a, int n)
5067c478bd9Sstevel@tonic-gate {
5077c478bd9Sstevel@tonic-gate register Cell *x, *ap, *k;
5087c478bd9Sstevel@tonic-gate Node *p;
5091ee2e5faSnakanon uchar *buf;
5107c478bd9Sstevel@tonic-gate uchar *s;
5111ee2e5faSnakanon size_t bsize, tlen, slen, len;
5127c478bd9Sstevel@tonic-gate
5137c478bd9Sstevel@tonic-gate ap = execute(a[1]); /* array name */
5147c478bd9Sstevel@tonic-gate if (!isarr(ap))
5157c478bd9Sstevel@tonic-gate ERROR "%s is not an array", ap->nval FATAL;
5161ee2e5faSnakanon init_buf(&buf, &bsize, LINE_INCR);
5177c478bd9Sstevel@tonic-gate buf[0] = 0;
5181ee2e5faSnakanon tlen = 0;
5191ee2e5faSnakanon slen = strlen((char *)*SUBSEP);
5207c478bd9Sstevel@tonic-gate for (p = a[0]; p; p = p->nnext) {
5217c478bd9Sstevel@tonic-gate x = execute(p); /* expr */
5227c478bd9Sstevel@tonic-gate s = getsval(x);
5231ee2e5faSnakanon len = strlen((char *)s);
5241ee2e5faSnakanon expand_buf(&buf, &bsize, tlen + len + slen);
5251ee2e5faSnakanon (void) memcpy(&buf[tlen], s, len);
5261ee2e5faSnakanon tlen += len;
5277c478bd9Sstevel@tonic-gate tempfree(x, "");
5281ee2e5faSnakanon if (p->nnext) {
5291ee2e5faSnakanon (void) memcpy(&buf[tlen], *SUBSEP, slen);
5301ee2e5faSnakanon tlen += slen;
5317c478bd9Sstevel@tonic-gate }
5321ee2e5faSnakanon buf[tlen] = '\0';
5331ee2e5faSnakanon }
5341ee2e5faSnakanon /*LINTED align*/
5357c478bd9Sstevel@tonic-gate k = lookup(buf, (Array *)ap->sval);
5367c478bd9Sstevel@tonic-gate tempfree(ap, "");
5371ee2e5faSnakanon free(buf);
5387c478bd9Sstevel@tonic-gate if (k == NULL)
5397c478bd9Sstevel@tonic-gate return (false);
5407c478bd9Sstevel@tonic-gate else
5417c478bd9Sstevel@tonic-gate return (true);
5427c478bd9Sstevel@tonic-gate }
5437c478bd9Sstevel@tonic-gate
5447c478bd9Sstevel@tonic-gate
5451ee2e5faSnakanon Cell *
matchop(Node ** a,int n)5461ee2e5faSnakanon matchop(Node **a, int n)
5477c478bd9Sstevel@tonic-gate {
5487c478bd9Sstevel@tonic-gate register Cell *x, *y;
5497c478bd9Sstevel@tonic-gate register uchar *s, *t;
5507c478bd9Sstevel@tonic-gate register int i;
5517c478bd9Sstevel@tonic-gate fa *pfa;
5527c478bd9Sstevel@tonic-gate int (*mf)() = match, mode = 0;
5537c478bd9Sstevel@tonic-gate
5547c478bd9Sstevel@tonic-gate if (n == MATCHFCN) {
5557c478bd9Sstevel@tonic-gate mf = pmatch;
5567c478bd9Sstevel@tonic-gate mode = 1;
5577c478bd9Sstevel@tonic-gate }
5587c478bd9Sstevel@tonic-gate x = execute(a[1]);
5597c478bd9Sstevel@tonic-gate s = getsval(x);
5607c478bd9Sstevel@tonic-gate if (a[0] == 0)
5617c478bd9Sstevel@tonic-gate i = (*mf)(a[2], s);
5627c478bd9Sstevel@tonic-gate else {
5637c478bd9Sstevel@tonic-gate y = execute(a[2]);
5647c478bd9Sstevel@tonic-gate t = getsval(y);
5657c478bd9Sstevel@tonic-gate pfa = makedfa(t, mode);
5667c478bd9Sstevel@tonic-gate i = (*mf)(pfa, s);
5677c478bd9Sstevel@tonic-gate tempfree(y, "");
5687c478bd9Sstevel@tonic-gate }
5697c478bd9Sstevel@tonic-gate tempfree(x, "");
5707c478bd9Sstevel@tonic-gate if (n == MATCHFCN) {
5717c478bd9Sstevel@tonic-gate int start = patbeg - s + 1;
5727c478bd9Sstevel@tonic-gate if (patlen < 0)
5737c478bd9Sstevel@tonic-gate start = 0;
5741ee2e5faSnakanon (void) setfval(rstartloc, (Awkfloat)start);
5751ee2e5faSnakanon (void) setfval(rlengthloc, (Awkfloat)patlen);
5767c478bd9Sstevel@tonic-gate x = gettemp("");
5777c478bd9Sstevel@tonic-gate x->tval = NUM;
5787c478bd9Sstevel@tonic-gate x->fval = start;
5791ee2e5faSnakanon return (x);
5807c478bd9Sstevel@tonic-gate } else if (n == MATCH && i == 1 || n == NOTMATCH && i == 0)
5817c478bd9Sstevel@tonic-gate return (true);
5827c478bd9Sstevel@tonic-gate else
5837c478bd9Sstevel@tonic-gate return (false);
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate
5867c478bd9Sstevel@tonic-gate
5871ee2e5faSnakanon Cell *
boolop(Node ** a,int n)5881ee2e5faSnakanon boolop(Node **a, int n)
5897c478bd9Sstevel@tonic-gate {
5907c478bd9Sstevel@tonic-gate register Cell *x, *y;
5917c478bd9Sstevel@tonic-gate register int i;
5927c478bd9Sstevel@tonic-gate
5937c478bd9Sstevel@tonic-gate x = execute(a[0]);
5947c478bd9Sstevel@tonic-gate i = istrue(x);
5957c478bd9Sstevel@tonic-gate tempfree(x, "");
5967c478bd9Sstevel@tonic-gate switch (n) {
5977c478bd9Sstevel@tonic-gate case BOR:
5981ee2e5faSnakanon if (i)
5991ee2e5faSnakanon return (true);
6007c478bd9Sstevel@tonic-gate y = execute(a[1]);
6017c478bd9Sstevel@tonic-gate i = istrue(y);
6027c478bd9Sstevel@tonic-gate tempfree(y, "");
6031ee2e5faSnakanon return (i ? true : false);
6047c478bd9Sstevel@tonic-gate case AND:
6051ee2e5faSnakanon if (!i)
6061ee2e5faSnakanon return (false);
6077c478bd9Sstevel@tonic-gate y = execute(a[1]);
6087c478bd9Sstevel@tonic-gate i = istrue(y);
6097c478bd9Sstevel@tonic-gate tempfree(y, "");
6101ee2e5faSnakanon return (i ? true : false);
6117c478bd9Sstevel@tonic-gate case NOT:
6121ee2e5faSnakanon return (i ? false : true);
6137c478bd9Sstevel@tonic-gate default: /* can't happen */
6147c478bd9Sstevel@tonic-gate ERROR "unknown boolean operator %d", n FATAL;
6157c478bd9Sstevel@tonic-gate }
6167c478bd9Sstevel@tonic-gate /*NOTREACHED*/
6171ee2e5faSnakanon return (NULL);
6187c478bd9Sstevel@tonic-gate }
6197c478bd9Sstevel@tonic-gate
6201ee2e5faSnakanon Cell *
relop(Node ** a,int n)6211ee2e5faSnakanon relop(Node **a, int n)
6227c478bd9Sstevel@tonic-gate {
6237c478bd9Sstevel@tonic-gate register int i;
6247c478bd9Sstevel@tonic-gate register Cell *x, *y;
6257c478bd9Sstevel@tonic-gate Awkfloat j;
6267c478bd9Sstevel@tonic-gate
6277c478bd9Sstevel@tonic-gate x = execute(a[0]);
6287c478bd9Sstevel@tonic-gate y = execute(a[1]);
6297c478bd9Sstevel@tonic-gate if (x->tval&NUM && y->tval&NUM) {
6307c478bd9Sstevel@tonic-gate j = x->fval - y->fval;
6317c478bd9Sstevel@tonic-gate i = j < 0 ? -1: (j > 0 ? 1: 0);
6327c478bd9Sstevel@tonic-gate } else {
6331ee2e5faSnakanon i = strcmp((char *)getsval(x), (char *)getsval(y));
6347c478bd9Sstevel@tonic-gate }
6357c478bd9Sstevel@tonic-gate tempfree(x, "");
6367c478bd9Sstevel@tonic-gate tempfree(y, "");
6377c478bd9Sstevel@tonic-gate switch (n) {
6381ee2e5faSnakanon case LT: return (i < 0 ? true : false);
6391ee2e5faSnakanon case LE: return (i <= 0 ? true : false);
6401ee2e5faSnakanon case NE: return (i != 0 ? true : false);
6411ee2e5faSnakanon case EQ: return (i == 0 ? true : false);
6421ee2e5faSnakanon case GE: return (i >= 0 ? true : false);
6431ee2e5faSnakanon case GT: return (i > 0 ? true : false);
6447c478bd9Sstevel@tonic-gate default: /* can't happen */
6457c478bd9Sstevel@tonic-gate ERROR "unknown relational operator %d", n FATAL;
6467c478bd9Sstevel@tonic-gate }
6477c478bd9Sstevel@tonic-gate /*NOTREACHED*/
6481ee2e5faSnakanon return (false);
6497c478bd9Sstevel@tonic-gate }
6507c478bd9Sstevel@tonic-gate
6511ee2e5faSnakanon static void
tfree(Cell * a,char * s)6521ee2e5faSnakanon tfree(Cell *a, char *s)
6537c478bd9Sstevel@tonic-gate {
6541ee2e5faSnakanon if (dbg > 1) {
6551ee2e5faSnakanon (void) printf("## tfree %.8s %06lo %s\n",
6561ee2e5faSnakanon s, (ulong_t)a, a->sval ? a->sval : (uchar *)"");
6571ee2e5faSnakanon }
6587c478bd9Sstevel@tonic-gate if (freeable(a))
6597c478bd9Sstevel@tonic-gate xfree(a->sval);
6607c478bd9Sstevel@tonic-gate if (a == tmps)
6617c478bd9Sstevel@tonic-gate ERROR "tempcell list is curdled" FATAL;
6627c478bd9Sstevel@tonic-gate a->cnext = tmps;
6637c478bd9Sstevel@tonic-gate tmps = a;
6647c478bd9Sstevel@tonic-gate }
6657c478bd9Sstevel@tonic-gate
6661ee2e5faSnakanon static Cell *
gettemp(char * s)6671ee2e5faSnakanon gettemp(char *s)
6681ee2e5faSnakanon {
6691ee2e5faSnakanon int i;
6707c478bd9Sstevel@tonic-gate register Cell *x;
6717c478bd9Sstevel@tonic-gate
6727c478bd9Sstevel@tonic-gate if (!tmps) {
6737c478bd9Sstevel@tonic-gate tmps = (Cell *)calloc(100, sizeof (Cell));
6747c478bd9Sstevel@tonic-gate if (!tmps)
6757c478bd9Sstevel@tonic-gate ERROR "no space for temporaries" FATAL;
6767c478bd9Sstevel@tonic-gate for (i = 1; i < 100; i++)
6777c478bd9Sstevel@tonic-gate tmps[i-1].cnext = &tmps[i];
6787c478bd9Sstevel@tonic-gate tmps[i-1].cnext = 0;
6797c478bd9Sstevel@tonic-gate }
6807c478bd9Sstevel@tonic-gate x = tmps;
6817c478bd9Sstevel@tonic-gate tmps = x->cnext;
6827c478bd9Sstevel@tonic-gate *x = tempcell;
6831ee2e5faSnakanon if (dbg > 1)
6841ee2e5faSnakanon (void) printf("## gtemp %.8s %06lo\n", s, (ulong_t)x);
6857c478bd9Sstevel@tonic-gate return (x);
6867c478bd9Sstevel@tonic-gate }
6877c478bd9Sstevel@tonic-gate
6881ee2e5faSnakanon /*ARGSUSED*/
6891ee2e5faSnakanon Cell *
indirect(Node ** a,int n)6901ee2e5faSnakanon indirect(Node **a, int n)
6917c478bd9Sstevel@tonic-gate {
6927c478bd9Sstevel@tonic-gate register Cell *x;
6937c478bd9Sstevel@tonic-gate register int m;
6947c478bd9Sstevel@tonic-gate register uchar *s;
6957c478bd9Sstevel@tonic-gate
6967c478bd9Sstevel@tonic-gate x = execute(a[0]);
69712809310Snakanon m = (int)getfval(x);
6981ee2e5faSnakanon if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */
6997c478bd9Sstevel@tonic-gate ERROR "illegal field $(%s)", s FATAL;
7007c478bd9Sstevel@tonic-gate tempfree(x, "");
7017c478bd9Sstevel@tonic-gate x = fieldadr(m);
7027c478bd9Sstevel@tonic-gate x->ctype = OCELL;
7037c478bd9Sstevel@tonic-gate x->csub = CFLD;
7047c478bd9Sstevel@tonic-gate return (x);
7057c478bd9Sstevel@tonic-gate }
7067c478bd9Sstevel@tonic-gate
7071ee2e5faSnakanon /*ARGSUSED*/
7081ee2e5faSnakanon Cell *
substr(Node ** a,int nnn)7091ee2e5faSnakanon substr(Node **a, int nnn)
7107c478bd9Sstevel@tonic-gate {
7117c478bd9Sstevel@tonic-gate register int k, m, n;
7127c478bd9Sstevel@tonic-gate register uchar *s;
7137c478bd9Sstevel@tonic-gate int temp;
7147c478bd9Sstevel@tonic-gate register Cell *x, *y, *z;
7157c478bd9Sstevel@tonic-gate
7167c478bd9Sstevel@tonic-gate x = execute(a[0]);
7177c478bd9Sstevel@tonic-gate y = execute(a[1]);
7187c478bd9Sstevel@tonic-gate if (a[2] != 0)
7197c478bd9Sstevel@tonic-gate z = execute(a[2]);
7207c478bd9Sstevel@tonic-gate s = getsval(x);
7211ee2e5faSnakanon k = strlen((char *)s) + 1;
7227c478bd9Sstevel@tonic-gate if (k <= 1) {
7237c478bd9Sstevel@tonic-gate tempfree(x, "");
7247c478bd9Sstevel@tonic-gate tempfree(y, "");
7257c478bd9Sstevel@tonic-gate if (a[2] != 0)
7267c478bd9Sstevel@tonic-gate tempfree(z, "");
7277c478bd9Sstevel@tonic-gate x = gettemp("");
7281ee2e5faSnakanon (void) setsval(x, (uchar *)"");
7297c478bd9Sstevel@tonic-gate return (x);
7307c478bd9Sstevel@tonic-gate }
73112809310Snakanon m = (int)getfval(y);
7327c478bd9Sstevel@tonic-gate if (m <= 0)
7337c478bd9Sstevel@tonic-gate m = 1;
7347c478bd9Sstevel@tonic-gate else if (m > k)
7357c478bd9Sstevel@tonic-gate m = k;
7367c478bd9Sstevel@tonic-gate tempfree(y, "");
7377c478bd9Sstevel@tonic-gate if (a[2] != 0) {
73812809310Snakanon n = (int)getfval(z);
7397c478bd9Sstevel@tonic-gate tempfree(z, "");
7407c478bd9Sstevel@tonic-gate } else
7417c478bd9Sstevel@tonic-gate n = k - 1;
7427c478bd9Sstevel@tonic-gate if (n < 0)
7437c478bd9Sstevel@tonic-gate n = 0;
7447c478bd9Sstevel@tonic-gate else if (n > k - m)
7457c478bd9Sstevel@tonic-gate n = k - m;
7467c478bd9Sstevel@tonic-gate dprintf(("substr: m=%d, n=%d, s=%s\n", m, n, s));
7477c478bd9Sstevel@tonic-gate y = gettemp("");
7487c478bd9Sstevel@tonic-gate temp = s[n + m - 1]; /* with thanks to John Linderman */
7497c478bd9Sstevel@tonic-gate s[n + m - 1] = '\0';
7501ee2e5faSnakanon (void) setsval(y, s + m - 1);
7517c478bd9Sstevel@tonic-gate s[n + m - 1] = temp;
7527c478bd9Sstevel@tonic-gate tempfree(x, "");
7537c478bd9Sstevel@tonic-gate return (y);
7547c478bd9Sstevel@tonic-gate }
7557c478bd9Sstevel@tonic-gate
7561ee2e5faSnakanon /*ARGSUSED*/
7571ee2e5faSnakanon Cell *
sindex(Node ** a,int nnn)7581ee2e5faSnakanon sindex(Node **a, int nnn)
7597c478bd9Sstevel@tonic-gate {
7607c478bd9Sstevel@tonic-gate register Cell *x, *y, *z;
7617c478bd9Sstevel@tonic-gate register uchar *s1, *s2, *p1, *p2, *q;
7627c478bd9Sstevel@tonic-gate Awkfloat v = 0.0;
7637c478bd9Sstevel@tonic-gate
7647c478bd9Sstevel@tonic-gate x = execute(a[0]);
7657c478bd9Sstevel@tonic-gate s1 = getsval(x);
7667c478bd9Sstevel@tonic-gate y = execute(a[1]);
7677c478bd9Sstevel@tonic-gate s2 = getsval(y);
7687c478bd9Sstevel@tonic-gate
7697c478bd9Sstevel@tonic-gate z = gettemp("");
7707c478bd9Sstevel@tonic-gate for (p1 = s1; *p1 != '\0'; p1++) {
7717c478bd9Sstevel@tonic-gate for (q = p1, p2 = s2; *p2 != '\0' && *q == *p2; q++, p2++)
7727c478bd9Sstevel@tonic-gate ;
7737c478bd9Sstevel@tonic-gate if (*p2 == '\0') {
7747c478bd9Sstevel@tonic-gate v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */
7757c478bd9Sstevel@tonic-gate break;
7767c478bd9Sstevel@tonic-gate }
7777c478bd9Sstevel@tonic-gate }
7787c478bd9Sstevel@tonic-gate tempfree(x, "");
7797c478bd9Sstevel@tonic-gate tempfree(y, "");
7801ee2e5faSnakanon (void) setfval(z, v);
7817c478bd9Sstevel@tonic-gate return (z);
7827c478bd9Sstevel@tonic-gate }
7837c478bd9Sstevel@tonic-gate
7841ee2e5faSnakanon void
format(uchar ** bufp,uchar * s,Node * a)7851ee2e5faSnakanon format(uchar **bufp, uchar *s, Node *a)
7867c478bd9Sstevel@tonic-gate {
7871ee2e5faSnakanon uchar *fmt;
7881ee2e5faSnakanon register uchar *os;
7897c478bd9Sstevel@tonic-gate register Cell *x;
7901ee2e5faSnakanon int flag = 0, len;
7911ee2e5faSnakanon uchar_t *buf;
7921ee2e5faSnakanon size_t bufsize, fmtsize, cnt, tcnt, ret;
7937c478bd9Sstevel@tonic-gate
7941ee2e5faSnakanon init_buf(&buf, &bufsize, LINE_INCR);
7951ee2e5faSnakanon init_buf(&fmt, &fmtsize, LINE_INCR);
7967c478bd9Sstevel@tonic-gate os = s;
7971ee2e5faSnakanon cnt = 0;
7987c478bd9Sstevel@tonic-gate while (*s) {
7997c478bd9Sstevel@tonic-gate if (*s != '%') {
8001ee2e5faSnakanon expand_buf(&buf, &bufsize, cnt);
8011ee2e5faSnakanon buf[cnt++] = *s++;
8027c478bd9Sstevel@tonic-gate continue;
8037c478bd9Sstevel@tonic-gate }
8047c478bd9Sstevel@tonic-gate if (*(s+1) == '%') {
8051ee2e5faSnakanon expand_buf(&buf, &bufsize, cnt);
8061ee2e5faSnakanon buf[cnt++] = '%';
8077c478bd9Sstevel@tonic-gate s += 2;
8087c478bd9Sstevel@tonic-gate continue;
8097c478bd9Sstevel@tonic-gate }
8101ee2e5faSnakanon for (tcnt = 0; ; s++) {
8111ee2e5faSnakanon expand_buf(&fmt, &fmtsize, tcnt);
8121ee2e5faSnakanon fmt[tcnt++] = *s;
8131ee2e5faSnakanon if (*s == '\0')
8141ee2e5faSnakanon break;
8157c478bd9Sstevel@tonic-gate if (isalpha(*s) && *s != 'l' && *s != 'h' && *s != 'L')
8167c478bd9Sstevel@tonic-gate break; /* the ansi panoply */
8177c478bd9Sstevel@tonic-gate if (*s == '*') {
8187c478bd9Sstevel@tonic-gate if (a == NULL) {
8197c478bd9Sstevel@tonic-gate ERROR
8207c478bd9Sstevel@tonic-gate "not enough args in printf(%s) or sprintf(%s)", os, os FATAL;
8217c478bd9Sstevel@tonic-gate }
8227c478bd9Sstevel@tonic-gate x = execute(a);
8237c478bd9Sstevel@tonic-gate a = a->nnext;
8241ee2e5faSnakanon tcnt--;
8251ee2e5faSnakanon expand_buf(&fmt, &fmtsize, tcnt + 12);
8261ee2e5faSnakanon ret = sprintf((char *)&fmt[tcnt], "%d",
8271ee2e5faSnakanon (int)getfval(x));
8281ee2e5faSnakanon tcnt += ret;
8297c478bd9Sstevel@tonic-gate tempfree(x, "");
8307c478bd9Sstevel@tonic-gate }
8317c478bd9Sstevel@tonic-gate }
8321ee2e5faSnakanon fmt[tcnt] = '\0';
8331ee2e5faSnakanon
8347c478bd9Sstevel@tonic-gate switch (*s) {
8357c478bd9Sstevel@tonic-gate case 'f': case 'e': case 'g': case 'E': case 'G':
8367c478bd9Sstevel@tonic-gate flag = 1;
8377c478bd9Sstevel@tonic-gate break;
8387c478bd9Sstevel@tonic-gate case 'd': case 'i':
8397c478bd9Sstevel@tonic-gate flag = 2;
8401ee2e5faSnakanon if (*(s-1) == 'l')
8411ee2e5faSnakanon break;
8421ee2e5faSnakanon fmt[tcnt - 1] = 'l';
8431ee2e5faSnakanon expand_buf(&fmt, &fmtsize, tcnt);
8441ee2e5faSnakanon fmt[tcnt++] = 'd';
8451ee2e5faSnakanon fmt[tcnt] = '\0';
8467c478bd9Sstevel@tonic-gate break;
8477c478bd9Sstevel@tonic-gate case 'o': case 'x': case 'X': case 'u':
8487c478bd9Sstevel@tonic-gate flag = *(s-1) == 'l' ? 2 : 3;
8497c478bd9Sstevel@tonic-gate break;
8507c478bd9Sstevel@tonic-gate case 's':
8517c478bd9Sstevel@tonic-gate flag = 4;
8527c478bd9Sstevel@tonic-gate break;
8537c478bd9Sstevel@tonic-gate case 'c':
8547c478bd9Sstevel@tonic-gate flag = 5;
8557c478bd9Sstevel@tonic-gate break;
8567c478bd9Sstevel@tonic-gate default:
8577c478bd9Sstevel@tonic-gate flag = 0;
8587c478bd9Sstevel@tonic-gate break;
8597c478bd9Sstevel@tonic-gate }
8607c478bd9Sstevel@tonic-gate if (flag == 0) {
8611ee2e5faSnakanon len = strlen((char *)fmt);
8621ee2e5faSnakanon expand_buf(&buf, &bufsize, cnt + len);
8631ee2e5faSnakanon (void) memcpy(&buf[cnt], fmt, len);
8641ee2e5faSnakanon cnt += len;
8651ee2e5faSnakanon buf[cnt] = '\0';
8667c478bd9Sstevel@tonic-gate continue;
8677c478bd9Sstevel@tonic-gate }
8687c478bd9Sstevel@tonic-gate if (a == NULL) {
8697c478bd9Sstevel@tonic-gate ERROR
8707c478bd9Sstevel@tonic-gate "not enough args in printf(%s) or sprintf(%s)", os, os FATAL;
8717c478bd9Sstevel@tonic-gate }
8727c478bd9Sstevel@tonic-gate x = execute(a);
8737c478bd9Sstevel@tonic-gate a = a->nnext;
8741ee2e5faSnakanon for (;;) {
8751ee2e5faSnakanon /* make sure we have at least 1 byte space */
8761ee2e5faSnakanon expand_buf(&buf, &bufsize, cnt + 1);
8771ee2e5faSnakanon len = bufsize - cnt;
8787c478bd9Sstevel@tonic-gate switch (flag) {
8791ee2e5faSnakanon case 1:
8801ee2e5faSnakanon /*LINTED*/
8811ee2e5faSnakanon ret = snprintf((char *)&buf[cnt], len,
8821ee2e5faSnakanon (char *)fmt, getfval(x));
8837c478bd9Sstevel@tonic-gate break;
8841ee2e5faSnakanon case 2:
8851ee2e5faSnakanon /*LINTED*/
8861ee2e5faSnakanon ret = snprintf((char *)&buf[cnt], len,
8871ee2e5faSnakanon (char *)fmt, (long)getfval(x));
8881ee2e5faSnakanon break;
8891ee2e5faSnakanon case 3:
8901ee2e5faSnakanon /*LINTED*/
8911ee2e5faSnakanon ret = snprintf((char *)&buf[cnt], len,
8921ee2e5faSnakanon (char *)fmt, (int)getfval(x));
8931ee2e5faSnakanon break;
8941ee2e5faSnakanon case 4:
8951ee2e5faSnakanon /*LINTED*/
8961ee2e5faSnakanon ret = snprintf((char *)&buf[cnt], len,
8971ee2e5faSnakanon (char *)fmt, getsval(x));
8981ee2e5faSnakanon break;
8991ee2e5faSnakanon case 5:
9001ee2e5faSnakanon if (isnum(x)) {
9011ee2e5faSnakanon /*LINTED*/
9021ee2e5faSnakanon ret = snprintf((char *)&buf[cnt], len,
9031ee2e5faSnakanon (char *)fmt, (int)getfval(x));
9041ee2e5faSnakanon } else {
9051ee2e5faSnakanon /*LINTED*/
9061ee2e5faSnakanon ret = snprintf((char *)&buf[cnt], len,
9071ee2e5faSnakanon (char *)fmt, getsval(x)[0]);
9081ee2e5faSnakanon }
9091ee2e5faSnakanon break;
9101ee2e5faSnakanon default:
9111ee2e5faSnakanon ret = 0;
9121ee2e5faSnakanon }
9131ee2e5faSnakanon if (ret < len)
9141ee2e5faSnakanon break;
9151ee2e5faSnakanon expand_buf(&buf, &bufsize, cnt + ret);
9167c478bd9Sstevel@tonic-gate }
9177c478bd9Sstevel@tonic-gate tempfree(x, "");
9181ee2e5faSnakanon cnt += ret;
9197c478bd9Sstevel@tonic-gate s++;
9207c478bd9Sstevel@tonic-gate }
9211ee2e5faSnakanon buf[cnt] = '\0';
9227c478bd9Sstevel@tonic-gate for (; a; a = a->nnext) /* evaluate any remaining args */
9231ee2e5faSnakanon (void) execute(a);
9241ee2e5faSnakanon *bufp = tostring(buf);
9251ee2e5faSnakanon free(buf);
9261ee2e5faSnakanon free(fmt);
9277c478bd9Sstevel@tonic-gate }
9287c478bd9Sstevel@tonic-gate
9291ee2e5faSnakanon /*ARGSUSED*/
9301ee2e5faSnakanon Cell *
a_sprintf(Node ** a,int n)931d0983205SRoger A. Faulkner a_sprintf(Node **a, int n)
9327c478bd9Sstevel@tonic-gate {
9337c478bd9Sstevel@tonic-gate register Cell *x;
9347c478bd9Sstevel@tonic-gate register Node *y;
9351ee2e5faSnakanon uchar *buf;
9367c478bd9Sstevel@tonic-gate
9377c478bd9Sstevel@tonic-gate y = a[0]->nnext;
9387c478bd9Sstevel@tonic-gate x = execute(a[0]);
9391ee2e5faSnakanon format(&buf, getsval(x), y);
9407c478bd9Sstevel@tonic-gate tempfree(x, "");
9417c478bd9Sstevel@tonic-gate x = gettemp("");
9421ee2e5faSnakanon x->sval = buf;
9437c478bd9Sstevel@tonic-gate x->tval = STR;
9447c478bd9Sstevel@tonic-gate return (x);
9457c478bd9Sstevel@tonic-gate }
9467c478bd9Sstevel@tonic-gate
9471ee2e5faSnakanon /*ARGSUSED*/
9481ee2e5faSnakanon Cell *
aprintf(Node ** a,int n)9491ee2e5faSnakanon aprintf(Node **a, int n)
9507c478bd9Sstevel@tonic-gate {
9517c478bd9Sstevel@tonic-gate FILE *fp;
9527c478bd9Sstevel@tonic-gate register Cell *x;
9537c478bd9Sstevel@tonic-gate register Node *y;
9541ee2e5faSnakanon uchar *buf;
9557c478bd9Sstevel@tonic-gate
9567c478bd9Sstevel@tonic-gate y = a[0]->nnext;
9577c478bd9Sstevel@tonic-gate x = execute(a[0]);
9581ee2e5faSnakanon format(&buf, getsval(x), y);
9597c478bd9Sstevel@tonic-gate tempfree(x, "");
9607c478bd9Sstevel@tonic-gate if (a[1] == NULL)
9611ee2e5faSnakanon (void) fputs((char *)buf, stdout);
9627c478bd9Sstevel@tonic-gate else {
9637c478bd9Sstevel@tonic-gate fp = redirect((int)a[1], a[2]);
9641ee2e5faSnakanon (void) fputs((char *)buf, fp);
9651ee2e5faSnakanon (void) fflush(fp);
9667c478bd9Sstevel@tonic-gate }
9671ee2e5faSnakanon free(buf);
9687c478bd9Sstevel@tonic-gate return (true);
9697c478bd9Sstevel@tonic-gate }
9707c478bd9Sstevel@tonic-gate
9711ee2e5faSnakanon Cell *
arith(Node ** a,int n)9721ee2e5faSnakanon arith(Node **a, int n)
9737c478bd9Sstevel@tonic-gate {
9747c478bd9Sstevel@tonic-gate Awkfloat i, j;
9751ee2e5faSnakanon double v;
9767c478bd9Sstevel@tonic-gate register Cell *x, *y, *z;
9777c478bd9Sstevel@tonic-gate
9787c478bd9Sstevel@tonic-gate x = execute(a[0]);
9797c478bd9Sstevel@tonic-gate i = getfval(x);
9807c478bd9Sstevel@tonic-gate tempfree(x, "");
9817c478bd9Sstevel@tonic-gate if (n != UMINUS) {
9827c478bd9Sstevel@tonic-gate y = execute(a[1]);
9837c478bd9Sstevel@tonic-gate j = getfval(y);
9847c478bd9Sstevel@tonic-gate tempfree(y, "");
9857c478bd9Sstevel@tonic-gate }
9867c478bd9Sstevel@tonic-gate z = gettemp("");
9877c478bd9Sstevel@tonic-gate switch (n) {
9887c478bd9Sstevel@tonic-gate case ADD:
9897c478bd9Sstevel@tonic-gate i += j;
9907c478bd9Sstevel@tonic-gate break;
9917c478bd9Sstevel@tonic-gate case MINUS:
9927c478bd9Sstevel@tonic-gate i -= j;
9937c478bd9Sstevel@tonic-gate break;
9947c478bd9Sstevel@tonic-gate case MULT:
9957c478bd9Sstevel@tonic-gate i *= j;
9967c478bd9Sstevel@tonic-gate break;
9977c478bd9Sstevel@tonic-gate case DIVIDE:
9987c478bd9Sstevel@tonic-gate if (j == 0)
9997c478bd9Sstevel@tonic-gate ERROR "division by zero" FATAL;
10007c478bd9Sstevel@tonic-gate i /= j;
10017c478bd9Sstevel@tonic-gate break;
10027c478bd9Sstevel@tonic-gate case MOD:
10037c478bd9Sstevel@tonic-gate if (j == 0)
10047c478bd9Sstevel@tonic-gate ERROR "division by zero in mod" FATAL;
10051ee2e5faSnakanon (void) modf(i/j, &v);
10067c478bd9Sstevel@tonic-gate i = i - j * v;
10077c478bd9Sstevel@tonic-gate break;
10087c478bd9Sstevel@tonic-gate case UMINUS:
10097c478bd9Sstevel@tonic-gate i = -i;
10107c478bd9Sstevel@tonic-gate break;
10117c478bd9Sstevel@tonic-gate case POWER:
10127c478bd9Sstevel@tonic-gate if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
10137c478bd9Sstevel@tonic-gate i = ipow(i, (int)j);
10147c478bd9Sstevel@tonic-gate else
10157c478bd9Sstevel@tonic-gate i = errcheck(pow(i, j), "pow");
10167c478bd9Sstevel@tonic-gate break;
10177c478bd9Sstevel@tonic-gate default: /* can't happen */
10187c478bd9Sstevel@tonic-gate ERROR "illegal arithmetic operator %d", n FATAL;
10197c478bd9Sstevel@tonic-gate }
10201ee2e5faSnakanon (void) setfval(z, i);
10217c478bd9Sstevel@tonic-gate return (z);
10227c478bd9Sstevel@tonic-gate }
10237c478bd9Sstevel@tonic-gate
10241ee2e5faSnakanon static double
ipow(double x,int n)10251ee2e5faSnakanon ipow(double x, int n)
10267c478bd9Sstevel@tonic-gate {
10277c478bd9Sstevel@tonic-gate double v;
10287c478bd9Sstevel@tonic-gate
10297c478bd9Sstevel@tonic-gate if (n <= 0)
10301ee2e5faSnakanon return (1.0);
10317c478bd9Sstevel@tonic-gate v = ipow(x, n/2);
10327c478bd9Sstevel@tonic-gate if (n % 2 == 0)
10331ee2e5faSnakanon return (v * v);
10347c478bd9Sstevel@tonic-gate else
10351ee2e5faSnakanon return (x * v * v);
10367c478bd9Sstevel@tonic-gate }
10377c478bd9Sstevel@tonic-gate
10381ee2e5faSnakanon Cell *
incrdecr(Node ** a,int n)10391ee2e5faSnakanon incrdecr(Node **a, int n)
10407c478bd9Sstevel@tonic-gate {
10417c478bd9Sstevel@tonic-gate register Cell *x, *z;
10427c478bd9Sstevel@tonic-gate register int k;
10437c478bd9Sstevel@tonic-gate Awkfloat xf;
10447c478bd9Sstevel@tonic-gate
10457c478bd9Sstevel@tonic-gate x = execute(a[0]);
10467c478bd9Sstevel@tonic-gate xf = getfval(x);
10477c478bd9Sstevel@tonic-gate k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
10487c478bd9Sstevel@tonic-gate if (n == PREINCR || n == PREDECR) {
10491ee2e5faSnakanon (void) setfval(x, xf + k);
10507c478bd9Sstevel@tonic-gate return (x);
10517c478bd9Sstevel@tonic-gate }
10527c478bd9Sstevel@tonic-gate z = gettemp("");
10531ee2e5faSnakanon (void) setfval(z, xf);
10541ee2e5faSnakanon (void) setfval(x, xf + k);
10557c478bd9Sstevel@tonic-gate tempfree(x, "");
10567c478bd9Sstevel@tonic-gate return (z);
10577c478bd9Sstevel@tonic-gate }
10587c478bd9Sstevel@tonic-gate
10591ee2e5faSnakanon Cell *
assign(Node ** a,int n)10601ee2e5faSnakanon assign(Node **a, int n)
10617c478bd9Sstevel@tonic-gate {
10627c478bd9Sstevel@tonic-gate register Cell *x, *y;
10637c478bd9Sstevel@tonic-gate Awkfloat xf, yf;
10641ee2e5faSnakanon double v;
10657c478bd9Sstevel@tonic-gate
10667c478bd9Sstevel@tonic-gate y = execute(a[1]);
10677c478bd9Sstevel@tonic-gate x = execute(a[0]); /* order reversed from before... */
10687c478bd9Sstevel@tonic-gate if (n == ASSIGN) { /* ordinary assignment */
10697c478bd9Sstevel@tonic-gate if ((y->tval & (STR|NUM)) == (STR|NUM)) {
10701ee2e5faSnakanon (void) setsval(x, getsval(y));
10717c478bd9Sstevel@tonic-gate x->fval = getfval(y);
10727c478bd9Sstevel@tonic-gate x->tval |= NUM;
10731ee2e5faSnakanon } else if (y->tval & STR)
10741ee2e5faSnakanon (void) setsval(x, getsval(y));
10757c478bd9Sstevel@tonic-gate else if (y->tval & NUM)
10761ee2e5faSnakanon (void) setfval(x, getfval(y));
10777c478bd9Sstevel@tonic-gate else
10787c478bd9Sstevel@tonic-gate funnyvar(y, "read value of");
10797c478bd9Sstevel@tonic-gate tempfree(y, "");
10807c478bd9Sstevel@tonic-gate return (x);
10817c478bd9Sstevel@tonic-gate }
10827c478bd9Sstevel@tonic-gate xf = getfval(x);
10837c478bd9Sstevel@tonic-gate yf = getfval(y);
10847c478bd9Sstevel@tonic-gate switch (n) {
10857c478bd9Sstevel@tonic-gate case ADDEQ:
10867c478bd9Sstevel@tonic-gate xf += yf;
10877c478bd9Sstevel@tonic-gate break;
10887c478bd9Sstevel@tonic-gate case SUBEQ:
10897c478bd9Sstevel@tonic-gate xf -= yf;
10907c478bd9Sstevel@tonic-gate break;
10917c478bd9Sstevel@tonic-gate case MULTEQ:
10927c478bd9Sstevel@tonic-gate xf *= yf;
10937c478bd9Sstevel@tonic-gate break;
10947c478bd9Sstevel@tonic-gate case DIVEQ:
10957c478bd9Sstevel@tonic-gate if (yf == 0)
10967c478bd9Sstevel@tonic-gate ERROR "division by zero in /=" FATAL;
10977c478bd9Sstevel@tonic-gate xf /= yf;
10987c478bd9Sstevel@tonic-gate break;
10997c478bd9Sstevel@tonic-gate case MODEQ:
11007c478bd9Sstevel@tonic-gate if (yf == 0)
11017c478bd9Sstevel@tonic-gate ERROR "division by zero in %%=" FATAL;
11021ee2e5faSnakanon (void) modf(xf/yf, &v);
11037c478bd9Sstevel@tonic-gate xf = xf - yf * v;
11047c478bd9Sstevel@tonic-gate break;
11057c478bd9Sstevel@tonic-gate case POWEQ:
11067c478bd9Sstevel@tonic-gate if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */
11077c478bd9Sstevel@tonic-gate xf = ipow(xf, (int)yf);
11087c478bd9Sstevel@tonic-gate else
11097c478bd9Sstevel@tonic-gate xf = errcheck(pow(xf, yf), "pow");
11107c478bd9Sstevel@tonic-gate break;
11117c478bd9Sstevel@tonic-gate default:
11127c478bd9Sstevel@tonic-gate ERROR "illegal assignment operator %d", n FATAL;
11137c478bd9Sstevel@tonic-gate break;
11147c478bd9Sstevel@tonic-gate }
11157c478bd9Sstevel@tonic-gate tempfree(y, "");
11161ee2e5faSnakanon (void) setfval(x, xf);
11177c478bd9Sstevel@tonic-gate return (x);
11187c478bd9Sstevel@tonic-gate }
11197c478bd9Sstevel@tonic-gate
11201ee2e5faSnakanon /*ARGSUSED*/
11211ee2e5faSnakanon Cell *
cat(Node ** a,int q)11221ee2e5faSnakanon cat(Node **a, int q)
11237c478bd9Sstevel@tonic-gate {
11247c478bd9Sstevel@tonic-gate register Cell *x, *y, *z;
11257c478bd9Sstevel@tonic-gate register int n1, n2;
11267c478bd9Sstevel@tonic-gate register uchar *s;
11277c478bd9Sstevel@tonic-gate
11287c478bd9Sstevel@tonic-gate x = execute(a[0]);
11297c478bd9Sstevel@tonic-gate y = execute(a[1]);
11301ee2e5faSnakanon (void) getsval(x);
11311ee2e5faSnakanon (void) getsval(y);
11321ee2e5faSnakanon n1 = strlen((char *)x->sval);
11331ee2e5faSnakanon n2 = strlen((char *)y->sval);
11347c478bd9Sstevel@tonic-gate s = (uchar *)malloc(n1 + n2 + 1);
11351ee2e5faSnakanon if (s == NULL) {
11367c478bd9Sstevel@tonic-gate ERROR "out of space concatenating %.15s and %.15s",
11377c478bd9Sstevel@tonic-gate x->sval, y->sval FATAL;
11381ee2e5faSnakanon }
11391ee2e5faSnakanon (void) strcpy((char *)s, (char *)x->sval);
11401ee2e5faSnakanon (void) strcpy((char *)s + n1, (char *)y->sval);
11417c478bd9Sstevel@tonic-gate tempfree(y, "");
11427c478bd9Sstevel@tonic-gate z = gettemp("");
11437c478bd9Sstevel@tonic-gate z->sval = s;
11447c478bd9Sstevel@tonic-gate z->tval = STR;
11457c478bd9Sstevel@tonic-gate tempfree(x, "");
11467c478bd9Sstevel@tonic-gate return (z);
11477c478bd9Sstevel@tonic-gate }
11487c478bd9Sstevel@tonic-gate
11491ee2e5faSnakanon /*ARGSUSED*/
11501ee2e5faSnakanon Cell *
pastat(Node ** a,int n)11511ee2e5faSnakanon pastat(Node **a, int n)
11527c478bd9Sstevel@tonic-gate {
11537c478bd9Sstevel@tonic-gate register Cell *x;
11547c478bd9Sstevel@tonic-gate
11557c478bd9Sstevel@tonic-gate if (a[0] == 0)
11567c478bd9Sstevel@tonic-gate x = execute(a[1]);
11577c478bd9Sstevel@tonic-gate else {
11587c478bd9Sstevel@tonic-gate x = execute(a[0]);
11597c478bd9Sstevel@tonic-gate if (istrue(x)) {
11607c478bd9Sstevel@tonic-gate tempfree(x, "");
11617c478bd9Sstevel@tonic-gate x = execute(a[1]);
11627c478bd9Sstevel@tonic-gate }
11637c478bd9Sstevel@tonic-gate }
11641ee2e5faSnakanon return (x);
11657c478bd9Sstevel@tonic-gate }
11667c478bd9Sstevel@tonic-gate
11671ee2e5faSnakanon /*ARGSUSED*/
11681ee2e5faSnakanon Cell *
dopa2(Node ** a,int n)11691ee2e5faSnakanon dopa2(Node **a, int n)
11707c478bd9Sstevel@tonic-gate {
11717c478bd9Sstevel@tonic-gate Cell *x;
11727c478bd9Sstevel@tonic-gate int pair;
11737c478bd9Sstevel@tonic-gate static int *pairstack = NULL;
11747c478bd9Sstevel@tonic-gate
11757c478bd9Sstevel@tonic-gate if (!pairstack) {
11767c478bd9Sstevel@tonic-gate /* first time */
11777c478bd9Sstevel@tonic-gate dprintf(("paircnt: %d\n", paircnt));
11787c478bd9Sstevel@tonic-gate pairstack = (int *)malloc(sizeof (int) * paircnt);
11797c478bd9Sstevel@tonic-gate if (!pairstack)
11807c478bd9Sstevel@tonic-gate ERROR "out of space in dopa2" FATAL;
11817c478bd9Sstevel@tonic-gate (void) memset(pairstack, 0, sizeof (int) * paircnt);
11827c478bd9Sstevel@tonic-gate }
11837c478bd9Sstevel@tonic-gate
11847c478bd9Sstevel@tonic-gate pair = (int)a[3];
11857c478bd9Sstevel@tonic-gate if (pairstack[pair] == 0) {
11867c478bd9Sstevel@tonic-gate x = execute(a[0]);
11877c478bd9Sstevel@tonic-gate if (istrue(x))
11887c478bd9Sstevel@tonic-gate pairstack[pair] = 1;
11897c478bd9Sstevel@tonic-gate tempfree(x, "");
11907c478bd9Sstevel@tonic-gate }
11917c478bd9Sstevel@tonic-gate if (pairstack[pair] == 1) {
11927c478bd9Sstevel@tonic-gate x = execute(a[1]);
11937c478bd9Sstevel@tonic-gate if (istrue(x))
11947c478bd9Sstevel@tonic-gate pairstack[pair] = 0;
11957c478bd9Sstevel@tonic-gate tempfree(x, "");
11967c478bd9Sstevel@tonic-gate x = execute(a[2]);
11977c478bd9Sstevel@tonic-gate return (x);
11987c478bd9Sstevel@tonic-gate }
11997c478bd9Sstevel@tonic-gate return (false);
12007c478bd9Sstevel@tonic-gate }
12017c478bd9Sstevel@tonic-gate
12021ee2e5faSnakanon /*ARGSUSED*/
12031ee2e5faSnakanon Cell *
split(Node ** a,int nnn)12041ee2e5faSnakanon split(Node **a, int nnn)
12057c478bd9Sstevel@tonic-gate {
12067c478bd9Sstevel@tonic-gate Cell *x, *y, *ap;
12077c478bd9Sstevel@tonic-gate register uchar *s;
12087c478bd9Sstevel@tonic-gate register int sep;
12091ee2e5faSnakanon uchar *t, temp, num[11], *fs;
12107c478bd9Sstevel@tonic-gate int n, tempstat;
12117c478bd9Sstevel@tonic-gate
12127c478bd9Sstevel@tonic-gate y = execute(a[0]); /* source string */
12137c478bd9Sstevel@tonic-gate s = getsval(y);
12147c478bd9Sstevel@tonic-gate if (a[2] == 0) /* fs string */
12157c478bd9Sstevel@tonic-gate fs = *FS;
12167c478bd9Sstevel@tonic-gate else if ((int)a[3] == STRING) { /* split(str,arr,"string") */
12177c478bd9Sstevel@tonic-gate x = execute(a[2]);
12187c478bd9Sstevel@tonic-gate fs = getsval(x);
12197c478bd9Sstevel@tonic-gate } else if ((int)a[3] == REGEXPR)
12207c478bd9Sstevel@tonic-gate fs = (uchar *)"(regexpr)"; /* split(str,arr,/regexpr/) */
12217c478bd9Sstevel@tonic-gate else
12227c478bd9Sstevel@tonic-gate ERROR "illegal type of split()" FATAL;
12237c478bd9Sstevel@tonic-gate sep = *fs;
12247c478bd9Sstevel@tonic-gate ap = execute(a[1]); /* array name */
12257c478bd9Sstevel@tonic-gate freesymtab(ap);
12267c478bd9Sstevel@tonic-gate dprintf(("split: s=|%s|, a=%s, sep=|%s|\n", s, ap->nval, fs));
12277c478bd9Sstevel@tonic-gate ap->tval &= ~STR;
12287c478bd9Sstevel@tonic-gate ap->tval |= ARR;
12297c478bd9Sstevel@tonic-gate ap->sval = (uchar *)makesymtab(NSYMTAB);
12307c478bd9Sstevel@tonic-gate
12317c478bd9Sstevel@tonic-gate n = 0;
12321ee2e5faSnakanon if (*s != '\0' && strlen((char *)fs) > 1 || (int)a[3] == REGEXPR) {
12331ee2e5faSnakanon /* reg expr */
12347c478bd9Sstevel@tonic-gate fa *pfa;
12357c478bd9Sstevel@tonic-gate if ((int)a[3] == REGEXPR) { /* it's ready already */
12367c478bd9Sstevel@tonic-gate pfa = (fa *)a[2];
12377c478bd9Sstevel@tonic-gate } else {
12387c478bd9Sstevel@tonic-gate pfa = makedfa(fs, 1);
12397c478bd9Sstevel@tonic-gate }
12407c478bd9Sstevel@tonic-gate if (nematch(pfa, s)) {
12417c478bd9Sstevel@tonic-gate tempstat = pfa->initstat;
12427c478bd9Sstevel@tonic-gate pfa->initstat = 2;
12437c478bd9Sstevel@tonic-gate do {
12447c478bd9Sstevel@tonic-gate n++;
12451ee2e5faSnakanon (void) sprintf((char *)num, "%d", n);
12467c478bd9Sstevel@tonic-gate temp = *patbeg;
12477c478bd9Sstevel@tonic-gate *patbeg = '\0';
12481ee2e5faSnakanon if (is_number(s)) {
12491ee2e5faSnakanon (void) setsymtab(num, s,
12501ee2e5faSnakanon atof((char *)s),
12511ee2e5faSnakanon /*LINTED align*/
12521ee2e5faSnakanon STR|NUM, (Array *)ap->sval);
12531ee2e5faSnakanon } else {
12541ee2e5faSnakanon (void) setsymtab(num, s, 0.0,
12551ee2e5faSnakanon /*LINTED align*/
12561ee2e5faSnakanon STR, (Array *)ap->sval);
12571ee2e5faSnakanon }
12587c478bd9Sstevel@tonic-gate *patbeg = temp;
12597c478bd9Sstevel@tonic-gate s = patbeg + patlen;
12607c478bd9Sstevel@tonic-gate if (*(patbeg+patlen-1) == 0 || *s == 0) {
12617c478bd9Sstevel@tonic-gate n++;
12621ee2e5faSnakanon (void) sprintf((char *)num, "%d", n);
12631ee2e5faSnakanon (void) setsymtab(num, (uchar *)"", 0.0,
12641ee2e5faSnakanon /*LINTED align*/
12651ee2e5faSnakanon STR, (Array *)ap->sval);
12667c478bd9Sstevel@tonic-gate pfa->initstat = tempstat;
12677c478bd9Sstevel@tonic-gate goto spdone;
12687c478bd9Sstevel@tonic-gate }
12697c478bd9Sstevel@tonic-gate } while (nematch(pfa, s));
12707c478bd9Sstevel@tonic-gate }
12717c478bd9Sstevel@tonic-gate n++;
12721ee2e5faSnakanon (void) sprintf((char *)num, "%d", n);
12731ee2e5faSnakanon if (is_number(s)) {
12741ee2e5faSnakanon (void) setsymtab(num, s, atof((char *)s),
12751ee2e5faSnakanon /*LINTED align*/
12761ee2e5faSnakanon STR|NUM, (Array *)ap->sval);
12771ee2e5faSnakanon } else {
12781ee2e5faSnakanon /*LINTED align*/
12791ee2e5faSnakanon (void) setsymtab(num, s, 0.0, STR, (Array *)ap->sval);
12801ee2e5faSnakanon }
12817c478bd9Sstevel@tonic-gate spdone:
12827c478bd9Sstevel@tonic-gate pfa = NULL;
12837c478bd9Sstevel@tonic-gate } else if (sep == ' ') {
12847c478bd9Sstevel@tonic-gate for (n = 0; ; ) {
12857c478bd9Sstevel@tonic-gate while (*s == ' ' || *s == '\t' || *s == '\n')
12867c478bd9Sstevel@tonic-gate s++;
12877c478bd9Sstevel@tonic-gate if (*s == 0)
12887c478bd9Sstevel@tonic-gate break;
12897c478bd9Sstevel@tonic-gate n++;
12907c478bd9Sstevel@tonic-gate t = s;
12917c478bd9Sstevel@tonic-gate do
12927c478bd9Sstevel@tonic-gate s++;
12931ee2e5faSnakanon while (*s != ' ' && *s != '\t' &&
12941ee2e5faSnakanon *s != '\n' && *s != '\0')
12951ee2e5faSnakanon ;
12967c478bd9Sstevel@tonic-gate temp = *s;
12977c478bd9Sstevel@tonic-gate *s = '\0';
12981ee2e5faSnakanon (void) sprintf((char *)num, "%d", n);
12991ee2e5faSnakanon if (is_number(t)) {
13001ee2e5faSnakanon (void) setsymtab(num, t, atof((char *)t),
13011ee2e5faSnakanon /*LINTED align*/
13021ee2e5faSnakanon STR|NUM, (Array *)ap->sval);
13031ee2e5faSnakanon } else {
13041ee2e5faSnakanon (void) setsymtab(num, t, 0.0,
13051ee2e5faSnakanon /*LINTED align*/
13061ee2e5faSnakanon STR, (Array *)ap->sval);
13071ee2e5faSnakanon }
13087c478bd9Sstevel@tonic-gate *s = temp;
13097c478bd9Sstevel@tonic-gate if (*s != 0)
13107c478bd9Sstevel@tonic-gate s++;
13117c478bd9Sstevel@tonic-gate }
13127c478bd9Sstevel@tonic-gate } else if (*s != 0) {
13137c478bd9Sstevel@tonic-gate for (;;) {
13147c478bd9Sstevel@tonic-gate n++;
13157c478bd9Sstevel@tonic-gate t = s;
13167c478bd9Sstevel@tonic-gate while (*s != sep && *s != '\n' && *s != '\0')
13177c478bd9Sstevel@tonic-gate s++;
13187c478bd9Sstevel@tonic-gate temp = *s;
13197c478bd9Sstevel@tonic-gate *s = '\0';
13201ee2e5faSnakanon (void) sprintf((char *)num, "%d", n);
13211ee2e5faSnakanon if (is_number(t)) {
13221ee2e5faSnakanon (void) setsymtab(num, t, atof((char *)t),
13231ee2e5faSnakanon /*LINTED align*/
13241ee2e5faSnakanon STR|NUM, (Array *)ap->sval);
13251ee2e5faSnakanon } else {
13261ee2e5faSnakanon (void) setsymtab(num, t, 0.0,
13271ee2e5faSnakanon /*LINTED align*/
13281ee2e5faSnakanon STR, (Array *)ap->sval);
13291ee2e5faSnakanon }
13307c478bd9Sstevel@tonic-gate *s = temp;
13317c478bd9Sstevel@tonic-gate if (*s++ == 0)
13327c478bd9Sstevel@tonic-gate break;
13337c478bd9Sstevel@tonic-gate }
13347c478bd9Sstevel@tonic-gate }
13357c478bd9Sstevel@tonic-gate tempfree(ap, "");
13367c478bd9Sstevel@tonic-gate tempfree(y, "");
13377c478bd9Sstevel@tonic-gate if (a[2] != 0 && (int)a[3] == STRING)
13387c478bd9Sstevel@tonic-gate tempfree(x, "");
13397c478bd9Sstevel@tonic-gate x = gettemp("");
13407c478bd9Sstevel@tonic-gate x->tval = NUM;
13417c478bd9Sstevel@tonic-gate x->fval = n;
13427c478bd9Sstevel@tonic-gate return (x);
13437c478bd9Sstevel@tonic-gate }
13447c478bd9Sstevel@tonic-gate
13451ee2e5faSnakanon /*ARGSUSED*/
13461ee2e5faSnakanon Cell *
condexpr(Node ** a,int n)13471ee2e5faSnakanon condexpr(Node **a, int n)
13487c478bd9Sstevel@tonic-gate {
13497c478bd9Sstevel@tonic-gate register Cell *x;
13507c478bd9Sstevel@tonic-gate
13517c478bd9Sstevel@tonic-gate x = execute(a[0]);
13527c478bd9Sstevel@tonic-gate if (istrue(x)) {
13537c478bd9Sstevel@tonic-gate tempfree(x, "");
13547c478bd9Sstevel@tonic-gate x = execute(a[1]);
13557c478bd9Sstevel@tonic-gate } else {
13567c478bd9Sstevel@tonic-gate tempfree(x, "");
13577c478bd9Sstevel@tonic-gate x = execute(a[2]);
13587c478bd9Sstevel@tonic-gate }
13597c478bd9Sstevel@tonic-gate return (x);
13607c478bd9Sstevel@tonic-gate }
13617c478bd9Sstevel@tonic-gate
13621ee2e5faSnakanon /*ARGSUSED*/
13631ee2e5faSnakanon Cell *
ifstat(Node ** a,int n)13641ee2e5faSnakanon ifstat(Node **a, int n)
13657c478bd9Sstevel@tonic-gate {
13667c478bd9Sstevel@tonic-gate register Cell *x;
13677c478bd9Sstevel@tonic-gate
13687c478bd9Sstevel@tonic-gate x = execute(a[0]);
13697c478bd9Sstevel@tonic-gate if (istrue(x)) {
13707c478bd9Sstevel@tonic-gate tempfree(x, "");
13717c478bd9Sstevel@tonic-gate x = execute(a[1]);
13727c478bd9Sstevel@tonic-gate } else if (a[2] != 0) {
13737c478bd9Sstevel@tonic-gate tempfree(x, "");
13747c478bd9Sstevel@tonic-gate x = execute(a[2]);
13757c478bd9Sstevel@tonic-gate }
13767c478bd9Sstevel@tonic-gate return (x);
13777c478bd9Sstevel@tonic-gate }
13787c478bd9Sstevel@tonic-gate
13791ee2e5faSnakanon /*ARGSUSED*/
13801ee2e5faSnakanon Cell *
whilestat(Node ** a,int n)13811ee2e5faSnakanon whilestat(Node **a, int n)
13827c478bd9Sstevel@tonic-gate {
13837c478bd9Sstevel@tonic-gate register Cell *x;
13847c478bd9Sstevel@tonic-gate
13857c478bd9Sstevel@tonic-gate for (;;) {
13867c478bd9Sstevel@tonic-gate x = execute(a[0]);
13877c478bd9Sstevel@tonic-gate if (!istrue(x))
13887c478bd9Sstevel@tonic-gate return (x);
13897c478bd9Sstevel@tonic-gate tempfree(x, "");
13907c478bd9Sstevel@tonic-gate x = execute(a[1]);
13917c478bd9Sstevel@tonic-gate if (isbreak(x)) {
13927c478bd9Sstevel@tonic-gate x = true;
13937c478bd9Sstevel@tonic-gate return (x);
13947c478bd9Sstevel@tonic-gate }
13957c478bd9Sstevel@tonic-gate if (isnext(x) || isexit(x) || isret(x))
13967c478bd9Sstevel@tonic-gate return (x);
13977c478bd9Sstevel@tonic-gate tempfree(x, "");
13987c478bd9Sstevel@tonic-gate }
13997c478bd9Sstevel@tonic-gate }
14007c478bd9Sstevel@tonic-gate
14011ee2e5faSnakanon /*ARGSUSED*/
14021ee2e5faSnakanon Cell *
dostat(Node ** a,int n)14031ee2e5faSnakanon dostat(Node **a, int n)
14047c478bd9Sstevel@tonic-gate {
14057c478bd9Sstevel@tonic-gate register Cell *x;
14067c478bd9Sstevel@tonic-gate
14077c478bd9Sstevel@tonic-gate for (;;) {
14087c478bd9Sstevel@tonic-gate x = execute(a[0]);
14097c478bd9Sstevel@tonic-gate if (isbreak(x))
14101ee2e5faSnakanon return (true);
14117c478bd9Sstevel@tonic-gate if (isnext(x) || isexit(x) || isret(x))
14127c478bd9Sstevel@tonic-gate return (x);
14137c478bd9Sstevel@tonic-gate tempfree(x, "");
14147c478bd9Sstevel@tonic-gate x = execute(a[1]);
14157c478bd9Sstevel@tonic-gate if (!istrue(x))
14167c478bd9Sstevel@tonic-gate return (x);
14177c478bd9Sstevel@tonic-gate tempfree(x, "");
14187c478bd9Sstevel@tonic-gate }
14197c478bd9Sstevel@tonic-gate }
14207c478bd9Sstevel@tonic-gate
14211ee2e5faSnakanon /*ARGSUSED*/
14221ee2e5faSnakanon Cell *
forstat(Node ** a,int n)14231ee2e5faSnakanon forstat(Node **a, int n)
14247c478bd9Sstevel@tonic-gate {
14257c478bd9Sstevel@tonic-gate register Cell *x;
14267c478bd9Sstevel@tonic-gate
14277c478bd9Sstevel@tonic-gate x = execute(a[0]);
14287c478bd9Sstevel@tonic-gate tempfree(x, "");
14297c478bd9Sstevel@tonic-gate for (;;) {
14307c478bd9Sstevel@tonic-gate if (a[1] != 0) {
14317c478bd9Sstevel@tonic-gate x = execute(a[1]);
14321ee2e5faSnakanon if (!istrue(x))
14331ee2e5faSnakanon return (x);
14341ee2e5faSnakanon else
14351ee2e5faSnakanon tempfree(x, "");
14367c478bd9Sstevel@tonic-gate }
14377c478bd9Sstevel@tonic-gate x = execute(a[3]);
14387c478bd9Sstevel@tonic-gate if (isbreak(x)) /* turn off break */
14391ee2e5faSnakanon return (true);
14407c478bd9Sstevel@tonic-gate if (isnext(x) || isexit(x) || isret(x))
14417c478bd9Sstevel@tonic-gate return (x);
14427c478bd9Sstevel@tonic-gate tempfree(x, "");
14437c478bd9Sstevel@tonic-gate x = execute(a[2]);
14447c478bd9Sstevel@tonic-gate tempfree(x, "");
14457c478bd9Sstevel@tonic-gate }
14467c478bd9Sstevel@tonic-gate }
14477c478bd9Sstevel@tonic-gate
14481ee2e5faSnakanon /*ARGSUSED*/
14491ee2e5faSnakanon Cell *
instat(Node ** a,int n)14501ee2e5faSnakanon instat(Node **a, int n)
14517c478bd9Sstevel@tonic-gate {
14527c478bd9Sstevel@tonic-gate register Cell *x, *vp, *arrayp, *cp, *ncp;
14537c478bd9Sstevel@tonic-gate Array *tp;
14547c478bd9Sstevel@tonic-gate int i;
14557c478bd9Sstevel@tonic-gate
14567c478bd9Sstevel@tonic-gate vp = execute(a[0]);
14577c478bd9Sstevel@tonic-gate arrayp = execute(a[1]);
14587c478bd9Sstevel@tonic-gate if (!isarr(arrayp))
14597c478bd9Sstevel@tonic-gate ERROR "%s is not an array", arrayp->nval FATAL;
14601ee2e5faSnakanon /*LINTED align*/
14617c478bd9Sstevel@tonic-gate tp = (Array *)arrayp->sval;
14627c478bd9Sstevel@tonic-gate tempfree(arrayp, "");
14637c478bd9Sstevel@tonic-gate for (i = 0; i < tp->size; i++) { /* this routine knows too much */
14647c478bd9Sstevel@tonic-gate for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
14651ee2e5faSnakanon (void) setsval(vp, cp->nval);
14667c478bd9Sstevel@tonic-gate ncp = cp->cnext;
14677c478bd9Sstevel@tonic-gate x = execute(a[2]);
14687c478bd9Sstevel@tonic-gate if (isbreak(x)) {
14697c478bd9Sstevel@tonic-gate tempfree(vp, "");
14701ee2e5faSnakanon return (true);
14717c478bd9Sstevel@tonic-gate }
14727c478bd9Sstevel@tonic-gate if (isnext(x) || isexit(x) || isret(x)) {
14737c478bd9Sstevel@tonic-gate tempfree(vp, "");
14747c478bd9Sstevel@tonic-gate return (x);
14757c478bd9Sstevel@tonic-gate }
14767c478bd9Sstevel@tonic-gate tempfree(x, "");
14777c478bd9Sstevel@tonic-gate }
14787c478bd9Sstevel@tonic-gate }
14791ee2e5faSnakanon return (true);
14807c478bd9Sstevel@tonic-gate }
14817c478bd9Sstevel@tonic-gate
14821ee2e5faSnakanon /*ARGSUSED*/
14831ee2e5faSnakanon Cell *
bltin(Node ** a,int n)14841ee2e5faSnakanon bltin(Node **a, int n)
14857c478bd9Sstevel@tonic-gate {
14867c478bd9Sstevel@tonic-gate register Cell *x, *y;
14877c478bd9Sstevel@tonic-gate Awkfloat u;
14887c478bd9Sstevel@tonic-gate register int t;
14891ee2e5faSnakanon uchar *p, *buf;
14907c478bd9Sstevel@tonic-gate Node *nextarg;
14917c478bd9Sstevel@tonic-gate
14927c478bd9Sstevel@tonic-gate t = (int)a[0];
14937c478bd9Sstevel@tonic-gate x = execute(a[1]);
14947c478bd9Sstevel@tonic-gate nextarg = a[1]->nnext;
14957c478bd9Sstevel@tonic-gate switch (t) {
14967c478bd9Sstevel@tonic-gate case FLENGTH:
14971ee2e5faSnakanon u = (Awkfloat)strlen((char *)getsval(x)); break;
14987c478bd9Sstevel@tonic-gate case FLOG:
14997c478bd9Sstevel@tonic-gate u = errcheck(log(getfval(x)), "log"); break;
15007c478bd9Sstevel@tonic-gate case FINT:
15011ee2e5faSnakanon (void) modf(getfval(x), &u); break;
15027c478bd9Sstevel@tonic-gate case FEXP:
15037c478bd9Sstevel@tonic-gate u = errcheck(exp(getfval(x)), "exp"); break;
15047c478bd9Sstevel@tonic-gate case FSQRT:
15057c478bd9Sstevel@tonic-gate u = errcheck(sqrt(getfval(x)), "sqrt"); break;
15067c478bd9Sstevel@tonic-gate case FSIN:
15077c478bd9Sstevel@tonic-gate u = sin(getfval(x)); break;
15087c478bd9Sstevel@tonic-gate case FCOS:
15097c478bd9Sstevel@tonic-gate u = cos(getfval(x)); break;
15107c478bd9Sstevel@tonic-gate case FATAN:
15117c478bd9Sstevel@tonic-gate if (nextarg == 0) {
15121ee2e5faSnakanon ERROR "atan2 requires two arguments; returning 1.0"
15131ee2e5faSnakanon WARNING;
15147c478bd9Sstevel@tonic-gate u = 1.0;
15157c478bd9Sstevel@tonic-gate } else {
15167c478bd9Sstevel@tonic-gate y = execute(a[1]->nnext);
15177c478bd9Sstevel@tonic-gate u = atan2(getfval(x), getfval(y));
15187c478bd9Sstevel@tonic-gate tempfree(y, "");
15197c478bd9Sstevel@tonic-gate nextarg = nextarg->nnext;
15207c478bd9Sstevel@tonic-gate }
15217c478bd9Sstevel@tonic-gate break;
15227c478bd9Sstevel@tonic-gate case FSYSTEM:
15231ee2e5faSnakanon /* in case something is buffered already */
15241ee2e5faSnakanon (void) fflush(stdout);
15251ee2e5faSnakanon /* 256 is unix-dep */
15261ee2e5faSnakanon u = (Awkfloat)system((char *)getsval(x)) / 256;
15277c478bd9Sstevel@tonic-gate break;
15287c478bd9Sstevel@tonic-gate case FRAND:
15297c478bd9Sstevel@tonic-gate u = (Awkfloat)(rand() % 32767) / 32767.0;
15307c478bd9Sstevel@tonic-gate break;
15317c478bd9Sstevel@tonic-gate case FSRAND:
15327c478bd9Sstevel@tonic-gate if (x->tval & REC) /* no argument provided */
15337c478bd9Sstevel@tonic-gate u = time((time_t *)0);
15347c478bd9Sstevel@tonic-gate else
15357c478bd9Sstevel@tonic-gate u = getfval(x);
15367c478bd9Sstevel@tonic-gate srand((int)u); u = (int)u;
15377c478bd9Sstevel@tonic-gate break;
15387c478bd9Sstevel@tonic-gate case FTOUPPER:
15397c478bd9Sstevel@tonic-gate case FTOLOWER:
15401ee2e5faSnakanon buf = tostring(getsval(x));
15417c478bd9Sstevel@tonic-gate if (t == FTOUPPER) {
15427c478bd9Sstevel@tonic-gate for (p = buf; *p; p++)
15437c478bd9Sstevel@tonic-gate if (islower(*p))
15447c478bd9Sstevel@tonic-gate *p = toupper(*p);
15457c478bd9Sstevel@tonic-gate } else {
15467c478bd9Sstevel@tonic-gate for (p = buf; *p; p++)
15477c478bd9Sstevel@tonic-gate if (isupper(*p))
15487c478bd9Sstevel@tonic-gate *p = tolower(*p);
15497c478bd9Sstevel@tonic-gate }
15507c478bd9Sstevel@tonic-gate tempfree(x, "");
15517c478bd9Sstevel@tonic-gate x = gettemp("");
15521ee2e5faSnakanon (void) setsval(x, buf);
15531ee2e5faSnakanon free(buf);
15541ee2e5faSnakanon return (x);
15557c478bd9Sstevel@tonic-gate default: /* can't happen */
15567c478bd9Sstevel@tonic-gate ERROR "illegal function type %d", t FATAL;
15577c478bd9Sstevel@tonic-gate break;
15587c478bd9Sstevel@tonic-gate }
15597c478bd9Sstevel@tonic-gate tempfree(x, "");
15607c478bd9Sstevel@tonic-gate x = gettemp("");
15611ee2e5faSnakanon (void) setfval(x, u);
15627c478bd9Sstevel@tonic-gate if (nextarg != 0) {
15637c478bd9Sstevel@tonic-gate ERROR "warning: function has too many arguments" WARNING;
15647c478bd9Sstevel@tonic-gate for (; nextarg; nextarg = nextarg->nnext)
15651ee2e5faSnakanon (void) execute(nextarg);
15667c478bd9Sstevel@tonic-gate }
15677c478bd9Sstevel@tonic-gate return (x);
15687c478bd9Sstevel@tonic-gate }
15697c478bd9Sstevel@tonic-gate
15701ee2e5faSnakanon /*ARGSUSED*/
15711ee2e5faSnakanon Cell *
print(Node ** a,int n)15721ee2e5faSnakanon print(Node **a, int n)
15737c478bd9Sstevel@tonic-gate {
15747c478bd9Sstevel@tonic-gate register Node *x;
15757c478bd9Sstevel@tonic-gate register Cell *y;
15767c478bd9Sstevel@tonic-gate FILE *fp;
15777c478bd9Sstevel@tonic-gate
15787c478bd9Sstevel@tonic-gate if (a[1] == 0)
15797c478bd9Sstevel@tonic-gate fp = stdout;
15807c478bd9Sstevel@tonic-gate else
15817c478bd9Sstevel@tonic-gate fp = redirect((int)a[1], a[2]);
15827c478bd9Sstevel@tonic-gate for (x = a[0]; x != NULL; x = x->nnext) {
15837c478bd9Sstevel@tonic-gate y = execute(x);
15841ee2e5faSnakanon (void) fputs((char *)getsval(y), fp);
15857c478bd9Sstevel@tonic-gate tempfree(y, "");
15867c478bd9Sstevel@tonic-gate if (x->nnext == NULL)
15871ee2e5faSnakanon (void) fputs((char *)*ORS, fp);
15887c478bd9Sstevel@tonic-gate else
15891ee2e5faSnakanon (void) fputs((char *)*OFS, fp);
15907c478bd9Sstevel@tonic-gate }
15917c478bd9Sstevel@tonic-gate if (a[1] != 0)
15921ee2e5faSnakanon (void) fflush(fp);
15937c478bd9Sstevel@tonic-gate return (true);
15947c478bd9Sstevel@tonic-gate }
15957c478bd9Sstevel@tonic-gate
15961ee2e5faSnakanon /*ARGSUSED*/
15971ee2e5faSnakanon Cell *
nullproc(Node ** a,int n)15981ee2e5faSnakanon nullproc(Node **a, int n)
15997c478bd9Sstevel@tonic-gate {
16001ee2e5faSnakanon return (0);
16011ee2e5faSnakanon }
16021ee2e5faSnakanon
16031ee2e5faSnakanon struct {
16047c478bd9Sstevel@tonic-gate FILE *fp;
16057c478bd9Sstevel@tonic-gate uchar *fname;
16067c478bd9Sstevel@tonic-gate int mode; /* '|', 'a', 'w' */
16077c478bd9Sstevel@tonic-gate } files[FOPEN_MAX];
16087c478bd9Sstevel@tonic-gate
16091ee2e5faSnakanon static FILE *
redirect(int a,Node * b)16101ee2e5faSnakanon redirect(int a, Node *b)
16117c478bd9Sstevel@tonic-gate {
16127c478bd9Sstevel@tonic-gate FILE *fp;
16137c478bd9Sstevel@tonic-gate Cell *x;
16147c478bd9Sstevel@tonic-gate uchar *fname;
16157c478bd9Sstevel@tonic-gate
16167c478bd9Sstevel@tonic-gate x = execute(b);
16177c478bd9Sstevel@tonic-gate fname = getsval(x);
16187c478bd9Sstevel@tonic-gate fp = openfile(a, fname);
16197c478bd9Sstevel@tonic-gate if (fp == NULL)
16207c478bd9Sstevel@tonic-gate ERROR "can't open file %s", fname FATAL;
16217c478bd9Sstevel@tonic-gate tempfree(x, "");
16221ee2e5faSnakanon return (fp);
16237c478bd9Sstevel@tonic-gate }
16247c478bd9Sstevel@tonic-gate
16251ee2e5faSnakanon static FILE *
openfile(int a,uchar * s)16261ee2e5faSnakanon openfile(int a, uchar *s)
16277c478bd9Sstevel@tonic-gate {
16287c478bd9Sstevel@tonic-gate register int i, m;
16297c478bd9Sstevel@tonic-gate register FILE *fp;
16307c478bd9Sstevel@tonic-gate
16317c478bd9Sstevel@tonic-gate if (*s == '\0')
16327c478bd9Sstevel@tonic-gate ERROR "null file name in print or getline" FATAL;
16331ee2e5faSnakanon for (i = 0; i < FOPEN_MAX; i++) {
16341ee2e5faSnakanon if (files[i].fname &&
16351ee2e5faSnakanon strcmp((char *)s, (char *)files[i].fname) == 0) {
16361ee2e5faSnakanon if (a == files[i].mode ||
16371ee2e5faSnakanon a == APPEND && files[i].mode == GT) {
16381ee2e5faSnakanon return (files[i].fp);
16391ee2e5faSnakanon }
16401ee2e5faSnakanon }
16411ee2e5faSnakanon }
16421ee2e5faSnakanon for (i = 0; i < FOPEN_MAX; i++) {
16437c478bd9Sstevel@tonic-gate if (files[i].fp == 0)
16447c478bd9Sstevel@tonic-gate break;
16451ee2e5faSnakanon }
16467c478bd9Sstevel@tonic-gate if (i >= FOPEN_MAX)
16477c478bd9Sstevel@tonic-gate ERROR "%s makes too many open files", s FATAL;
16481ee2e5faSnakanon (void) fflush(stdout); /* force a semblance of order */
16497c478bd9Sstevel@tonic-gate m = a;
16507c478bd9Sstevel@tonic-gate if (a == GT) {
16517c478bd9Sstevel@tonic-gate fp = fopen((char *)s, "w");
16527c478bd9Sstevel@tonic-gate } else if (a == APPEND) {
16537c478bd9Sstevel@tonic-gate fp = fopen((char *)s, "a");
16547c478bd9Sstevel@tonic-gate m = GT; /* so can mix > and >> */
16557c478bd9Sstevel@tonic-gate } else if (a == '|') { /* output pipe */
16567c478bd9Sstevel@tonic-gate fp = popen((char *)s, "w");
16577c478bd9Sstevel@tonic-gate } else if (a == LE) { /* input pipe */
16587c478bd9Sstevel@tonic-gate fp = popen((char *)s, "r");
16597c478bd9Sstevel@tonic-gate } else if (a == LT) { /* getline <file */
16601ee2e5faSnakanon fp = strcmp((char *)s, "-") == 0 ?
16611ee2e5faSnakanon stdin : fopen((char *)s, "r"); /* "-" is stdin */
16627c478bd9Sstevel@tonic-gate } else /* can't happen */
16637c478bd9Sstevel@tonic-gate ERROR "illegal redirection" FATAL;
16647c478bd9Sstevel@tonic-gate if (fp != NULL) {
16657c478bd9Sstevel@tonic-gate files[i].fname = tostring(s);
16667c478bd9Sstevel@tonic-gate files[i].fp = fp;
16677c478bd9Sstevel@tonic-gate files[i].mode = m;
16687c478bd9Sstevel@tonic-gate }
16691ee2e5faSnakanon return (fp);
16707c478bd9Sstevel@tonic-gate }
16717c478bd9Sstevel@tonic-gate
16721ee2e5faSnakanon /*ARGSUSED*/
16731ee2e5faSnakanon Cell *
closefile(Node ** a,int n)16741ee2e5faSnakanon closefile(Node **a, int n)
16757c478bd9Sstevel@tonic-gate {
16767c478bd9Sstevel@tonic-gate register Cell *x;
16777c478bd9Sstevel@tonic-gate int i, stat;
16787c478bd9Sstevel@tonic-gate
16797c478bd9Sstevel@tonic-gate x = execute(a[0]);
16801ee2e5faSnakanon (void) getsval(x);
16811ee2e5faSnakanon for (i = 0; i < FOPEN_MAX; i++) {
16821ee2e5faSnakanon if (files[i].fname &&
16831ee2e5faSnakanon strcmp((char *)x->sval, (char *)files[i].fname) == 0) {
16841ee2e5faSnakanon if (ferror(files[i].fp)) {
16851ee2e5faSnakanon ERROR "i/o error occurred on %s",
16861ee2e5faSnakanon files[i].fname WARNING;
16871ee2e5faSnakanon }
16887c478bd9Sstevel@tonic-gate if (files[i].mode == '|' || files[i].mode == LE)
16897c478bd9Sstevel@tonic-gate stat = pclose(files[i].fp);
16907c478bd9Sstevel@tonic-gate else
16917c478bd9Sstevel@tonic-gate stat = fclose(files[i].fp);
16921ee2e5faSnakanon if (stat == EOF) {
16931ee2e5faSnakanon ERROR "i/o error occurred closing %s",
16941ee2e5faSnakanon files[i].fname WARNING;
16951ee2e5faSnakanon }
16967c478bd9Sstevel@tonic-gate xfree(files[i].fname);
16971ee2e5faSnakanon /* watch out for ref thru this */
16981ee2e5faSnakanon files[i].fname = NULL;
16997c478bd9Sstevel@tonic-gate files[i].fp = NULL;
17007c478bd9Sstevel@tonic-gate }
17011ee2e5faSnakanon }
17027c478bd9Sstevel@tonic-gate tempfree(x, "close");
17037c478bd9Sstevel@tonic-gate return (true);
17047c478bd9Sstevel@tonic-gate }
17057c478bd9Sstevel@tonic-gate
17061ee2e5faSnakanon static void
closeall(void)17071ee2e5faSnakanon closeall(void)
17087c478bd9Sstevel@tonic-gate {
17097c478bd9Sstevel@tonic-gate int i, stat;
17107c478bd9Sstevel@tonic-gate
17111ee2e5faSnakanon for (i = 0; i < FOPEN_MAX; i++) {
17127c478bd9Sstevel@tonic-gate if (files[i].fp) {
17131ee2e5faSnakanon if (ferror(files[i].fp)) {
17141ee2e5faSnakanon ERROR "i/o error occurred on %s",
17151ee2e5faSnakanon files[i].fname WARNING;
17161ee2e5faSnakanon }
17177c478bd9Sstevel@tonic-gate if (files[i].mode == '|' || files[i].mode == LE)
17187c478bd9Sstevel@tonic-gate stat = pclose(files[i].fp);
17197c478bd9Sstevel@tonic-gate else
17207c478bd9Sstevel@tonic-gate stat = fclose(files[i].fp);
17211ee2e5faSnakanon if (stat == EOF) {
17221ee2e5faSnakanon ERROR "i/o error occurred while closing %s",
17231ee2e5faSnakanon files[i].fname WARNING;
17241ee2e5faSnakanon }
17251ee2e5faSnakanon }
17267c478bd9Sstevel@tonic-gate }
17277c478bd9Sstevel@tonic-gate }
17287c478bd9Sstevel@tonic-gate
17291ee2e5faSnakanon /*ARGSUSED*/
17301ee2e5faSnakanon Cell *
sub(Node ** a,int nnn)17311ee2e5faSnakanon sub(Node **a, int nnn)
17327c478bd9Sstevel@tonic-gate {
17331ee2e5faSnakanon register uchar *sptr;
17347c478bd9Sstevel@tonic-gate register Cell *x, *y, *result;
17351ee2e5faSnakanon uchar *buf, *t;
17367c478bd9Sstevel@tonic-gate fa *pfa;
17371ee2e5faSnakanon size_t bsize, cnt, len;
17387c478bd9Sstevel@tonic-gate
17397c478bd9Sstevel@tonic-gate x = execute(a[3]); /* target string */
17407c478bd9Sstevel@tonic-gate t = getsval(x);
17417c478bd9Sstevel@tonic-gate if (a[0] == 0)
17427c478bd9Sstevel@tonic-gate pfa = (fa *)a[1]; /* regular expression */
17437c478bd9Sstevel@tonic-gate else {
17447c478bd9Sstevel@tonic-gate y = execute(a[1]);
17457c478bd9Sstevel@tonic-gate pfa = makedfa(getsval(y), 1);
17467c478bd9Sstevel@tonic-gate tempfree(y, "");
17477c478bd9Sstevel@tonic-gate }
17487c478bd9Sstevel@tonic-gate y = execute(a[2]); /* replacement string */
17497c478bd9Sstevel@tonic-gate result = false;
17507c478bd9Sstevel@tonic-gate if (pmatch(pfa, t)) {
17511ee2e5faSnakanon init_buf(&buf, &bsize, LINE_INCR);
17521ee2e5faSnakanon cnt = 0;
17537c478bd9Sstevel@tonic-gate sptr = t;
17541ee2e5faSnakanon len = patbeg - sptr;
17551ee2e5faSnakanon if (len > 0) {
17561ee2e5faSnakanon expand_buf(&buf, &bsize, cnt + len);
17571ee2e5faSnakanon (void) memcpy(buf, sptr, len);
17581ee2e5faSnakanon cnt += len;
17591ee2e5faSnakanon }
17607c478bd9Sstevel@tonic-gate sptr = getsval(y);
17611ee2e5faSnakanon while (*sptr != 0) {
17621ee2e5faSnakanon expand_buf(&buf, &bsize, cnt);
176383efe03bScf46844 if (*sptr == '\\' &&
176483efe03bScf46844 (*(sptr+1) == '&' || *(sptr+1) == '\\')) {
17657c478bd9Sstevel@tonic-gate sptr++; /* skip \, */
176683efe03bScf46844 buf[cnt++] = *sptr++; /* add & or \ */
17677c478bd9Sstevel@tonic-gate } else if (*sptr == '&') {
17681ee2e5faSnakanon expand_buf(&buf, &bsize, cnt + patlen);
17697c478bd9Sstevel@tonic-gate sptr++;
17701ee2e5faSnakanon (void) memcpy(&buf[cnt], patbeg, patlen);
17711ee2e5faSnakanon cnt += patlen;
17721ee2e5faSnakanon } else {
17731ee2e5faSnakanon buf[cnt++] = *sptr++;
17741ee2e5faSnakanon }
17751ee2e5faSnakanon }
17767c478bd9Sstevel@tonic-gate sptr = patbeg + patlen;
17771ee2e5faSnakanon if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
17781ee2e5faSnakanon len = strlen((char *)sptr);
17791ee2e5faSnakanon expand_buf(&buf, &bsize, cnt + len);
17801ee2e5faSnakanon (void) memcpy(&buf[cnt], sptr, len);
17811ee2e5faSnakanon cnt += len;
17821ee2e5faSnakanon }
17831ee2e5faSnakanon buf[cnt] = '\0';
17841ee2e5faSnakanon (void) setsval(x, buf);
17851ee2e5faSnakanon free(buf);
17861ee2e5faSnakanon result = true;
17877c478bd9Sstevel@tonic-gate }
17887c478bd9Sstevel@tonic-gate tempfree(x, "");
17897c478bd9Sstevel@tonic-gate tempfree(y, "");
17901ee2e5faSnakanon return (result);
17917c478bd9Sstevel@tonic-gate }
17927c478bd9Sstevel@tonic-gate
17931ee2e5faSnakanon /*ARGSUSED*/
17941ee2e5faSnakanon Cell *
gsub(Node ** a,int nnn)17951ee2e5faSnakanon gsub(Node **a, int nnn)
17967c478bd9Sstevel@tonic-gate {
17977c478bd9Sstevel@tonic-gate register Cell *x, *y;
17981ee2e5faSnakanon register uchar *rptr, *sptr, *t;
17991ee2e5faSnakanon uchar *buf;
18007c478bd9Sstevel@tonic-gate register fa *pfa;
18017c478bd9Sstevel@tonic-gate int mflag, tempstat, num;
18021ee2e5faSnakanon size_t bsize, cnt, len;
18037c478bd9Sstevel@tonic-gate
18047c478bd9Sstevel@tonic-gate mflag = 0; /* if mflag == 0, can replace empty string */
18057c478bd9Sstevel@tonic-gate num = 0;
18067c478bd9Sstevel@tonic-gate x = execute(a[3]); /* target string */
18077c478bd9Sstevel@tonic-gate t = getsval(x);
18087c478bd9Sstevel@tonic-gate if (a[0] == 0)
18097c478bd9Sstevel@tonic-gate pfa = (fa *) a[1]; /* regular expression */
18107c478bd9Sstevel@tonic-gate else {
18117c478bd9Sstevel@tonic-gate y = execute(a[1]);
18127c478bd9Sstevel@tonic-gate pfa = makedfa(getsval(y), 1);
18137c478bd9Sstevel@tonic-gate tempfree(y, "");
18147c478bd9Sstevel@tonic-gate }
18157c478bd9Sstevel@tonic-gate y = execute(a[2]); /* replacement string */
18167c478bd9Sstevel@tonic-gate if (pmatch(pfa, t)) {
18177c478bd9Sstevel@tonic-gate tempstat = pfa->initstat;
18187c478bd9Sstevel@tonic-gate pfa->initstat = 2;
18191ee2e5faSnakanon init_buf(&buf, &bsize, LINE_INCR);
18207c478bd9Sstevel@tonic-gate rptr = getsval(y);
18211ee2e5faSnakanon cnt = 0;
18227c478bd9Sstevel@tonic-gate do {
18231ee2e5faSnakanon if (patlen == 0 && *patbeg != 0) {
18241ee2e5faSnakanon /* matched empty string */
18257c478bd9Sstevel@tonic-gate if (mflag == 0) { /* can replace empty */
18267c478bd9Sstevel@tonic-gate num++;
18277c478bd9Sstevel@tonic-gate sptr = rptr;
18281ee2e5faSnakanon while (*sptr != 0) {
18291ee2e5faSnakanon expand_buf(&buf, &bsize, cnt);
18301ee2e5faSnakanon if (*sptr == '\\' &&
183183efe03bScf46844 (*(sptr+1) == '&' ||
183283efe03bScf46844 *(sptr+1) == '\\')) {
18337c478bd9Sstevel@tonic-gate sptr++;
18341ee2e5faSnakanon buf[cnt++] = *sptr++;
18357c478bd9Sstevel@tonic-gate } else if (*sptr == '&') {
18361ee2e5faSnakanon expand_buf(&buf,
18371ee2e5faSnakanon &bsize,
18381ee2e5faSnakanon cnt + patlen);
18397c478bd9Sstevel@tonic-gate sptr++;
18401ee2e5faSnakanon (void) memcpy(&buf[cnt],
18411ee2e5faSnakanon patbeg, patlen);
18421ee2e5faSnakanon cnt += patlen;
18431ee2e5faSnakanon } else {
18441ee2e5faSnakanon buf[cnt++] = *sptr++;
18451ee2e5faSnakanon }
18461ee2e5faSnakanon }
18477c478bd9Sstevel@tonic-gate }
18487c478bd9Sstevel@tonic-gate if (*t == 0) /* at end */
18497c478bd9Sstevel@tonic-gate goto done;
18501ee2e5faSnakanon expand_buf(&buf, &bsize, cnt);
18511ee2e5faSnakanon buf[cnt++] = *t++;
18527c478bd9Sstevel@tonic-gate mflag = 0;
18531ee2e5faSnakanon } else { /* matched nonempty string */
18547c478bd9Sstevel@tonic-gate num++;
18557c478bd9Sstevel@tonic-gate sptr = t;
18561ee2e5faSnakanon len = patbeg - sptr;
18571ee2e5faSnakanon if (len > 0) {
18581ee2e5faSnakanon expand_buf(&buf, &bsize, cnt + len);
18591ee2e5faSnakanon (void) memcpy(&buf[cnt], sptr, len);
18601ee2e5faSnakanon cnt += len;
18611ee2e5faSnakanon }
18627c478bd9Sstevel@tonic-gate sptr = rptr;
18631ee2e5faSnakanon while (*sptr != 0) {
18641ee2e5faSnakanon expand_buf(&buf, &bsize, cnt);
186583efe03bScf46844 if (*sptr == '\\' &&
186683efe03bScf46844 (*(sptr+1) == '&' ||
186783efe03bScf46844 *(sptr+1) == '\\')) {
18687c478bd9Sstevel@tonic-gate sptr++;
18691ee2e5faSnakanon buf[cnt++] = *sptr++;
18707c478bd9Sstevel@tonic-gate } else if (*sptr == '&') {
18711ee2e5faSnakanon expand_buf(&buf, &bsize,
18721ee2e5faSnakanon cnt + patlen);
18737c478bd9Sstevel@tonic-gate sptr++;
18741ee2e5faSnakanon (void) memcpy(&buf[cnt],
18751ee2e5faSnakanon patbeg, patlen);
18761ee2e5faSnakanon cnt += patlen;
18771ee2e5faSnakanon } else {
18781ee2e5faSnakanon buf[cnt++] = *sptr++;
18791ee2e5faSnakanon }
18801ee2e5faSnakanon }
18817c478bd9Sstevel@tonic-gate t = patbeg + patlen;
18827c478bd9Sstevel@tonic-gate if ((*(t-1) == 0) || (*t == 0))
18837c478bd9Sstevel@tonic-gate goto done;
18847c478bd9Sstevel@tonic-gate mflag = 1;
18857c478bd9Sstevel@tonic-gate }
18867c478bd9Sstevel@tonic-gate } while (pmatch(pfa, t));
18877c478bd9Sstevel@tonic-gate sptr = t;
18881ee2e5faSnakanon len = strlen((char *)sptr);
18891ee2e5faSnakanon expand_buf(&buf, &bsize, len + cnt);
18901ee2e5faSnakanon (void) memcpy(&buf[cnt], sptr, len);
18911ee2e5faSnakanon cnt += len;
18921ee2e5faSnakanon done:
18931ee2e5faSnakanon buf[cnt] = '\0';
18941ee2e5faSnakanon (void) setsval(x, buf);
18951ee2e5faSnakanon free(buf);
18967c478bd9Sstevel@tonic-gate pfa->initstat = tempstat;
18977c478bd9Sstevel@tonic-gate }
18987c478bd9Sstevel@tonic-gate tempfree(x, "");
18997c478bd9Sstevel@tonic-gate tempfree(y, "");
19007c478bd9Sstevel@tonic-gate x = gettemp("");
19017c478bd9Sstevel@tonic-gate x->tval = NUM;
19027c478bd9Sstevel@tonic-gate x->fval = num;
19037c478bd9Sstevel@tonic-gate return (x);
19047c478bd9Sstevel@tonic-gate }
1905