1*3ee4fc2aSCody Peter Mello /*
2*3ee4fc2aSCody Peter Mello * Copyright (C) Lucent Technologies 1997
3*3ee4fc2aSCody Peter Mello * All Rights Reserved
4*3ee4fc2aSCody Peter Mello *
5*3ee4fc2aSCody Peter Mello * Permission to use, copy, modify, and distribute this software and
6*3ee4fc2aSCody Peter Mello * its documentation for any purpose and without fee is hereby
7*3ee4fc2aSCody Peter Mello * granted, provided that the above copyright notice appear in all
8*3ee4fc2aSCody Peter Mello * copies and that both that the copyright notice and this
9*3ee4fc2aSCody Peter Mello * permission notice and warranty disclaimer appear in supporting
10*3ee4fc2aSCody Peter Mello * documentation, and that the name Lucent Technologies or any of
11*3ee4fc2aSCody Peter Mello * its entities not be used in advertising or publicity pertaining
12*3ee4fc2aSCody Peter Mello * to distribution of the software without specific, written prior
13*3ee4fc2aSCody Peter Mello * permission.
14*3ee4fc2aSCody Peter Mello *
15*3ee4fc2aSCody Peter Mello * LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16*3ee4fc2aSCody Peter Mello * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
17*3ee4fc2aSCody Peter Mello * IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
18*3ee4fc2aSCody Peter Mello * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19*3ee4fc2aSCody Peter Mello * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
20*3ee4fc2aSCody Peter Mello * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21*3ee4fc2aSCody Peter Mello * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
22*3ee4fc2aSCody Peter Mello * THIS SOFTWARE.
23*3ee4fc2aSCody Peter Mello */
24*3ee4fc2aSCody Peter Mello
257c478bd9Sstevel@tonic-gate /*
267c478bd9Sstevel@tonic-gate * CDDL HEADER START
277c478bd9Sstevel@tonic-gate *
287c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
2983efe03bScf * Common Development and Distribution License (the "License").
3083efe03bScf * You may not use this file except in compliance with the License.
317c478bd9Sstevel@tonic-gate *
327c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
337c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
347c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
357c478bd9Sstevel@tonic-gate * and limitations under the License.
367c478bd9Sstevel@tonic-gate *
377c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
387c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
397c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
407c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
417c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
427c478bd9Sstevel@tonic-gate *
437c478bd9Sstevel@tonic-gate * CDDL HEADER END
447c478bd9Sstevel@tonic-gate */
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate /*
4723a1cceaSRoger A. Faulkner * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
487c478bd9Sstevel@tonic-gate */
497c478bd9Sstevel@tonic-gate
501ee2e5faSnakanon /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
511ee2e5faSnakanon /* All Rights Reserved */
521ee2e5faSnakanon
531ee2e5faSnakanon #define DEBUG
547c478bd9Sstevel@tonic-gate #include <stdio.h>
557c478bd9Sstevel@tonic-gate #include <ctype.h>
567c478bd9Sstevel@tonic-gate #include <setjmp.h>
57*3ee4fc2aSCody Peter Mello #include <math.h>
587c478bd9Sstevel@tonic-gate #include <time.h>
59*3ee4fc2aSCody Peter Mello #include <sys/wait.h>
60*3ee4fc2aSCody Peter Mello #include "awk.h"
61*3ee4fc2aSCody Peter Mello #include "y.tab.h"
627c478bd9Sstevel@tonic-gate
63*3ee4fc2aSCody Peter Mello #define tempfree(x) if (istemp(x)) tfree(x)
647c478bd9Sstevel@tonic-gate
651ee2e5faSnakanon static jmp_buf env;
66*3ee4fc2aSCody Peter Mello extern Awkfloat srand_seed;
677c478bd9Sstevel@tonic-gate
68*3ee4fc2aSCody Peter Mello static Cell *execute(Node *);
69*3ee4fc2aSCody Peter Mello static Cell *gettemp(void), *copycell(Cell *);
70*3ee4fc2aSCody Peter Mello static FILE *openfile(int, const char *), *redirect(int, Node *);
717c478bd9Sstevel@tonic-gate
72*3ee4fc2aSCody Peter Mello Node *winner = NULL; /* root of parse tree */
73*3ee4fc2aSCody Peter Mello static Cell *tmps; /* free temporary cells for execution */
741ee2e5faSnakanon
75*3ee4fc2aSCody Peter Mello static Cell truecell = { OBOOL, BTRUE, NULL, NULL, 1.0, NUM, NULL };
76*3ee4fc2aSCody Peter Mello Cell *True = &truecell;
77*3ee4fc2aSCody Peter Mello static Cell falsecell = { OBOOL, BFALSE, NULL, NULL, 0.0, NUM, NULL };
78*3ee4fc2aSCody Peter Mello Cell *False = &falsecell;
79*3ee4fc2aSCody Peter Mello static Cell breakcell = { OJUMP, JBREAK, NULL, NULL, 0.0, NUM, NULL };
807c478bd9Sstevel@tonic-gate Cell *jbreak = &breakcell;
81*3ee4fc2aSCody Peter Mello static Cell contcell = { OJUMP, JCONT, NULL, NULL, 0.0, NUM, NULL };
827c478bd9Sstevel@tonic-gate Cell *jcont = &contcell;
83*3ee4fc2aSCody Peter Mello static Cell nextcell = { OJUMP, JNEXT, NULL, NULL, 0.0, NUM, NULL };
847c478bd9Sstevel@tonic-gate Cell *jnext = &nextcell;
85*3ee4fc2aSCody Peter Mello static Cell nextfilecell = { OJUMP, JNEXTFILE, NULL, NULL, 0.0,
86*3ee4fc2aSCody Peter Mello NUM, NULL };
87*3ee4fc2aSCody Peter Mello Cell *jnextfile = &nextfilecell;
88*3ee4fc2aSCody Peter Mello static Cell exitcell = { OJUMP, JEXIT, NULL, NULL, 0.0, NUM, NULL };
897c478bd9Sstevel@tonic-gate Cell *jexit = &exitcell;
90*3ee4fc2aSCody Peter Mello static Cell retcell = { OJUMP, JRET, NULL, NULL, 0.0, NUM, NULL };
917c478bd9Sstevel@tonic-gate Cell *jret = &retcell;
92*3ee4fc2aSCody Peter Mello static Cell tempcell = { OCELL, CTEMP, NULL, "", 0.0,
93*3ee4fc2aSCody Peter Mello NUM|STR|DONTFREE, NULL };
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate Node *curnode = NULL; /* the node being executed, for debugging */
967c478bd9Sstevel@tonic-gate
97*3ee4fc2aSCody Peter Mello static void tfree(Cell *);
981ee2e5faSnakanon static void closeall(void);
991ee2e5faSnakanon static double ipow(double, int);
100*3ee4fc2aSCody Peter Mello static void backsub(char **pb_ptr, char **sptr_ptr);
101*3ee4fc2aSCody Peter Mello
102*3ee4fc2aSCody Peter Mello
103*3ee4fc2aSCody Peter Mello /*
104*3ee4fc2aSCody Peter Mello * buffer memory management
105*3ee4fc2aSCody Peter Mello *
106*3ee4fc2aSCody Peter Mello * pbuf: address of pointer to buffer being managed
107*3ee4fc2aSCody Peter Mello * psiz: address of buffer size variable
108*3ee4fc2aSCody Peter Mello * minlen: minimum length of buffer needed
109*3ee4fc2aSCody Peter Mello * quantum: buffer size quantum
110*3ee4fc2aSCody Peter Mello * pbptr: address of movable pointer into buffer, or 0 if none
111*3ee4fc2aSCody Peter Mello * whatrtn: name of the calling routine if failure should cause fatal error
112*3ee4fc2aSCody Peter Mello *
113*3ee4fc2aSCody Peter Mello * return 0 for realloc failure, !=0 for success
114*3ee4fc2aSCody Peter Mello */
115*3ee4fc2aSCody Peter Mello int
adjbuf(char ** pbuf,size_t * psiz,size_t minlen,size_t quantum,char ** pbptr,const char * whatrtn)116*3ee4fc2aSCody Peter Mello adjbuf(char **pbuf, size_t *psiz, size_t minlen, size_t quantum, char **pbptr,
117*3ee4fc2aSCody Peter Mello const char *whatrtn)
118*3ee4fc2aSCody Peter Mello {
119*3ee4fc2aSCody Peter Mello if (minlen > *psiz) {
120*3ee4fc2aSCody Peter Mello char *tbuf;
121*3ee4fc2aSCody Peter Mello int rminlen = quantum ? minlen % quantum : 0;
122*3ee4fc2aSCody Peter Mello int boff = pbptr ? *pbptr - *pbuf : 0;
123*3ee4fc2aSCody Peter Mello /* round up to next multiple of quantum */
124*3ee4fc2aSCody Peter Mello if (rminlen)
125*3ee4fc2aSCody Peter Mello minlen += quantum - rminlen;
126*3ee4fc2aSCody Peter Mello tbuf = (char *)realloc(*pbuf, minlen);
127*3ee4fc2aSCody Peter Mello dprintf(("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn,
128*3ee4fc2aSCody Peter Mello *psiz, minlen, (void *)*pbuf, (void *)tbuf));
129*3ee4fc2aSCody Peter Mello if (tbuf == NULL) {
130*3ee4fc2aSCody Peter Mello if (whatrtn)
131*3ee4fc2aSCody Peter Mello FATAL("out of memory in %s", whatrtn);
132*3ee4fc2aSCody Peter Mello return (0);
133*3ee4fc2aSCody Peter Mello }
134*3ee4fc2aSCody Peter Mello *pbuf = tbuf;
135*3ee4fc2aSCody Peter Mello *psiz = minlen;
136*3ee4fc2aSCody Peter Mello if (pbptr)
137*3ee4fc2aSCody Peter Mello *pbptr = tbuf + boff;
138*3ee4fc2aSCody Peter Mello }
139*3ee4fc2aSCody Peter Mello return (1);
140*3ee4fc2aSCody Peter Mello }
1411ee2e5faSnakanon
1421ee2e5faSnakanon void
run(Node * a)143*3ee4fc2aSCody Peter Mello run(Node *a) /* execution of parse tree starts here */
1447c478bd9Sstevel@tonic-gate {
145*3ee4fc2aSCody Peter Mello extern void stdinit(void);
146*3ee4fc2aSCody Peter Mello
147*3ee4fc2aSCody Peter Mello stdinit();
1481ee2e5faSnakanon (void) execute(a);
1497c478bd9Sstevel@tonic-gate closeall();
1507c478bd9Sstevel@tonic-gate }
1517c478bd9Sstevel@tonic-gate
1521ee2e5faSnakanon static Cell *
execute(Node * u)153*3ee4fc2aSCody Peter Mello execute(Node *u) /* execute a node of the parse tree */
1547c478bd9Sstevel@tonic-gate {
155*3ee4fc2aSCody Peter Mello Cell *(*proc)(Node **, int);
156*3ee4fc2aSCody Peter Mello Cell *x;
157*3ee4fc2aSCody Peter Mello Node *a;
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate if (u == NULL)
160*3ee4fc2aSCody Peter Mello return (True);
1617c478bd9Sstevel@tonic-gate for (a = u; ; a = a->nnext) {
1627c478bd9Sstevel@tonic-gate curnode = a;
1637c478bd9Sstevel@tonic-gate if (isvalue(a)) {
1647c478bd9Sstevel@tonic-gate x = (Cell *) (a->narg[0]);
165*3ee4fc2aSCody Peter Mello if (isfld(x) && !donefld)
1667c478bd9Sstevel@tonic-gate fldbld();
167*3ee4fc2aSCody Peter Mello else if (isrec(x) && !donerec)
1687c478bd9Sstevel@tonic-gate recbld();
1691ee2e5faSnakanon return (x);
1707c478bd9Sstevel@tonic-gate }
1711ee2e5faSnakanon /* probably a Cell* but too risky to print */
1721ee2e5faSnakanon if (notlegal(a->nobj))
173*3ee4fc2aSCody Peter Mello FATAL("illegal statement");
1747c478bd9Sstevel@tonic-gate proc = proctab[a->nobj-FIRSTTOKEN];
1757c478bd9Sstevel@tonic-gate x = (*proc)(a->narg, a->nobj);
176*3ee4fc2aSCody Peter Mello if (isfld(x) && !donefld)
1777c478bd9Sstevel@tonic-gate fldbld();
178*3ee4fc2aSCody Peter Mello else if (isrec(x) && !donerec)
1797c478bd9Sstevel@tonic-gate recbld();
1807c478bd9Sstevel@tonic-gate if (isexpr(a))
1811ee2e5faSnakanon return (x);
1827c478bd9Sstevel@tonic-gate /* a statement, goto next statement */
1837c478bd9Sstevel@tonic-gate if (isjump(x))
1841ee2e5faSnakanon return (x);
185*3ee4fc2aSCody Peter Mello if (a->nnext == NULL)
1861ee2e5faSnakanon return (x);
187*3ee4fc2aSCody Peter Mello tempfree(x);
1887c478bd9Sstevel@tonic-gate }
1897c478bd9Sstevel@tonic-gate }
1907c478bd9Sstevel@tonic-gate
191*3ee4fc2aSCody Peter Mello /* execute an awk program */
192*3ee4fc2aSCody Peter Mello /* a[0] = BEGIN, a[1] = body, a[2] = END */
1931ee2e5faSnakanon /*ARGSUSED*/
1941ee2e5faSnakanon Cell *
program(Node ** a,int n)1951ee2e5faSnakanon program(Node **a, int n)
1967c478bd9Sstevel@tonic-gate {
197*3ee4fc2aSCody Peter Mello Cell *x;
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate if (setjmp(env) != 0)
2007c478bd9Sstevel@tonic-gate goto ex;
2017c478bd9Sstevel@tonic-gate if (a[0]) { /* BEGIN */
2027c478bd9Sstevel@tonic-gate x = execute(a[0]);
2037c478bd9Sstevel@tonic-gate if (isexit(x))
204*3ee4fc2aSCody Peter Mello return (True);
2051ee2e5faSnakanon if (isjump(x)) {
206*3ee4fc2aSCody Peter Mello FATAL("illegal break, continue, next or nextfile "
207*3ee4fc2aSCody Peter Mello "from BEGIN");
2081ee2e5faSnakanon }
209*3ee4fc2aSCody Peter Mello tempfree(x);
2107c478bd9Sstevel@tonic-gate }
2117c478bd9Sstevel@tonic-gate if (a[1] || a[2])
212*3ee4fc2aSCody Peter Mello while (getrec(&record, &recsize, 1) > 0) {
2137c478bd9Sstevel@tonic-gate x = execute(a[1]);
2147c478bd9Sstevel@tonic-gate if (isexit(x))
2157c478bd9Sstevel@tonic-gate break;
216*3ee4fc2aSCody Peter Mello tempfree(x);
2177c478bd9Sstevel@tonic-gate }
2181ee2e5faSnakanon ex:
219*3ee4fc2aSCody Peter Mello if (setjmp(env) != 0) /* handles exit within END */
2207c478bd9Sstevel@tonic-gate goto ex1;
2217c478bd9Sstevel@tonic-gate if (a[2]) { /* END */
2227c478bd9Sstevel@tonic-gate x = execute(a[2]);
223*3ee4fc2aSCody Peter Mello if (isbreak(x) || isnext(x) || iscont(x))
224*3ee4fc2aSCody Peter Mello FATAL("illegal break, continue, next or nextfile "
225*3ee4fc2aSCody Peter Mello "from END");
226*3ee4fc2aSCody Peter Mello tempfree(x);
2277c478bd9Sstevel@tonic-gate }
2281ee2e5faSnakanon ex1:
229*3ee4fc2aSCody Peter Mello return (True);
2307c478bd9Sstevel@tonic-gate }
2317c478bd9Sstevel@tonic-gate
232*3ee4fc2aSCody Peter Mello struct Frame { /* stack frame for awk function calls */
2337c478bd9Sstevel@tonic-gate int nargs; /* number of arguments in this call */
2347c478bd9Sstevel@tonic-gate Cell *fcncell; /* pointer to Cell for function */
2357c478bd9Sstevel@tonic-gate Cell **args; /* pointer to array of arguments after execute */
2367c478bd9Sstevel@tonic-gate Cell *retval; /* return value */
2377c478bd9Sstevel@tonic-gate };
2387c478bd9Sstevel@tonic-gate
239*3ee4fc2aSCody Peter Mello #define NARGS 50 /* max args in a call */
2407c478bd9Sstevel@tonic-gate
241*3ee4fc2aSCody Peter Mello struct Frame *frame = NULL; /* base of stack frames; dynamically alloc'd */
2427c478bd9Sstevel@tonic-gate int nframe = 0; /* number of frames allocated */
2437c478bd9Sstevel@tonic-gate struct Frame *fp = NULL; /* frame pointer. bottom level unused */
2447c478bd9Sstevel@tonic-gate
2451ee2e5faSnakanon /*ARGSUSED*/
2461ee2e5faSnakanon Cell *
call(Node ** a,int n)247*3ee4fc2aSCody Peter Mello call(Node **a, int n) /* function call. very kludgy and fragile */
2487c478bd9Sstevel@tonic-gate {
2491ee2e5faSnakanon static Cell newcopycell =
250*3ee4fc2aSCody Peter Mello { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE, NULL };
251*3ee4fc2aSCody Peter Mello int i, ncall, ndef;
252*3ee4fc2aSCody Peter Mello /* handles potential double freeing when fcn & param share a tempcell */
253*3ee4fc2aSCody Peter Mello int freed = 0;
2547c478bd9Sstevel@tonic-gate Node *x;
255*3ee4fc2aSCody Peter Mello Cell *args[NARGS], *oargs[NARGS]; /* BUG: fixed size arrays */
256*3ee4fc2aSCody Peter Mello Cell *y, *z, *fcn;
257*3ee4fc2aSCody Peter Mello char *s;
2587c478bd9Sstevel@tonic-gate
2597c478bd9Sstevel@tonic-gate fcn = execute(a[0]); /* the function itself */
2607c478bd9Sstevel@tonic-gate s = fcn->nval;
261*3ee4fc2aSCody Peter Mello if (!isfcn(fcn))
262*3ee4fc2aSCody Peter Mello FATAL("calling undefined function %s", s);
2637c478bd9Sstevel@tonic-gate if (frame == NULL) {
2641ee2e5faSnakanon fp = frame = (struct Frame *)calloc(nframe += 100,
2651ee2e5faSnakanon sizeof (struct Frame));
2661ee2e5faSnakanon if (frame == NULL) {
267*3ee4fc2aSCody Peter Mello FATAL("out of space for stack frames calling %s", s);
2681ee2e5faSnakanon }
2697c478bd9Sstevel@tonic-gate }
2701ee2e5faSnakanon for (ncall = 0, x = a[1]; x != NULL; x = x->nnext) /* args in call */
2717c478bd9Sstevel@tonic-gate ncall++;
2721ee2e5faSnakanon ndef = (int)fcn->fval; /* args in defn */
2731ee2e5faSnakanon dprintf(("calling %s, %d args (%d in defn), fp=%d\n",
2741ee2e5faSnakanon s, ncall, ndef, fp-frame));
2751ee2e5faSnakanon if (ncall > ndef) {
276*3ee4fc2aSCody Peter Mello WARNING("function %s called with %d args, uses only %d",
277*3ee4fc2aSCody Peter Mello s, ncall, ndef);
2781ee2e5faSnakanon }
2791ee2e5faSnakanon if (ncall + ndef > NARGS) {
280*3ee4fc2aSCody Peter Mello FATAL("function %s has %d arguments, limit %d",
281*3ee4fc2aSCody Peter Mello s, ncall+ndef, NARGS);
2821ee2e5faSnakanon }
2831ee2e5faSnakanon for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) {
2841ee2e5faSnakanon /* get call args */
2851ee2e5faSnakanon dprintf(("evaluate args[%d], fp=%d:\n", i, fp-frame));
2867c478bd9Sstevel@tonic-gate y = execute(x);
2877c478bd9Sstevel@tonic-gate oargs[i] = y;
2881ee2e5faSnakanon dprintf(("args[%d]: %s %f <%s>, t=%o\n",
289*3ee4fc2aSCody Peter Mello i, NN(y->nval), y->fval,
290*3ee4fc2aSCody Peter Mello isarr(y) ? "(array)" : NN(y->sval), y->tval));
291*3ee4fc2aSCody Peter Mello if (isfcn(y)) {
292*3ee4fc2aSCody Peter Mello FATAL("can't use function %s as argument in %s",
293*3ee4fc2aSCody Peter Mello y->nval, s);
2941ee2e5faSnakanon }
2957c478bd9Sstevel@tonic-gate if (isarr(y))
2967c478bd9Sstevel@tonic-gate args[i] = y; /* arrays by ref */
2977c478bd9Sstevel@tonic-gate else
2987c478bd9Sstevel@tonic-gate args[i] = copycell(y);
299*3ee4fc2aSCody Peter Mello tempfree(y);
3007c478bd9Sstevel@tonic-gate }
301*3ee4fc2aSCody Peter Mello for (; i < ndef; i++) { /* add null args for ones not provided */
302*3ee4fc2aSCody Peter Mello args[i] = gettemp();
3037c478bd9Sstevel@tonic-gate *args[i] = newcopycell;
3047c478bd9Sstevel@tonic-gate }
3057c478bd9Sstevel@tonic-gate fp++; /* now ok to up frame */
3067c478bd9Sstevel@tonic-gate if (fp >= frame + nframe) {
3077c478bd9Sstevel@tonic-gate int dfp = fp - frame; /* old index */
3087c478bd9Sstevel@tonic-gate frame = (struct Frame *)
3091ee2e5faSnakanon realloc(frame, (nframe += 100) * sizeof (struct Frame));
3107c478bd9Sstevel@tonic-gate if (frame == NULL)
311*3ee4fc2aSCody Peter Mello FATAL("out of space for stack frames in %s", s);
3127c478bd9Sstevel@tonic-gate fp = frame + dfp;
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate fp->fcncell = fcn;
3157c478bd9Sstevel@tonic-gate fp->args = args;
3167c478bd9Sstevel@tonic-gate fp->nargs = ndef; /* number defined with (excess are locals) */
317*3ee4fc2aSCody Peter Mello fp->retval = gettemp();
3187c478bd9Sstevel@tonic-gate
3191ee2e5faSnakanon dprintf(("start exec of %s, fp=%d\n", s, fp-frame));
3201ee2e5faSnakanon /*LINTED align*/
3217c478bd9Sstevel@tonic-gate y = execute((Node *)(fcn->sval)); /* execute body */
3221ee2e5faSnakanon dprintf(("finished exec of %s, fp=%d\n", s, fp-frame));
3237c478bd9Sstevel@tonic-gate
3247c478bd9Sstevel@tonic-gate for (i = 0; i < ndef; i++) {
3257c478bd9Sstevel@tonic-gate Cell *t = fp->args[i];
3267c478bd9Sstevel@tonic-gate if (isarr(t)) {
3277c478bd9Sstevel@tonic-gate if (t->csub == CCOPY) {
3287c478bd9Sstevel@tonic-gate if (i >= ncall) {
3297c478bd9Sstevel@tonic-gate freesymtab(t);
3307c478bd9Sstevel@tonic-gate t->csub = CTEMP;
331*3ee4fc2aSCody Peter Mello tempfree(t);
3327c478bd9Sstevel@tonic-gate } else {
3337c478bd9Sstevel@tonic-gate oargs[i]->tval = t->tval;
3347c478bd9Sstevel@tonic-gate oargs[i]->tval &= ~(STR|NUM|DONTFREE);
3357c478bd9Sstevel@tonic-gate oargs[i]->sval = t->sval;
336*3ee4fc2aSCody Peter Mello tempfree(t);
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate }
339*3ee4fc2aSCody Peter Mello } else if (t != y) { /* kludge to prevent freeing twice */
3407c478bd9Sstevel@tonic-gate t->csub = CTEMP;
341*3ee4fc2aSCody Peter Mello tempfree(t);
342*3ee4fc2aSCody Peter Mello } else if (t == y && t->csub == CCOPY) {
343*3ee4fc2aSCody Peter Mello t->csub = CTEMP;
344*3ee4fc2aSCody Peter Mello tempfree(t);
345*3ee4fc2aSCody Peter Mello freed = 1;
3467c478bd9Sstevel@tonic-gate }
3477c478bd9Sstevel@tonic-gate }
348*3ee4fc2aSCody Peter Mello tempfree(fcn);
3497c478bd9Sstevel@tonic-gate if (isexit(y) || isnext(y))
3501ee2e5faSnakanon return (y);
351*3ee4fc2aSCody Peter Mello if (freed == 0) {
352*3ee4fc2aSCody Peter Mello tempfree(y); /* don't free twice! */
353*3ee4fc2aSCody Peter Mello }
3547c478bd9Sstevel@tonic-gate z = fp->retval; /* return value */
3551ee2e5faSnakanon dprintf(("%s returns %g |%s| %o\n",
3561ee2e5faSnakanon s, getfval(z), getsval(z), z->tval));
3577c478bd9Sstevel@tonic-gate fp--;
3581ee2e5faSnakanon return (z);
3597c478bd9Sstevel@tonic-gate }
3607c478bd9Sstevel@tonic-gate
3611ee2e5faSnakanon static Cell *
copycell(Cell * x)3621ee2e5faSnakanon copycell(Cell *x) /* make a copy of a cell in a temp */
3637c478bd9Sstevel@tonic-gate {
3647c478bd9Sstevel@tonic-gate Cell *y;
3657c478bd9Sstevel@tonic-gate
366*3ee4fc2aSCody Peter Mello /* copy is not constant or field */
367*3ee4fc2aSCody Peter Mello
368*3ee4fc2aSCody Peter Mello y = gettemp();
369*3ee4fc2aSCody Peter Mello y->tval = x->tval & ~(CON|FLD|REC);
3707c478bd9Sstevel@tonic-gate y->csub = CCOPY; /* prevents freeing until call is over */
371*3ee4fc2aSCody Peter Mello y->nval = x->nval; /* BUG? */
372*3ee4fc2aSCody Peter Mello if (isstr(x)) {
373*3ee4fc2aSCody Peter Mello y->sval = tostring(x->sval);
374*3ee4fc2aSCody Peter Mello y->tval &= ~DONTFREE;
375*3ee4fc2aSCody Peter Mello } else
376*3ee4fc2aSCody Peter Mello y->tval |= DONTFREE;
3777c478bd9Sstevel@tonic-gate y->fval = x->fval;
3781ee2e5faSnakanon return (y);
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate
3811ee2e5faSnakanon /*ARGSUSED*/
3821ee2e5faSnakanon Cell *
arg(Node ** a,int nnn)383*3ee4fc2aSCody Peter Mello arg(Node **a, int nnn) /* nth argument of a function */
3847c478bd9Sstevel@tonic-gate {
3857c478bd9Sstevel@tonic-gate int n;
3867c478bd9Sstevel@tonic-gate
387*3ee4fc2aSCody Peter Mello n = ptoi(a[0]); /* argument number, counting from 0 */
3881ee2e5faSnakanon dprintf(("arg(%d), fp->nargs=%d\n", n, fp->nargs));
3891ee2e5faSnakanon if (n+1 > fp->nargs) {
390*3ee4fc2aSCody Peter Mello FATAL("argument #%d of function %s was not supplied",
391*3ee4fc2aSCody Peter Mello n+1, fp->fcncell->nval);
3921ee2e5faSnakanon }
3931ee2e5faSnakanon return (fp->args[n]);
3947c478bd9Sstevel@tonic-gate }
3957c478bd9Sstevel@tonic-gate
3961ee2e5faSnakanon Cell *
jump(Node ** a,int n)397*3ee4fc2aSCody Peter Mello jump(Node **a, int n) /* break, continue, next, nextfile, return */
3987c478bd9Sstevel@tonic-gate {
399*3ee4fc2aSCody Peter Mello Cell *y;
4007c478bd9Sstevel@tonic-gate
4017c478bd9Sstevel@tonic-gate switch (n) {
4027c478bd9Sstevel@tonic-gate case EXIT:
4037c478bd9Sstevel@tonic-gate if (a[0] != NULL) {
4047c478bd9Sstevel@tonic-gate y = execute(a[0]);
40512809310Snakanon errorflag = (int)getfval(y);
406*3ee4fc2aSCody Peter Mello tempfree(y);
4077c478bd9Sstevel@tonic-gate }
4087c478bd9Sstevel@tonic-gate longjmp(env, 1);
4091ee2e5faSnakanon /*NOTREACHED*/
4107c478bd9Sstevel@tonic-gate case RETURN:
4117c478bd9Sstevel@tonic-gate if (a[0] != NULL) {
4127c478bd9Sstevel@tonic-gate y = execute(a[0]);
4137c478bd9Sstevel@tonic-gate if ((y->tval & (STR|NUM)) == (STR|NUM)) {
4141ee2e5faSnakanon (void) setsval(fp->retval, getsval(y));
4157c478bd9Sstevel@tonic-gate fp->retval->fval = getfval(y);
4167c478bd9Sstevel@tonic-gate fp->retval->tval |= NUM;
4171ee2e5faSnakanon } else if (y->tval & STR)
4181ee2e5faSnakanon (void) setsval(fp->retval, getsval(y));
4197c478bd9Sstevel@tonic-gate else if (y->tval & NUM)
4201ee2e5faSnakanon (void) setfval(fp->retval, getfval(y));
421*3ee4fc2aSCody Peter Mello else /* can't happen */
422*3ee4fc2aSCody Peter Mello FATAL("bad type variable %d", y->tval);
423*3ee4fc2aSCody Peter Mello tempfree(y);
4247c478bd9Sstevel@tonic-gate }
4251ee2e5faSnakanon return (jret);
4267c478bd9Sstevel@tonic-gate case NEXT:
4271ee2e5faSnakanon return (jnext);
428*3ee4fc2aSCody Peter Mello case NEXTFILE:
429*3ee4fc2aSCody Peter Mello nextfile();
430*3ee4fc2aSCody Peter Mello return (jnextfile);
4317c478bd9Sstevel@tonic-gate case BREAK:
4321ee2e5faSnakanon return (jbreak);
4337c478bd9Sstevel@tonic-gate case CONTINUE:
4341ee2e5faSnakanon return (jcont);
4357c478bd9Sstevel@tonic-gate default: /* can't happen */
436*3ee4fc2aSCody Peter Mello FATAL("illegal jump type %d", n);
4377c478bd9Sstevel@tonic-gate }
4381ee2e5faSnakanon /*NOTREACHED*/
4391ee2e5faSnakanon return (NULL);
4407c478bd9Sstevel@tonic-gate }
4417c478bd9Sstevel@tonic-gate
4421ee2e5faSnakanon Cell *
awkgetline(Node ** a,int n)443*3ee4fc2aSCody Peter Mello awkgetline(Node **a, int n) /* get next line from specific input */
4447c478bd9Sstevel@tonic-gate {
4457c478bd9Sstevel@tonic-gate /* a[0] is variable, a[1] is operator, a[2] is filename */
446*3ee4fc2aSCody Peter Mello Cell *r, *x;
4477c478bd9Sstevel@tonic-gate FILE *fp;
448*3ee4fc2aSCody Peter Mello char *buf;
449*3ee4fc2aSCody Peter Mello size_t bufsize = recsize;
450*3ee4fc2aSCody Peter Mello int mode;
451*3ee4fc2aSCody Peter Mello
452*3ee4fc2aSCody Peter Mello if ((buf = (char *)malloc(bufsize)) == NULL)
453*3ee4fc2aSCody Peter Mello FATAL("out of memory in getline");
4547c478bd9Sstevel@tonic-gate
4551ee2e5faSnakanon (void) fflush(stdout); /* in case someone is waiting for a prompt */
456*3ee4fc2aSCody Peter Mello r = gettemp();
4577c478bd9Sstevel@tonic-gate if (a[1] != NULL) { /* getline < file */
4587c478bd9Sstevel@tonic-gate x = execute(a[2]); /* filename */
459*3ee4fc2aSCody Peter Mello mode = ptoi(a[1]);
460*3ee4fc2aSCody Peter Mello if (mode == '|') /* input pipe */
461*3ee4fc2aSCody Peter Mello mode = LE; /* arbitrary flag */
462*3ee4fc2aSCody Peter Mello fp = openfile(mode, getsval(x));
463*3ee4fc2aSCody Peter Mello tempfree(x);
4647c478bd9Sstevel@tonic-gate if (fp == NULL)
4657c478bd9Sstevel@tonic-gate n = -1;
4667c478bd9Sstevel@tonic-gate else
467*3ee4fc2aSCody Peter Mello n = readrec(&buf, &bufsize, fp);
468*3ee4fc2aSCody Peter Mello /*LINTED if*/
469*3ee4fc2aSCody Peter Mello if (n <= 0) {
470*3ee4fc2aSCody Peter Mello ;
471*3ee4fc2aSCody Peter Mello } else if (a[0] != NULL) { /* getline var <file */
472*3ee4fc2aSCody Peter Mello x = execute(a[0]);
473*3ee4fc2aSCody Peter Mello (void) setsval(x, buf);
474*3ee4fc2aSCody Peter Mello tempfree(x);
475*3ee4fc2aSCody Peter Mello } else { /* getline <file */
476*3ee4fc2aSCody Peter Mello (void) setsval(recloc, buf);
477*3ee4fc2aSCody Peter Mello if (is_number(recloc->sval)) {
478*3ee4fc2aSCody Peter Mello recloc->fval = atof(recloc->sval);
479*3ee4fc2aSCody Peter Mello recloc->tval |= NUM;
4801ee2e5faSnakanon }
4817c478bd9Sstevel@tonic-gate }
4827c478bd9Sstevel@tonic-gate } else { /* bare getline; use current input */
4837c478bd9Sstevel@tonic-gate if (a[0] == NULL) /* getline */
484*3ee4fc2aSCody Peter Mello n = getrec(&record, &recsize, 1);
4857c478bd9Sstevel@tonic-gate else { /* getline var */
486*3ee4fc2aSCody Peter Mello n = getrec(&buf, &bufsize, 0);
487*3ee4fc2aSCody Peter Mello x = execute(a[0]);
488*3ee4fc2aSCody Peter Mello (void) setsval(x, buf);
489*3ee4fc2aSCody Peter Mello tempfree(x);
4907c478bd9Sstevel@tonic-gate }
4917c478bd9Sstevel@tonic-gate }
4921ee2e5faSnakanon (void) setfval(r, (Awkfloat)n);
493*3ee4fc2aSCody Peter Mello free(buf);
4941ee2e5faSnakanon return (r);
4957c478bd9Sstevel@tonic-gate }
4967c478bd9Sstevel@tonic-gate
4971ee2e5faSnakanon /*ARGSUSED*/
4981ee2e5faSnakanon Cell *
getnf(Node ** a,int n)499*3ee4fc2aSCody Peter Mello getnf(Node **a, int n) /* get NF */
5007c478bd9Sstevel@tonic-gate {
5017c478bd9Sstevel@tonic-gate if (donefld == 0)
5027c478bd9Sstevel@tonic-gate fldbld();
5031ee2e5faSnakanon return ((Cell *)a[0]);
5047c478bd9Sstevel@tonic-gate }
5057c478bd9Sstevel@tonic-gate
5061ee2e5faSnakanon /*ARGSUSED*/
5071ee2e5faSnakanon Cell *
array(Node ** a,int n)508*3ee4fc2aSCody Peter Mello array(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
5097c478bd9Sstevel@tonic-gate {
510*3ee4fc2aSCody Peter Mello Cell *x, *y, *z;
511*3ee4fc2aSCody Peter Mello char *s;
512*3ee4fc2aSCody Peter Mello Node *np;
513*3ee4fc2aSCody Peter Mello char *buf;
514*3ee4fc2aSCody Peter Mello size_t bufsz = recsize;
515*3ee4fc2aSCody Peter Mello size_t tlen = 0, len, nsub;
516*3ee4fc2aSCody Peter Mello
517*3ee4fc2aSCody Peter Mello if ((buf = (char *)malloc(bufsz)) == NULL)
518*3ee4fc2aSCody Peter Mello FATAL("out of memory in array");
5197c478bd9Sstevel@tonic-gate
5207c478bd9Sstevel@tonic-gate x = execute(a[0]); /* Cell* for symbol table */
5211ee2e5faSnakanon buf[0] = '\0';
522*3ee4fc2aSCody Peter Mello for (np = a[1]; np != NULL; np = np->nnext) {
5237c478bd9Sstevel@tonic-gate y = execute(np); /* subscript */
5247c478bd9Sstevel@tonic-gate s = getsval(y);
525*3ee4fc2aSCody Peter Mello len = strlen(s);
526*3ee4fc2aSCody Peter Mello nsub = strlen(getsval(subseploc));
527*3ee4fc2aSCody Peter Mello (void) adjbuf(&buf, &bufsz, tlen + len + nsub + 1,
528*3ee4fc2aSCody Peter Mello recsize, 0, "array");
5291ee2e5faSnakanon (void) memcpy(&buf[tlen], s, len);
5301ee2e5faSnakanon tlen += len;
5311ee2e5faSnakanon if (np->nnext) {
532*3ee4fc2aSCody Peter Mello (void) memcpy(&buf[tlen], *SUBSEP, nsub);
533*3ee4fc2aSCody Peter Mello tlen += nsub;
5341ee2e5faSnakanon }
5351ee2e5faSnakanon buf[tlen] = '\0';
536*3ee4fc2aSCody Peter Mello tempfree(y);
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate if (!isarr(x)) {
539*3ee4fc2aSCody Peter Mello dprintf(("making %s into an array\n", NN(x->nval)));
5407c478bd9Sstevel@tonic-gate if (freeable(x))
5417c478bd9Sstevel@tonic-gate xfree(x->sval);
5427c478bd9Sstevel@tonic-gate x->tval &= ~(STR|NUM|DONTFREE);
5437c478bd9Sstevel@tonic-gate x->tval |= ARR;
544*3ee4fc2aSCody Peter Mello x->sval = (char *)makesymtab(NSYMTAB);
5457c478bd9Sstevel@tonic-gate }
5461ee2e5faSnakanon /*LINTED align*/
547*3ee4fc2aSCody Peter Mello z = setsymtab(buf, "", 0.0, STR|NUM, (Array *)x->sval);
5487c478bd9Sstevel@tonic-gate z->ctype = OCELL;
5497c478bd9Sstevel@tonic-gate z->csub = CVAR;
550*3ee4fc2aSCody Peter Mello tempfree(x);
5511ee2e5faSnakanon free(buf);
5521ee2e5faSnakanon return (z);
5537c478bd9Sstevel@tonic-gate }
5547c478bd9Sstevel@tonic-gate
5551ee2e5faSnakanon /*ARGSUSED*/
5561ee2e5faSnakanon Cell *
awkdelete(Node ** a,int n)557*3ee4fc2aSCody Peter Mello awkdelete(Node **a, int n) /* a[0] is symtab, a[1] is list of subscripts */
5587c478bd9Sstevel@tonic-gate {
5597c478bd9Sstevel@tonic-gate Cell *x, *y;
5607c478bd9Sstevel@tonic-gate Node *np;
561*3ee4fc2aSCody Peter Mello char *s;
562*3ee4fc2aSCody Peter Mello size_t nsub;
563*3ee4fc2aSCody Peter Mello size_t tlen = 0, len;
5647c478bd9Sstevel@tonic-gate
5657c478bd9Sstevel@tonic-gate x = execute(a[0]); /* Cell* for symbol table */
566*3ee4fc2aSCody Peter Mello if (x == symtabloc) {
567*3ee4fc2aSCody Peter Mello FATAL("cannot delete SYMTAB or its elements");
568*3ee4fc2aSCody Peter Mello }
569*3ee4fc2aSCody Peter Mello if (!isarr(x)) {
570*3ee4fc2aSCody Peter Mello dprintf(("making %s into an array\n", x->nval));
571*3ee4fc2aSCody Peter Mello if (freeable(x))
572*3ee4fc2aSCody Peter Mello xfree(x->sval);
573*3ee4fc2aSCody Peter Mello x->tval &= ~(STR|NUM|DONTFREE);
574*3ee4fc2aSCody Peter Mello x->tval |= ARR;
575*3ee4fc2aSCody Peter Mello x->sval = (char *)makesymtab(NSYMTAB);
576*3ee4fc2aSCody Peter Mello }
577*3ee4fc2aSCody Peter Mello if (a[1] == NULL) { /* delete the elements, not the table */
578*3ee4fc2aSCody Peter Mello freesymtab(x);
579*3ee4fc2aSCody Peter Mello x->tval &= ~STR;
580*3ee4fc2aSCody Peter Mello x->tval |= ARR;
581*3ee4fc2aSCody Peter Mello x->sval = (char *)makesymtab(NSYMTAB);
582*3ee4fc2aSCody Peter Mello } else {
583*3ee4fc2aSCody Peter Mello size_t bufsz = recsize;
584*3ee4fc2aSCody Peter Mello char *buf;
585*3ee4fc2aSCody Peter Mello if ((buf = (char *)malloc(bufsz)) == NULL)
586*3ee4fc2aSCody Peter Mello FATAL("out of memory in awkdelete");
587*3ee4fc2aSCody Peter Mello buf[0] = '\0';
588*3ee4fc2aSCody Peter Mello for (np = a[1]; np != NULL; np = np->nnext) {
589*3ee4fc2aSCody Peter Mello y = execute(np); /* subscript */
590*3ee4fc2aSCody Peter Mello s = getsval(y);
591*3ee4fc2aSCody Peter Mello len = strlen(s);
592*3ee4fc2aSCody Peter Mello nsub = strlen(getsval(subseploc));
593*3ee4fc2aSCody Peter Mello (void) adjbuf(&buf, &bufsz, tlen + len + nsub + 1,
594*3ee4fc2aSCody Peter Mello recsize, 0, "awkdelete");
595*3ee4fc2aSCody Peter Mello (void) memcpy(&buf[tlen], s, len);
596*3ee4fc2aSCody Peter Mello tlen += len;
597*3ee4fc2aSCody Peter Mello if (np->nnext) {
598*3ee4fc2aSCody Peter Mello (void) memcpy(&buf[tlen], *SUBSEP, nsub);
599*3ee4fc2aSCody Peter Mello tlen += nsub;
600*3ee4fc2aSCody Peter Mello }
601*3ee4fc2aSCody Peter Mello buf[tlen] = '\0';
602*3ee4fc2aSCody Peter Mello tempfree(y);
6031ee2e5faSnakanon }
604*3ee4fc2aSCody Peter Mello freeelem(x, buf);
605*3ee4fc2aSCody Peter Mello free(buf);
6067c478bd9Sstevel@tonic-gate }
607*3ee4fc2aSCody Peter Mello tempfree(x);
608*3ee4fc2aSCody Peter Mello return (True);
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate
6111ee2e5faSnakanon /*ARGSUSED*/
6121ee2e5faSnakanon Cell *
intest(Node ** a,int n)613*3ee4fc2aSCody Peter Mello intest(Node **a, int n) /* a[0] is index (list), a[1] is symtab */
6147c478bd9Sstevel@tonic-gate {
615*3ee4fc2aSCody Peter Mello Cell *x, *ap, *k;
6167c478bd9Sstevel@tonic-gate Node *p;
617*3ee4fc2aSCody Peter Mello char *buf;
618*3ee4fc2aSCody Peter Mello char *s;
619*3ee4fc2aSCody Peter Mello size_t bufsz = recsize;
620*3ee4fc2aSCody Peter Mello size_t nsub;
621*3ee4fc2aSCody Peter Mello size_t tlen = 0, len;
6227c478bd9Sstevel@tonic-gate
6237c478bd9Sstevel@tonic-gate ap = execute(a[1]); /* array name */
624*3ee4fc2aSCody Peter Mello if (!isarr(ap)) {
625*3ee4fc2aSCody Peter Mello dprintf(("making %s into an array\n", ap->nval));
626*3ee4fc2aSCody Peter Mello if (freeable(ap))
627*3ee4fc2aSCody Peter Mello xfree(ap->sval);
628*3ee4fc2aSCody Peter Mello ap->tval &= ~(STR|NUM|DONTFREE);
629*3ee4fc2aSCody Peter Mello ap->tval |= ARR;
630*3ee4fc2aSCody Peter Mello ap->sval = (char *)makesymtab(NSYMTAB);
631*3ee4fc2aSCody Peter Mello }
632*3ee4fc2aSCody Peter Mello if ((buf = (char *)malloc(bufsz)) == NULL) {
633*3ee4fc2aSCody Peter Mello FATAL("out of memory in intest");
634*3ee4fc2aSCody Peter Mello }
635*3ee4fc2aSCody Peter Mello buf[0] = '\0';
636*3ee4fc2aSCody Peter Mello for (p = a[0]; p != NULL; p = p->nnext) {
6377c478bd9Sstevel@tonic-gate x = execute(p); /* expr */
6387c478bd9Sstevel@tonic-gate s = getsval(x);
639*3ee4fc2aSCody Peter Mello len = strlen(s);
640*3ee4fc2aSCody Peter Mello nsub = strlen(getsval(subseploc));
641*3ee4fc2aSCody Peter Mello (void) adjbuf(&buf, &bufsz, tlen + len + nsub + 1,
642*3ee4fc2aSCody Peter Mello recsize, 0, "intest");
6431ee2e5faSnakanon (void) memcpy(&buf[tlen], s, len);
6441ee2e5faSnakanon tlen += len;
645*3ee4fc2aSCody Peter Mello tempfree(x);
6461ee2e5faSnakanon if (p->nnext) {
647*3ee4fc2aSCody Peter Mello (void) memcpy(&buf[tlen], *SUBSEP, nsub);
648*3ee4fc2aSCody Peter Mello tlen += nsub;
6491ee2e5faSnakanon }
6501ee2e5faSnakanon buf[tlen] = '\0';
6517c478bd9Sstevel@tonic-gate }
6521ee2e5faSnakanon /*LINTED align*/
6531ee2e5faSnakanon k = lookup(buf, (Array *)ap->sval);
654*3ee4fc2aSCody Peter Mello tempfree(ap);
6551ee2e5faSnakanon free(buf);
6567c478bd9Sstevel@tonic-gate if (k == NULL)
657*3ee4fc2aSCody Peter Mello return (False);
6587c478bd9Sstevel@tonic-gate else
659*3ee4fc2aSCody Peter Mello return (True);
6607c478bd9Sstevel@tonic-gate }
6617c478bd9Sstevel@tonic-gate
6627c478bd9Sstevel@tonic-gate
6631ee2e5faSnakanon Cell *
matchop(Node ** a,int n)664*3ee4fc2aSCody Peter Mello matchop(Node **a, int n) /* ~ and match() */
6657c478bd9Sstevel@tonic-gate {
666*3ee4fc2aSCody Peter Mello Cell *x, *y;
667*3ee4fc2aSCody Peter Mello char *s, *t;
668*3ee4fc2aSCody Peter Mello int i;
6697c478bd9Sstevel@tonic-gate fa *pfa;
670*3ee4fc2aSCody Peter Mello int (*mf)(fa *, const char *) = match, mode = 0;
6717c478bd9Sstevel@tonic-gate
6727c478bd9Sstevel@tonic-gate if (n == MATCHFCN) {
6737c478bd9Sstevel@tonic-gate mf = pmatch;
6747c478bd9Sstevel@tonic-gate mode = 1;
6757c478bd9Sstevel@tonic-gate }
676*3ee4fc2aSCody Peter Mello x = execute(a[1]); /* a[1] = target text */
6777c478bd9Sstevel@tonic-gate s = getsval(x);
678*3ee4fc2aSCody Peter Mello if (a[0] == NULL) /* a[1] == 0: already-compiled reg expr */
679*3ee4fc2aSCody Peter Mello i = (*mf)((fa *)a[2], s);
6807c478bd9Sstevel@tonic-gate else {
681*3ee4fc2aSCody Peter Mello y = execute(a[2]); /* a[2] = regular expr */
6827c478bd9Sstevel@tonic-gate t = getsval(y);
6837c478bd9Sstevel@tonic-gate pfa = makedfa(t, mode);
6847c478bd9Sstevel@tonic-gate i = (*mf)(pfa, s);
685*3ee4fc2aSCody Peter Mello tempfree(y);
6867c478bd9Sstevel@tonic-gate }
687*3ee4fc2aSCody Peter Mello tempfree(x);
6887c478bd9Sstevel@tonic-gate if (n == MATCHFCN) {
6897c478bd9Sstevel@tonic-gate int start = patbeg - s + 1;
6907c478bd9Sstevel@tonic-gate if (patlen < 0)
6917c478bd9Sstevel@tonic-gate start = 0;
6921ee2e5faSnakanon (void) setfval(rstartloc, (Awkfloat)start);
6931ee2e5faSnakanon (void) setfval(rlengthloc, (Awkfloat)patlen);
694*3ee4fc2aSCody Peter Mello x = gettemp();
6957c478bd9Sstevel@tonic-gate x->tval = NUM;
6967c478bd9Sstevel@tonic-gate x->fval = start;
6971ee2e5faSnakanon return (x);
698*3ee4fc2aSCody Peter Mello } else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
699*3ee4fc2aSCody Peter Mello return (True);
7007c478bd9Sstevel@tonic-gate else
701*3ee4fc2aSCody Peter Mello return (False);
7027c478bd9Sstevel@tonic-gate }
7037c478bd9Sstevel@tonic-gate
7047c478bd9Sstevel@tonic-gate
7051ee2e5faSnakanon Cell *
boolop(Node ** a,int n)706*3ee4fc2aSCody Peter Mello boolop(Node **a, int n) /* a[0] || a[1], a[0] && a[1], !a[0] */
7077c478bd9Sstevel@tonic-gate {
708*3ee4fc2aSCody Peter Mello Cell *x, *y;
709*3ee4fc2aSCody Peter Mello int i;
7107c478bd9Sstevel@tonic-gate
7117c478bd9Sstevel@tonic-gate x = execute(a[0]);
7127c478bd9Sstevel@tonic-gate i = istrue(x);
713*3ee4fc2aSCody Peter Mello tempfree(x);
7147c478bd9Sstevel@tonic-gate switch (n) {
7157c478bd9Sstevel@tonic-gate case BOR:
7161ee2e5faSnakanon if (i)
717*3ee4fc2aSCody Peter Mello return (True);
7187c478bd9Sstevel@tonic-gate y = execute(a[1]);
7197c478bd9Sstevel@tonic-gate i = istrue(y);
720*3ee4fc2aSCody Peter Mello tempfree(y);
721*3ee4fc2aSCody Peter Mello return (i ? True : False);
7227c478bd9Sstevel@tonic-gate case AND:
7231ee2e5faSnakanon if (!i)
724*3ee4fc2aSCody Peter Mello return (False);
7257c478bd9Sstevel@tonic-gate y = execute(a[1]);
7267c478bd9Sstevel@tonic-gate i = istrue(y);
727*3ee4fc2aSCody Peter Mello tempfree(y);
728*3ee4fc2aSCody Peter Mello return (i ? True : False);
7297c478bd9Sstevel@tonic-gate case NOT:
730*3ee4fc2aSCody Peter Mello return (i ? False : True);
7317c478bd9Sstevel@tonic-gate default: /* can't happen */
732*3ee4fc2aSCody Peter Mello FATAL("unknown boolean operator %d", n);
7337c478bd9Sstevel@tonic-gate }
7347c478bd9Sstevel@tonic-gate /*NOTREACHED*/
7351ee2e5faSnakanon return (NULL);
7367c478bd9Sstevel@tonic-gate }
7377c478bd9Sstevel@tonic-gate
7381ee2e5faSnakanon Cell *
relop(Node ** a,int n)739*3ee4fc2aSCody Peter Mello relop(Node **a, int n) /* a[0] < a[1], etc. */
7407c478bd9Sstevel@tonic-gate {
741*3ee4fc2aSCody Peter Mello int i;
742*3ee4fc2aSCody Peter Mello Cell *x, *y;
7437c478bd9Sstevel@tonic-gate Awkfloat j;
7447c478bd9Sstevel@tonic-gate
7457c478bd9Sstevel@tonic-gate x = execute(a[0]);
7467c478bd9Sstevel@tonic-gate y = execute(a[1]);
7477c478bd9Sstevel@tonic-gate if (x->tval&NUM && y->tval&NUM) {
7487c478bd9Sstevel@tonic-gate j = x->fval - y->fval;
7491ee2e5faSnakanon i = j < 0 ? -1: (j > 0 ? 1: 0);
7507c478bd9Sstevel@tonic-gate } else {
751*3ee4fc2aSCody Peter Mello i = strcmp(getsval(x), getsval(y));
7527c478bd9Sstevel@tonic-gate }
753*3ee4fc2aSCody Peter Mello tempfree(x);
754*3ee4fc2aSCody Peter Mello tempfree(y);
7557c478bd9Sstevel@tonic-gate switch (n) {
756*3ee4fc2aSCody Peter Mello case LT: return (i < 0 ? True : False);
757*3ee4fc2aSCody Peter Mello case LE: return (i <= 0 ? True : False);
758*3ee4fc2aSCody Peter Mello case NE: return (i != 0 ? True : False);
759*3ee4fc2aSCody Peter Mello case EQ: return (i == 0 ? True : False);
760*3ee4fc2aSCody Peter Mello case GE: return (i >= 0 ? True : False);
761*3ee4fc2aSCody Peter Mello case GT: return (i > 0 ? True : False);
7627c478bd9Sstevel@tonic-gate default: /* can't happen */
763*3ee4fc2aSCody Peter Mello FATAL("unknown relational operator %d", n);
7647c478bd9Sstevel@tonic-gate }
7657c478bd9Sstevel@tonic-gate /*NOTREACHED*/
766*3ee4fc2aSCody Peter Mello return (False);
7677c478bd9Sstevel@tonic-gate }
7687c478bd9Sstevel@tonic-gate
7691ee2e5faSnakanon static void
tfree(Cell * a)770*3ee4fc2aSCody Peter Mello tfree(Cell *a) /* free a tempcell */
7717c478bd9Sstevel@tonic-gate {
772*3ee4fc2aSCody Peter Mello if (freeable(a)) {
773*3ee4fc2aSCody Peter Mello dprintf(("freeing %s %s %o\n",
774*3ee4fc2aSCody Peter Mello NN(a->nval), NN(a->sval), a->tval));
7757c478bd9Sstevel@tonic-gate xfree(a->sval);
776*3ee4fc2aSCody Peter Mello }
7777c478bd9Sstevel@tonic-gate if (a == tmps)
778*3ee4fc2aSCody Peter Mello FATAL("tempcell list is curdled");
7797c478bd9Sstevel@tonic-gate a->cnext = tmps;
7807c478bd9Sstevel@tonic-gate tmps = a;
7817c478bd9Sstevel@tonic-gate }
7827c478bd9Sstevel@tonic-gate
7831ee2e5faSnakanon static Cell *
gettemp(void)784*3ee4fc2aSCody Peter Mello gettemp(void) /* get a tempcell */
7851ee2e5faSnakanon {
7861ee2e5faSnakanon int i;
787*3ee4fc2aSCody Peter Mello Cell *x;
7887c478bd9Sstevel@tonic-gate
7897c478bd9Sstevel@tonic-gate if (!tmps) {
7901ee2e5faSnakanon tmps = (Cell *)calloc(100, sizeof (Cell));
7917c478bd9Sstevel@tonic-gate if (!tmps)
792*3ee4fc2aSCody Peter Mello FATAL("out of space for temporaries");
7931ee2e5faSnakanon for (i = 1; i < 100; i++)
7947c478bd9Sstevel@tonic-gate tmps[i-1].cnext = &tmps[i];
795*3ee4fc2aSCody Peter Mello tmps[i-1].cnext = NULL;
7967c478bd9Sstevel@tonic-gate }
7977c478bd9Sstevel@tonic-gate x = tmps;
7987c478bd9Sstevel@tonic-gate tmps = x->cnext;
7997c478bd9Sstevel@tonic-gate *x = tempcell;
800*3ee4fc2aSCody Peter Mello dprintf(("gtemp %.8s %06lo\n", NN(x->nval), (ulong_t)x));
8011ee2e5faSnakanon return (x);
8027c478bd9Sstevel@tonic-gate }
8037c478bd9Sstevel@tonic-gate
8041ee2e5faSnakanon /*ARGSUSED*/
8051ee2e5faSnakanon Cell *
indirect(Node ** a,int n)806*3ee4fc2aSCody Peter Mello indirect(Node **a, int n) /* $( a[0] ) */
8077c478bd9Sstevel@tonic-gate {
808*3ee4fc2aSCody Peter Mello Awkfloat val;
809*3ee4fc2aSCody Peter Mello Cell *x;
810*3ee4fc2aSCody Peter Mello int m;
811*3ee4fc2aSCody Peter Mello char *s;
8127c478bd9Sstevel@tonic-gate
8137c478bd9Sstevel@tonic-gate x = execute(a[0]);
814*3ee4fc2aSCody Peter Mello
815*3ee4fc2aSCody Peter Mello /* freebsd: defend against super large field numbers */
816*3ee4fc2aSCody Peter Mello val = getfval(x);
817*3ee4fc2aSCody Peter Mello if ((Awkfloat)INT_MAX < val)
818*3ee4fc2aSCody Peter Mello FATAL("trying to access out of range field %s", x->nval);
819*3ee4fc2aSCody Peter Mello m = (int)val;
8201ee2e5faSnakanon if (m == 0 && !is_number(s = getsval(x))) /* suspicion! */
821*3ee4fc2aSCody Peter Mello FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
822*3ee4fc2aSCody Peter Mello /* BUG: can x->nval ever be null??? */
823*3ee4fc2aSCody Peter Mello tempfree(x);
8247c478bd9Sstevel@tonic-gate x = fieldadr(m);
825*3ee4fc2aSCody Peter Mello x->ctype = OCELL; /* BUG? why are these needed? */
8267c478bd9Sstevel@tonic-gate x->csub = CFLD;
8271ee2e5faSnakanon return (x);
8287c478bd9Sstevel@tonic-gate }
8297c478bd9Sstevel@tonic-gate
8301ee2e5faSnakanon /*ARGSUSED*/
8311ee2e5faSnakanon Cell *
substr(Node ** a,int nnn)832*3ee4fc2aSCody Peter Mello substr(Node **a, int nnn) /* substr(a[0], a[1], a[2]) */
8337c478bd9Sstevel@tonic-gate {
834*3ee4fc2aSCody Peter Mello int k, m, n;
835*3ee4fc2aSCody Peter Mello char *s;
8367c478bd9Sstevel@tonic-gate int temp;
837*3ee4fc2aSCody Peter Mello Cell *x, *y, *z = NULL;
8387c478bd9Sstevel@tonic-gate
8397c478bd9Sstevel@tonic-gate x = execute(a[0]);
8407c478bd9Sstevel@tonic-gate y = execute(a[1]);
841*3ee4fc2aSCody Peter Mello if (a[2] != NULL)
8427c478bd9Sstevel@tonic-gate z = execute(a[2]);
8437c478bd9Sstevel@tonic-gate s = getsval(x);
844*3ee4fc2aSCody Peter Mello k = strlen(s) + 1;
8457c478bd9Sstevel@tonic-gate if (k <= 1) {
846*3ee4fc2aSCody Peter Mello tempfree(x);
847*3ee4fc2aSCody Peter Mello tempfree(y);
848*3ee4fc2aSCody Peter Mello if (a[2] != NULL) {
849*3ee4fc2aSCody Peter Mello tempfree(z);
850*3ee4fc2aSCody Peter Mello }
851*3ee4fc2aSCody Peter Mello x = gettemp();
852*3ee4fc2aSCody Peter Mello (void) setsval(x, "");
8531ee2e5faSnakanon return (x);
8547c478bd9Sstevel@tonic-gate }
85512809310Snakanon m = (int)getfval(y);
8567c478bd9Sstevel@tonic-gate if (m <= 0)
8577c478bd9Sstevel@tonic-gate m = 1;
8587c478bd9Sstevel@tonic-gate else if (m > k)
8597c478bd9Sstevel@tonic-gate m = k;
860*3ee4fc2aSCody Peter Mello tempfree(y);
861*3ee4fc2aSCody Peter Mello if (a[2] != NULL) {
86212809310Snakanon n = (int)getfval(z);
863*3ee4fc2aSCody Peter Mello tempfree(z);
8647c478bd9Sstevel@tonic-gate } else
8657c478bd9Sstevel@tonic-gate n = k - 1;
8667c478bd9Sstevel@tonic-gate if (n < 0)
8677c478bd9Sstevel@tonic-gate n = 0;
8687c478bd9Sstevel@tonic-gate else if (n > k - m)
8697c478bd9Sstevel@tonic-gate n = k - m;
8701ee2e5faSnakanon dprintf(("substr: m=%d, n=%d, s=%s\n", m, n, s));
871*3ee4fc2aSCody Peter Mello y = gettemp();
8721ee2e5faSnakanon temp = s[n + m - 1]; /* with thanks to John Linderman */
8731ee2e5faSnakanon s[n + m - 1] = '\0';
8741ee2e5faSnakanon (void) setsval(y, s + m - 1);
8751ee2e5faSnakanon s[n + m - 1] = temp;
876*3ee4fc2aSCody Peter Mello tempfree(x);
8771ee2e5faSnakanon return (y);
8787c478bd9Sstevel@tonic-gate }
8797c478bd9Sstevel@tonic-gate
8801ee2e5faSnakanon /*ARGSUSED*/
8811ee2e5faSnakanon Cell *
sindex(Node ** a,int nnn)882*3ee4fc2aSCody Peter Mello sindex(Node **a, int nnn) /* index(a[0], a[1]) */
8837c478bd9Sstevel@tonic-gate {
884*3ee4fc2aSCody Peter Mello Cell *x, *y, *z;
885*3ee4fc2aSCody Peter Mello char *s1, *s2, *p1, *p2, *q;
8867c478bd9Sstevel@tonic-gate Awkfloat v = 0.0;
8877c478bd9Sstevel@tonic-gate
8887c478bd9Sstevel@tonic-gate x = execute(a[0]);
8897c478bd9Sstevel@tonic-gate s1 = getsval(x);
8907c478bd9Sstevel@tonic-gate y = execute(a[1]);
8917c478bd9Sstevel@tonic-gate s2 = getsval(y);
8927c478bd9Sstevel@tonic-gate
893*3ee4fc2aSCody Peter Mello z = gettemp();
8947c478bd9Sstevel@tonic-gate for (p1 = s1; *p1 != '\0'; p1++) {
8951ee2e5faSnakanon for (q = p1, p2 = s2; *p2 != '\0' && *q == *p2; q++, p2++)
8967c478bd9Sstevel@tonic-gate ;
8977c478bd9Sstevel@tonic-gate if (*p2 == '\0') {
8987c478bd9Sstevel@tonic-gate v = (Awkfloat) (p1 - s1 + 1); /* origin 1 */
8997c478bd9Sstevel@tonic-gate break;
9007c478bd9Sstevel@tonic-gate }
9017c478bd9Sstevel@tonic-gate }
902*3ee4fc2aSCody Peter Mello tempfree(x);
903*3ee4fc2aSCody Peter Mello tempfree(y);
9041ee2e5faSnakanon (void) setfval(z, v);
9051ee2e5faSnakanon return (z);
9067c478bd9Sstevel@tonic-gate }
9077c478bd9Sstevel@tonic-gate
908*3ee4fc2aSCody Peter Mello #define MAXNUMSIZE 50
909*3ee4fc2aSCody Peter Mello
910*3ee4fc2aSCody Peter Mello /* printf-like conversions */
911*3ee4fc2aSCody Peter Mello int
format(char ** pbuf,int * pbufsize,const char * s,Node * a)912*3ee4fc2aSCody Peter Mello format(char **pbuf, int *pbufsize, const char *s, Node *a)
9137c478bd9Sstevel@tonic-gate {
914*3ee4fc2aSCody Peter Mello char *fmt;
915*3ee4fc2aSCody Peter Mello const char *os;
916*3ee4fc2aSCody Peter Mello Cell *x;
917*3ee4fc2aSCody Peter Mello int flag = 0, n, len;
918*3ee4fc2aSCody Peter Mello int fmtwd; /* format width */
919*3ee4fc2aSCody Peter Mello char *buf = *pbuf;
920*3ee4fc2aSCody Peter Mello size_t bufsize = *pbufsize;
921*3ee4fc2aSCody Peter Mello size_t fmtsz = recsize;
922*3ee4fc2aSCody Peter Mello size_t cnt, tcnt, ret;
923*3ee4fc2aSCody Peter Mello
9247c478bd9Sstevel@tonic-gate os = s;
9251ee2e5faSnakanon cnt = 0;
926*3ee4fc2aSCody Peter Mello if ((fmt = (char *)malloc(fmtsz)) == NULL)
927*3ee4fc2aSCody Peter Mello FATAL("out of memory in format()");
9287c478bd9Sstevel@tonic-gate while (*s) {
9297c478bd9Sstevel@tonic-gate if (*s != '%') {
9301ee2e5faSnakanon expand_buf(&buf, &bufsize, cnt);
9311ee2e5faSnakanon buf[cnt++] = *s++;
9327c478bd9Sstevel@tonic-gate continue;
9337c478bd9Sstevel@tonic-gate }
9347c478bd9Sstevel@tonic-gate if (*(s+1) == '%') {
9351ee2e5faSnakanon expand_buf(&buf, &bufsize, cnt);
9361ee2e5faSnakanon buf[cnt++] = '%';
9377c478bd9Sstevel@tonic-gate s += 2;
9387c478bd9Sstevel@tonic-gate continue;
9397c478bd9Sstevel@tonic-gate }
940*3ee4fc2aSCody Peter Mello /*
941*3ee4fc2aSCody Peter Mello * have to be real careful in case this is a huge number,
942*3ee4fc2aSCody Peter Mello * eg, "%100000d".
943*3ee4fc2aSCody Peter Mello */
944*3ee4fc2aSCody Peter Mello fmtwd = atoi(s+1);
945*3ee4fc2aSCody Peter Mello if (fmtwd < 0)
946*3ee4fc2aSCody Peter Mello fmtwd = -fmtwd;
9471ee2e5faSnakanon for (tcnt = 0; ; s++) {
948*3ee4fc2aSCody Peter Mello expand_buf(&fmt, &fmtsz, tcnt);
9491ee2e5faSnakanon fmt[tcnt++] = *s;
9501ee2e5faSnakanon if (*s == '\0')
9511ee2e5faSnakanon break;
952*3ee4fc2aSCody Peter Mello if (isalpha((uschar)*s) &&
953*3ee4fc2aSCody Peter Mello *s != 'l' && *s != 'h' && *s != 'L')
9547c478bd9Sstevel@tonic-gate break; /* the ansi panoply */
955*3ee4fc2aSCody Peter Mello if (*s == '$') {
956*3ee4fc2aSCody Peter Mello FATAL("'$' not permitted in awk formats");
957*3ee4fc2aSCody Peter Mello }
9587c478bd9Sstevel@tonic-gate if (*s == '*') {
9597c478bd9Sstevel@tonic-gate if (a == NULL) {
960*3ee4fc2aSCody Peter Mello FATAL("not enough args in printf(%s) "
961*3ee4fc2aSCody Peter Mello "or sprintf(%s)", os, os);
9627c478bd9Sstevel@tonic-gate }
9637c478bd9Sstevel@tonic-gate x = execute(a);
9647c478bd9Sstevel@tonic-gate a = a->nnext;
9651ee2e5faSnakanon tcnt--;
966*3ee4fc2aSCody Peter Mello expand_buf(&fmt, &fmtsz, tcnt + 12);
967*3ee4fc2aSCody Peter Mello fmtwd = (int)getfval(x);
968*3ee4fc2aSCody Peter Mello ret = sprintf(&fmt[tcnt], "%d", fmtwd);
969*3ee4fc2aSCody Peter Mello if (fmtwd < 0)
970*3ee4fc2aSCody Peter Mello fmtwd = -fmtwd;
9711ee2e5faSnakanon tcnt += ret;
972*3ee4fc2aSCody Peter Mello tempfree(x);
9737c478bd9Sstevel@tonic-gate }
9747c478bd9Sstevel@tonic-gate }
9751ee2e5faSnakanon fmt[tcnt] = '\0';
976*3ee4fc2aSCody Peter Mello if (fmtwd < 0)
977*3ee4fc2aSCody Peter Mello fmtwd = -fmtwd;
9781ee2e5faSnakanon
9797c478bd9Sstevel@tonic-gate switch (*s) {
980*3ee4fc2aSCody Peter Mello case 'a': case 'A':
981*3ee4fc2aSCody Peter Mello flag = *s;
982*3ee4fc2aSCody Peter Mello break;
9837c478bd9Sstevel@tonic-gate case 'f': case 'e': case 'g': case 'E': case 'G':
984*3ee4fc2aSCody Peter Mello flag = 'f';
9857c478bd9Sstevel@tonic-gate break;
9867c478bd9Sstevel@tonic-gate case 'd': case 'i':
987*3ee4fc2aSCody Peter Mello flag = 'd';
9881ee2e5faSnakanon if (*(s-1) == 'l')
9891ee2e5faSnakanon break;
9901ee2e5faSnakanon fmt[tcnt - 1] = 'l';
991*3ee4fc2aSCody Peter Mello expand_buf(&fmt, &fmtsz, tcnt);
9921ee2e5faSnakanon fmt[tcnt++] = 'd';
9931ee2e5faSnakanon fmt[tcnt] = '\0';
9947c478bd9Sstevel@tonic-gate break;
9957c478bd9Sstevel@tonic-gate case 'o': case 'x': case 'X': case 'u':
996*3ee4fc2aSCody Peter Mello flag = *(s-1) == 'l' ? 'd' : 'u';
9977c478bd9Sstevel@tonic-gate break;
9987c478bd9Sstevel@tonic-gate case 's':
999*3ee4fc2aSCody Peter Mello flag = 's';
10007c478bd9Sstevel@tonic-gate break;
10017c478bd9Sstevel@tonic-gate case 'c':
1002*3ee4fc2aSCody Peter Mello flag = 'c';
10037c478bd9Sstevel@tonic-gate break;
10047c478bd9Sstevel@tonic-gate default:
1005*3ee4fc2aSCody Peter Mello WARNING("weird printf conversion %s", fmt);
1006*3ee4fc2aSCody Peter Mello flag = '?';
10077c478bd9Sstevel@tonic-gate break;
10087c478bd9Sstevel@tonic-gate }
1009*3ee4fc2aSCody Peter Mello if (flag == '?') {
1010*3ee4fc2aSCody Peter Mello len = strlen(fmt);
10111ee2e5faSnakanon expand_buf(&buf, &bufsize, cnt + len);
10121ee2e5faSnakanon (void) memcpy(&buf[cnt], fmt, len);
10131ee2e5faSnakanon cnt += len;
10141ee2e5faSnakanon buf[cnt] = '\0';
10157c478bd9Sstevel@tonic-gate continue;
10167c478bd9Sstevel@tonic-gate }
10177c478bd9Sstevel@tonic-gate if (a == NULL) {
1018*3ee4fc2aSCody Peter Mello FATAL("not enough args in printf(%s) "
1019*3ee4fc2aSCody Peter Mello "or sprintf(%s)", os, os);
10207c478bd9Sstevel@tonic-gate }
10217c478bd9Sstevel@tonic-gate x = execute(a);
10227c478bd9Sstevel@tonic-gate a = a->nnext;
1023*3ee4fc2aSCody Peter Mello n = MAXNUMSIZE;
1024*3ee4fc2aSCody Peter Mello if (fmtwd > n)
1025*3ee4fc2aSCody Peter Mello n = fmtwd;
1026*3ee4fc2aSCody Peter Mello retry:
1027*3ee4fc2aSCody Peter Mello /* make sure we have at least 1 byte space */
1028*3ee4fc2aSCody Peter Mello (void) adjbuf(&buf, &bufsize, 1 + n + cnt,
1029*3ee4fc2aSCody Peter Mello recsize, NULL, "format5");
1030*3ee4fc2aSCody Peter Mello len = bufsize - cnt;
1031*3ee4fc2aSCody Peter Mello switch (flag) {
1032*3ee4fc2aSCody Peter Mello case 'a':
1033*3ee4fc2aSCody Peter Mello case 'A':
1034*3ee4fc2aSCody Peter Mello case 'f':
1035*3ee4fc2aSCody Peter Mello /*LINTED*/
1036*3ee4fc2aSCody Peter Mello ret = snprintf(&buf[cnt], len,
1037*3ee4fc2aSCody Peter Mello fmt, getfval(x));
1038*3ee4fc2aSCody Peter Mello break;
1039*3ee4fc2aSCody Peter Mello case 'd':
1040*3ee4fc2aSCody Peter Mello /*LINTED*/
1041*3ee4fc2aSCody Peter Mello ret = snprintf(&buf[cnt], len,
1042*3ee4fc2aSCody Peter Mello fmt, (long)getfval(x));
1043*3ee4fc2aSCody Peter Mello break;
1044*3ee4fc2aSCody Peter Mello case 'u':
1045*3ee4fc2aSCody Peter Mello /*LINTED*/
1046*3ee4fc2aSCody Peter Mello ret = snprintf(&buf[cnt], len,
1047*3ee4fc2aSCody Peter Mello fmt, (int)getfval(x));
1048*3ee4fc2aSCody Peter Mello break;
1049*3ee4fc2aSCody Peter Mello case 's':
1050*3ee4fc2aSCody Peter Mello /*LINTED*/
1051*3ee4fc2aSCody Peter Mello ret = snprintf(&buf[cnt], len,
1052*3ee4fc2aSCody Peter Mello fmt, getsval(x));
1053*3ee4fc2aSCody Peter Mello break;
1054*3ee4fc2aSCody Peter Mello case 'c':
1055*3ee4fc2aSCody Peter Mello if (!isnum(x)) {
10561ee2e5faSnakanon /*LINTED*/
1057*3ee4fc2aSCody Peter Mello ret = snprintf(&buf[cnt], len,
1058*3ee4fc2aSCody Peter Mello fmt, getsval(x)[0]);
10591ee2e5faSnakanon break;
1060*3ee4fc2aSCody Peter Mello }
1061*3ee4fc2aSCody Peter Mello if (getfval(x)) {
10621ee2e5faSnakanon /*LINTED*/
1063*3ee4fc2aSCody Peter Mello ret = snprintf(&buf[cnt], len,
1064*3ee4fc2aSCody Peter Mello fmt, (int)getfval(x));
1065*3ee4fc2aSCody Peter Mello } else {
1066*3ee4fc2aSCody Peter Mello /* explicit null byte */
1067*3ee4fc2aSCody Peter Mello buf[cnt] = '\0';
1068*3ee4fc2aSCody Peter Mello /* next output will start here */
1069*3ee4fc2aSCody Peter Mello buf[cnt + 1] = '\0';
1070*3ee4fc2aSCody Peter Mello ret = 1;
10711ee2e5faSnakanon }
1072*3ee4fc2aSCody Peter Mello break;
1073*3ee4fc2aSCody Peter Mello default:
1074*3ee4fc2aSCody Peter Mello FATAL("can't happen: "
1075*3ee4fc2aSCody Peter Mello "bad conversion %c in format()", flag);
1076*3ee4fc2aSCody Peter Mello }
1077*3ee4fc2aSCody Peter Mello if (ret >= len) {
1078*3ee4fc2aSCody Peter Mello (void) adjbuf(&buf, &bufsize, cnt + ret + 1,
1079*3ee4fc2aSCody Peter Mello recsize, NULL, "format6");
1080*3ee4fc2aSCody Peter Mello goto retry;
10817c478bd9Sstevel@tonic-gate }
1082*3ee4fc2aSCody Peter Mello tempfree(x);
10831ee2e5faSnakanon cnt += ret;
10847c478bd9Sstevel@tonic-gate s++;
10857c478bd9Sstevel@tonic-gate }
10861ee2e5faSnakanon buf[cnt] = '\0';
10871ee2e5faSnakanon free(fmt);
1088*3ee4fc2aSCody Peter Mello for (; a != NULL; a = a->nnext) /* evaluate any remaining args */
1089*3ee4fc2aSCody Peter Mello (void) execute(a);
1090*3ee4fc2aSCody Peter Mello *pbuf = buf;
1091*3ee4fc2aSCody Peter Mello *pbufsize = bufsize;
1092*3ee4fc2aSCody Peter Mello return (cnt);
10937c478bd9Sstevel@tonic-gate }
10947c478bd9Sstevel@tonic-gate
10951ee2e5faSnakanon /*ARGSUSED*/
10961ee2e5faSnakanon Cell *
awksprintf(Node ** a,int n)1097*3ee4fc2aSCody Peter Mello awksprintf(Node **a, int n) /* sprintf(a[0]) */
10987c478bd9Sstevel@tonic-gate {
1099*3ee4fc2aSCody Peter Mello Cell *x;
1100*3ee4fc2aSCody Peter Mello Node *y;
1101*3ee4fc2aSCody Peter Mello char *buf;
1102*3ee4fc2aSCody Peter Mello int bufsz = 3 * recsize;
11037c478bd9Sstevel@tonic-gate
1104*3ee4fc2aSCody Peter Mello if ((buf = (char *)malloc(bufsz)) == NULL)
1105*3ee4fc2aSCody Peter Mello FATAL("out of memory in awksprintf");
11067c478bd9Sstevel@tonic-gate y = a[0]->nnext;
11077c478bd9Sstevel@tonic-gate x = execute(a[0]);
1108*3ee4fc2aSCody Peter Mello if (format(&buf, &bufsz, getsval(x), y) == -1)
1109*3ee4fc2aSCody Peter Mello FATAL("sprintf string %.30s... too long. can't happen.", buf);
1110*3ee4fc2aSCody Peter Mello tempfree(x);
1111*3ee4fc2aSCody Peter Mello x = gettemp();
11121ee2e5faSnakanon x->sval = buf;
11137c478bd9Sstevel@tonic-gate x->tval = STR;
11141ee2e5faSnakanon return (x);
11157c478bd9Sstevel@tonic-gate }
11167c478bd9Sstevel@tonic-gate
11171ee2e5faSnakanon /*ARGSUSED*/
11181ee2e5faSnakanon Cell *
awkprintf(Node ** a,int n)1119*3ee4fc2aSCody Peter Mello awkprintf(Node **a, int n) /* printf */
11207c478bd9Sstevel@tonic-gate {
1121*3ee4fc2aSCody Peter Mello /* a[0] is list of args, starting with format string */
1122*3ee4fc2aSCody Peter Mello /* a[1] is redirection operator, a[2] is redirection file */
11237c478bd9Sstevel@tonic-gate FILE *fp;
1124*3ee4fc2aSCody Peter Mello Cell *x;
1125*3ee4fc2aSCody Peter Mello Node *y;
1126*3ee4fc2aSCody Peter Mello char *buf;
1127*3ee4fc2aSCody Peter Mello int len;
1128*3ee4fc2aSCody Peter Mello int bufsz = 3 * recsize;
11297c478bd9Sstevel@tonic-gate
1130*3ee4fc2aSCody Peter Mello if ((buf = (char *)malloc(bufsz)) == NULL)
1131*3ee4fc2aSCody Peter Mello FATAL("out of memory in awkprintf");
11327c478bd9Sstevel@tonic-gate y = a[0]->nnext;
11337c478bd9Sstevel@tonic-gate x = execute(a[0]);
1134*3ee4fc2aSCody Peter Mello if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
1135*3ee4fc2aSCody Peter Mello FATAL("printf string %.30s... too long. can't happen.", buf);
1136*3ee4fc2aSCody Peter Mello tempfree(x);
1137*3ee4fc2aSCody Peter Mello if (a[1] == NULL) {
1138*3ee4fc2aSCody Peter Mello (void) fwrite(buf, len, 1, stdout);
1139*3ee4fc2aSCody Peter Mello if (ferror(stdout))
1140*3ee4fc2aSCody Peter Mello FATAL("write error on stdout");
1141*3ee4fc2aSCody Peter Mello } else {
1142*3ee4fc2aSCody Peter Mello fp = redirect(ptoi(a[1]), a[2]);
1143*3ee4fc2aSCody Peter Mello (void) fwrite(buf, len, 1, fp);
11441ee2e5faSnakanon (void) fflush(fp);
1145*3ee4fc2aSCody Peter Mello if (ferror(fp))
1146*3ee4fc2aSCody Peter Mello FATAL("write error on %s", filename(fp));
11477c478bd9Sstevel@tonic-gate }
11481ee2e5faSnakanon free(buf);
1149*3ee4fc2aSCody Peter Mello return (True);
11507c478bd9Sstevel@tonic-gate }
11517c478bd9Sstevel@tonic-gate
11521ee2e5faSnakanon Cell *
arith(Node ** a,int n)1153*3ee4fc2aSCody Peter Mello arith(Node **a, int n) /* a[0] + a[1], etc. also -a[0] */
11547c478bd9Sstevel@tonic-gate {
1155*3ee4fc2aSCody Peter Mello Awkfloat i, j = 0;
11561ee2e5faSnakanon double v;
1157*3ee4fc2aSCody Peter Mello Cell *x, *y, *z;
11587c478bd9Sstevel@tonic-gate
11597c478bd9Sstevel@tonic-gate x = execute(a[0]);
11607c478bd9Sstevel@tonic-gate i = getfval(x);
1161*3ee4fc2aSCody Peter Mello tempfree(x);
1162*3ee4fc2aSCody Peter Mello if (n != UMINUS && n != UPLUS) {
11637c478bd9Sstevel@tonic-gate y = execute(a[1]);
11647c478bd9Sstevel@tonic-gate j = getfval(y);
1165*3ee4fc2aSCody Peter Mello tempfree(y);
11667c478bd9Sstevel@tonic-gate }
1167*3ee4fc2aSCody Peter Mello z = gettemp();
11687c478bd9Sstevel@tonic-gate switch (n) {
11697c478bd9Sstevel@tonic-gate case ADD:
11707c478bd9Sstevel@tonic-gate i += j;
11717c478bd9Sstevel@tonic-gate break;
11727c478bd9Sstevel@tonic-gate case MINUS:
11737c478bd9Sstevel@tonic-gate i -= j;
11747c478bd9Sstevel@tonic-gate break;
11757c478bd9Sstevel@tonic-gate case MULT:
11767c478bd9Sstevel@tonic-gate i *= j;
11777c478bd9Sstevel@tonic-gate break;
11787c478bd9Sstevel@tonic-gate case DIVIDE:
11797c478bd9Sstevel@tonic-gate if (j == 0)
1180*3ee4fc2aSCody Peter Mello FATAL("division by zero");
11817c478bd9Sstevel@tonic-gate i /= j;
11827c478bd9Sstevel@tonic-gate break;
11837c478bd9Sstevel@tonic-gate case MOD:
11847c478bd9Sstevel@tonic-gate if (j == 0)
1185*3ee4fc2aSCody Peter Mello FATAL("division by zero in mod");
11861ee2e5faSnakanon (void) modf(i/j, &v);
11877c478bd9Sstevel@tonic-gate i = i - j * v;
11887c478bd9Sstevel@tonic-gate break;
11897c478bd9Sstevel@tonic-gate case UMINUS:
11907c478bd9Sstevel@tonic-gate i = -i;
11917c478bd9Sstevel@tonic-gate break;
1192*3ee4fc2aSCody Peter Mello case UPLUS: /* handled by getfval(), above */
1193*3ee4fc2aSCody Peter Mello break;
11947c478bd9Sstevel@tonic-gate case POWER:
11951ee2e5faSnakanon if (j >= 0 && modf(j, &v) == 0.0) /* pos integer exponent */
11961ee2e5faSnakanon i = ipow(i, (int)j);
11977c478bd9Sstevel@tonic-gate else
11987c478bd9Sstevel@tonic-gate i = errcheck(pow(i, j), "pow");
11997c478bd9Sstevel@tonic-gate break;
12007c478bd9Sstevel@tonic-gate default: /* can't happen */
1201*3ee4fc2aSCody Peter Mello FATAL("illegal arithmetic operator %d", n);
12027c478bd9Sstevel@tonic-gate }
12031ee2e5faSnakanon (void) setfval(z, i);
12041ee2e5faSnakanon return (z);
12057c478bd9Sstevel@tonic-gate }
12067c478bd9Sstevel@tonic-gate
12071ee2e5faSnakanon static double
ipow(double x,int n)1208*3ee4fc2aSCody Peter Mello ipow(double x, int n) /* x**n. ought to be done by pow, but isn't always */
12097c478bd9Sstevel@tonic-gate {
12107c478bd9Sstevel@tonic-gate double v;
12117c478bd9Sstevel@tonic-gate
12127c478bd9Sstevel@tonic-gate if (n <= 0)
12131ee2e5faSnakanon return (1.0);
12147c478bd9Sstevel@tonic-gate v = ipow(x, n/2);
12157c478bd9Sstevel@tonic-gate if (n % 2 == 0)
12161ee2e5faSnakanon return (v * v);
12177c478bd9Sstevel@tonic-gate else
12181ee2e5faSnakanon return (x * v * v);
12197c478bd9Sstevel@tonic-gate }
12207c478bd9Sstevel@tonic-gate
12211ee2e5faSnakanon Cell *
incrdecr(Node ** a,int n)1222*3ee4fc2aSCody Peter Mello incrdecr(Node **a, int n) /* a[0]++, etc. */
12237c478bd9Sstevel@tonic-gate {
1224*3ee4fc2aSCody Peter Mello Cell *x, *z;
1225*3ee4fc2aSCody Peter Mello int k;
12267c478bd9Sstevel@tonic-gate Awkfloat xf;
12277c478bd9Sstevel@tonic-gate
12287c478bd9Sstevel@tonic-gate x = execute(a[0]);
12297c478bd9Sstevel@tonic-gate xf = getfval(x);
12307c478bd9Sstevel@tonic-gate k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
12317c478bd9Sstevel@tonic-gate if (n == PREINCR || n == PREDECR) {
12321ee2e5faSnakanon (void) setfval(x, xf + k);
12331ee2e5faSnakanon return (x);
12347c478bd9Sstevel@tonic-gate }
1235*3ee4fc2aSCody Peter Mello z = gettemp();
12361ee2e5faSnakanon (void) setfval(z, xf);
12371ee2e5faSnakanon (void) setfval(x, xf + k);
1238*3ee4fc2aSCody Peter Mello tempfree(x);
12391ee2e5faSnakanon return (z);
12407c478bd9Sstevel@tonic-gate }
12417c478bd9Sstevel@tonic-gate
1242*3ee4fc2aSCody Peter Mello /* a[0] = a[1], a[0] += a[1], etc. */
1243*3ee4fc2aSCody Peter Mello /* this is subtle; don't muck with it. */
12441ee2e5faSnakanon Cell *
assign(Node ** a,int n)12451ee2e5faSnakanon assign(Node **a, int n)
12467c478bd9Sstevel@tonic-gate {
1247*3ee4fc2aSCody Peter Mello Cell *x, *y;
12487c478bd9Sstevel@tonic-gate Awkfloat xf, yf;
12491ee2e5faSnakanon double v;
12507c478bd9Sstevel@tonic-gate
12517c478bd9Sstevel@tonic-gate y = execute(a[1]);
12527c478bd9Sstevel@tonic-gate x = execute(a[0]); /* order reversed from before... */
12537c478bd9Sstevel@tonic-gate if (n == ASSIGN) { /* ordinary assignment */
1254*3ee4fc2aSCody Peter Mello /*LINTED if*/
1255*3ee4fc2aSCody Peter Mello if (x == y && !(x->tval & (FLD|REC)) && x != nfloc) {
1256*3ee4fc2aSCody Peter Mello /*
1257*3ee4fc2aSCody Peter Mello * If this is a self-assignment, we leave things alone,
1258*3ee4fc2aSCody Peter Mello * unless it's a field or NF.
1259*3ee4fc2aSCody Peter Mello */
1260*3ee4fc2aSCody Peter Mello } else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
12611ee2e5faSnakanon (void) setsval(x, getsval(y));
12627c478bd9Sstevel@tonic-gate x->fval = getfval(y);
12637c478bd9Sstevel@tonic-gate x->tval |= NUM;
1264*3ee4fc2aSCody Peter Mello } else if (isstr(y))
12651ee2e5faSnakanon (void) setsval(x, getsval(y));
1266*3ee4fc2aSCody Peter Mello else if (isnum(y))
12671ee2e5faSnakanon (void) setfval(x, getfval(y));
12687c478bd9Sstevel@tonic-gate else
12697c478bd9Sstevel@tonic-gate funnyvar(y, "read value of");
1270*3ee4fc2aSCody Peter Mello tempfree(y);
12711ee2e5faSnakanon return (x);
12727c478bd9Sstevel@tonic-gate }
12737c478bd9Sstevel@tonic-gate xf = getfval(x);
12747c478bd9Sstevel@tonic-gate yf = getfval(y);
12757c478bd9Sstevel@tonic-gate switch (n) {
12767c478bd9Sstevel@tonic-gate case ADDEQ:
12777c478bd9Sstevel@tonic-gate xf += yf;
12787c478bd9Sstevel@tonic-gate break;
12797c478bd9Sstevel@tonic-gate case SUBEQ:
12807c478bd9Sstevel@tonic-gate xf -= yf;
12817c478bd9Sstevel@tonic-gate break;
12827c478bd9Sstevel@tonic-gate case MULTEQ:
12837c478bd9Sstevel@tonic-gate xf *= yf;
12847c478bd9Sstevel@tonic-gate break;
12857c478bd9Sstevel@tonic-gate case DIVEQ:
12867c478bd9Sstevel@tonic-gate if (yf == 0)
1287*3ee4fc2aSCody Peter Mello FATAL("division by zero in /=");
12887c478bd9Sstevel@tonic-gate xf /= yf;
12897c478bd9Sstevel@tonic-gate break;
12907c478bd9Sstevel@tonic-gate case MODEQ:
12917c478bd9Sstevel@tonic-gate if (yf == 0)
1292*3ee4fc2aSCody Peter Mello FATAL("division by zero in %%=");
12931ee2e5faSnakanon (void) modf(xf/yf, &v);
12947c478bd9Sstevel@tonic-gate xf = xf - yf * v;
12957c478bd9Sstevel@tonic-gate break;
12967c478bd9Sstevel@tonic-gate case POWEQ:
12971ee2e5faSnakanon if (yf >= 0 && modf(yf, &v) == 0.0) /* pos integer exponent */
12981ee2e5faSnakanon xf = ipow(xf, (int)yf);
12997c478bd9Sstevel@tonic-gate else
13007c478bd9Sstevel@tonic-gate xf = errcheck(pow(xf, yf), "pow");
13017c478bd9Sstevel@tonic-gate break;
13027c478bd9Sstevel@tonic-gate default:
1303*3ee4fc2aSCody Peter Mello FATAL("illegal assignment operator %d", n);
13047c478bd9Sstevel@tonic-gate break;
13057c478bd9Sstevel@tonic-gate }
1306*3ee4fc2aSCody Peter Mello tempfree(y);
13071ee2e5faSnakanon (void) setfval(x, xf);
13081ee2e5faSnakanon return (x);
13097c478bd9Sstevel@tonic-gate }
13107c478bd9Sstevel@tonic-gate
13111ee2e5faSnakanon /*ARGSUSED*/
13121ee2e5faSnakanon Cell *
cat(Node ** a,int q)1313*3ee4fc2aSCody Peter Mello cat(Node **a, int q) /* a[0] cat a[1] */
13147c478bd9Sstevel@tonic-gate {
1315*3ee4fc2aSCody Peter Mello Cell *x, *y, *z;
1316*3ee4fc2aSCody Peter Mello int n1, n2;
1317*3ee4fc2aSCody Peter Mello char *s = NULL;
1318*3ee4fc2aSCody Peter Mello size_t ssz = 0;
13197c478bd9Sstevel@tonic-gate
13207c478bd9Sstevel@tonic-gate x = execute(a[0]);
1321*3ee4fc2aSCody Peter Mello n1 = strlen(getsval(x));
1322*3ee4fc2aSCody Peter Mello (void) adjbuf(&s, &ssz, n1 + 1, recsize, 0, "cat1");
1323*3ee4fc2aSCody Peter Mello (void) strncpy(s, x->sval, ssz);
1324*3ee4fc2aSCody Peter Mello
13257c478bd9Sstevel@tonic-gate y = execute(a[1]);
1326*3ee4fc2aSCody Peter Mello n2 = strlen(getsval(y));
1327*3ee4fc2aSCody Peter Mello (void) adjbuf(&s, &ssz, n1 + n2 + 1, recsize, 0, "cat2");
1328*3ee4fc2aSCody Peter Mello (void) strncpy(s + n1, y->sval, ssz - n1);
1329*3ee4fc2aSCody Peter Mello
1330*3ee4fc2aSCody Peter Mello tempfree(x);
1331*3ee4fc2aSCody Peter Mello tempfree(y);
1332*3ee4fc2aSCody Peter Mello
1333*3ee4fc2aSCody Peter Mello z = gettemp();
13347c478bd9Sstevel@tonic-gate z->sval = s;
13357c478bd9Sstevel@tonic-gate z->tval = STR;
1336*3ee4fc2aSCody Peter Mello
13371ee2e5faSnakanon return (z);
13387c478bd9Sstevel@tonic-gate }
13397c478bd9Sstevel@tonic-gate
13401ee2e5faSnakanon /*ARGSUSED*/
13411ee2e5faSnakanon Cell *
pastat(Node ** a,int n)1342*3ee4fc2aSCody Peter Mello pastat(Node **a, int n) /* a[0] { a[1] } */
13437c478bd9Sstevel@tonic-gate {
1344*3ee4fc2aSCody Peter Mello Cell *x;
13457c478bd9Sstevel@tonic-gate
1346*3ee4fc2aSCody Peter Mello if (a[0] == NULL)
13477c478bd9Sstevel@tonic-gate x = execute(a[1]);
13487c478bd9Sstevel@tonic-gate else {
13497c478bd9Sstevel@tonic-gate x = execute(a[0]);
13507c478bd9Sstevel@tonic-gate if (istrue(x)) {
1351*3ee4fc2aSCody Peter Mello tempfree(x);
13527c478bd9Sstevel@tonic-gate x = execute(a[1]);
13537c478bd9Sstevel@tonic-gate }
13547c478bd9Sstevel@tonic-gate }
13551ee2e5faSnakanon return (x);
13567c478bd9Sstevel@tonic-gate }
13577c478bd9Sstevel@tonic-gate
13581ee2e5faSnakanon /*ARGSUSED*/
13591ee2e5faSnakanon Cell *
dopa2(Node ** a,int n)1360*3ee4fc2aSCody Peter Mello dopa2(Node **a, int n) /* a[0], a[1] { a[2] } */
13617c478bd9Sstevel@tonic-gate {
13627c478bd9Sstevel@tonic-gate Cell *x;
13637c478bd9Sstevel@tonic-gate int pair;
13647c478bd9Sstevel@tonic-gate
13657c478bd9Sstevel@tonic-gate if (!pairstack) {
13667c478bd9Sstevel@tonic-gate /* first time */
13677c478bd9Sstevel@tonic-gate dprintf(("paircnt: %d\n", paircnt));
1368*3ee4fc2aSCody Peter Mello pairstack = (int *)calloc(paircnt, sizeof (int));
1369*3ee4fc2aSCody Peter Mello if (pairstack == NULL)
1370*3ee4fc2aSCody Peter Mello FATAL("out of space in dopa2");
13717c478bd9Sstevel@tonic-gate }
13727c478bd9Sstevel@tonic-gate
1373*3ee4fc2aSCody Peter Mello pair = ptoi(a[3]);
13747c478bd9Sstevel@tonic-gate if (pairstack[pair] == 0) {
13757c478bd9Sstevel@tonic-gate x = execute(a[0]);
13767c478bd9Sstevel@tonic-gate if (istrue(x))
13777c478bd9Sstevel@tonic-gate pairstack[pair] = 1;
1378*3ee4fc2aSCody Peter Mello tempfree(x);
13797c478bd9Sstevel@tonic-gate }
13807c478bd9Sstevel@tonic-gate if (pairstack[pair] == 1) {
13817c478bd9Sstevel@tonic-gate x = execute(a[1]);
13827c478bd9Sstevel@tonic-gate if (istrue(x))
13837c478bd9Sstevel@tonic-gate pairstack[pair] = 0;
1384*3ee4fc2aSCody Peter Mello tempfree(x);
13857c478bd9Sstevel@tonic-gate x = execute(a[2]);
13861ee2e5faSnakanon return (x);
13877c478bd9Sstevel@tonic-gate }
1388*3ee4fc2aSCody Peter Mello return (False);
13897c478bd9Sstevel@tonic-gate }
13907c478bd9Sstevel@tonic-gate
13911ee2e5faSnakanon /*ARGSUSED*/
13921ee2e5faSnakanon Cell *
split(Node ** a,int nnn)1393*3ee4fc2aSCody Peter Mello split(Node **a, int nnn) /* split(a[0], a[1], a[2]); a[3] is type */
13947c478bd9Sstevel@tonic-gate {
1395*3ee4fc2aSCody Peter Mello Cell *x = NULL, *y, *ap;
1396*3ee4fc2aSCody Peter Mello char *s, *origs;
1397*3ee4fc2aSCody Peter Mello char *fs, *origfs = NULL;
1398*3ee4fc2aSCody Peter Mello int sep;
1399*3ee4fc2aSCody Peter Mello char *t, temp, num[50];
1400*3ee4fc2aSCody Peter Mello int n, tempstat, arg3type;
14017c478bd9Sstevel@tonic-gate
14027c478bd9Sstevel@tonic-gate y = execute(a[0]); /* source string */
1403*3ee4fc2aSCody Peter Mello origs = s = tostring(getsval(y));
1404*3ee4fc2aSCody Peter Mello arg3type = ptoi(a[3]);
1405*3ee4fc2aSCody Peter Mello if (a[2] == NULL) /* fs string */
1406*3ee4fc2aSCody Peter Mello fs = getsval(fsloc);
1407*3ee4fc2aSCody Peter Mello else if (arg3type == STRING) { /* split(str,arr,"string") */
14087c478bd9Sstevel@tonic-gate x = execute(a[2]);
1409*3ee4fc2aSCody Peter Mello origfs = fs = tostring(getsval(x));
1410*3ee4fc2aSCody Peter Mello tempfree(x);
1411*3ee4fc2aSCody Peter Mello } else if (arg3type == REGEXPR)
1412*3ee4fc2aSCody Peter Mello fs = "(regexpr)"; /* split(str,arr,/regexpr/) */
14137c478bd9Sstevel@tonic-gate else
1414*3ee4fc2aSCody Peter Mello FATAL("illegal type of split");
14157c478bd9Sstevel@tonic-gate sep = *fs;
14167c478bd9Sstevel@tonic-gate ap = execute(a[1]); /* array name */
14177c478bd9Sstevel@tonic-gate freesymtab(ap);
1418*3ee4fc2aSCody Peter Mello dprintf(("split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs));
14197c478bd9Sstevel@tonic-gate ap->tval &= ~STR;
14207c478bd9Sstevel@tonic-gate ap->tval |= ARR;
1421*3ee4fc2aSCody Peter Mello ap->sval = (char *)makesymtab(NSYMTAB);
14227c478bd9Sstevel@tonic-gate
14237c478bd9Sstevel@tonic-gate n = 0;
1424*3ee4fc2aSCody Peter Mello if (arg3type == REGEXPR && strlen((char *)((fa*)a[2])->restr) == 0) {
1425*3ee4fc2aSCody Peter Mello /*
1426*3ee4fc2aSCody Peter Mello * split(s, a, //); have to arrange things such that it looks
1427*3ee4fc2aSCody Peter Mello * like an empty separator.
1428*3ee4fc2aSCody Peter Mello */
1429*3ee4fc2aSCody Peter Mello arg3type = 0;
1430*3ee4fc2aSCody Peter Mello fs = "";
1431*3ee4fc2aSCody Peter Mello sep = 0;
1432*3ee4fc2aSCody Peter Mello }
1433*3ee4fc2aSCody Peter Mello if (*s != '\0' && (strlen(fs) > 1 || arg3type == REGEXPR)) {
14341ee2e5faSnakanon /* reg expr */
14357c478bd9Sstevel@tonic-gate fa *pfa;
1436*3ee4fc2aSCody Peter Mello if (arg3type == REGEXPR) { /* it's ready already */
14371ee2e5faSnakanon pfa = (fa *)a[2];
14387c478bd9Sstevel@tonic-gate } else {
14397c478bd9Sstevel@tonic-gate pfa = makedfa(fs, 1);
14407c478bd9Sstevel@tonic-gate }
14411ee2e5faSnakanon if (nematch(pfa, s)) {
14427c478bd9Sstevel@tonic-gate tempstat = pfa->initstat;
14437c478bd9Sstevel@tonic-gate pfa->initstat = 2;
14447c478bd9Sstevel@tonic-gate do {
14457c478bd9Sstevel@tonic-gate n++;
1446*3ee4fc2aSCody Peter Mello (void) sprintf(num, "%d", n);
14477c478bd9Sstevel@tonic-gate temp = *patbeg;
14487c478bd9Sstevel@tonic-gate *patbeg = '\0';
14491ee2e5faSnakanon if (is_number(s)) {
14501ee2e5faSnakanon (void) setsymtab(num, s,
1451*3ee4fc2aSCody Peter Mello atof(s),
14521ee2e5faSnakanon /*LINTED align*/
14531ee2e5faSnakanon STR|NUM, (Array *)ap->sval);
14541ee2e5faSnakanon } else {
14551ee2e5faSnakanon (void) setsymtab(num, s, 0.0,
14561ee2e5faSnakanon /*LINTED align*/
14571ee2e5faSnakanon STR, (Array *)ap->sval);
14581ee2e5faSnakanon }
14597c478bd9Sstevel@tonic-gate *patbeg = temp;
14607c478bd9Sstevel@tonic-gate s = patbeg + patlen;
14617c478bd9Sstevel@tonic-gate if (*(patbeg+patlen-1) == 0 || *s == 0) {
14627c478bd9Sstevel@tonic-gate n++;
1463*3ee4fc2aSCody Peter Mello (void) sprintf(num, "%d", n);
1464*3ee4fc2aSCody Peter Mello (void) setsymtab(num, "", 0.0,
14651ee2e5faSnakanon /*LINTED align*/
14661ee2e5faSnakanon STR, (Array *)ap->sval);
14677c478bd9Sstevel@tonic-gate pfa->initstat = tempstat;
14687c478bd9Sstevel@tonic-gate goto spdone;
14697c478bd9Sstevel@tonic-gate }
14701ee2e5faSnakanon } while (nematch(pfa, s));
1471*3ee4fc2aSCody Peter Mello /* bwk: has to be here to reset */
1472*3ee4fc2aSCody Peter Mello /* cf gsub and refldbld */
1473*3ee4fc2aSCody Peter Mello pfa->initstat = tempstat;
14747c478bd9Sstevel@tonic-gate }
14757c478bd9Sstevel@tonic-gate n++;
1476*3ee4fc2aSCody Peter Mello (void) sprintf(num, "%d", n);
14771ee2e5faSnakanon if (is_number(s)) {
1478*3ee4fc2aSCody Peter Mello (void) setsymtab(num, s, atof(s),
14791ee2e5faSnakanon /*LINTED align*/
14801ee2e5faSnakanon STR|NUM, (Array *)ap->sval);
14811ee2e5faSnakanon } else {
14821ee2e5faSnakanon /*LINTED align*/
14831ee2e5faSnakanon (void) setsymtab(num, s, 0.0, STR, (Array *)ap->sval);
14841ee2e5faSnakanon }
14851ee2e5faSnakanon spdone:
14867c478bd9Sstevel@tonic-gate pfa = NULL;
14877c478bd9Sstevel@tonic-gate } else if (sep == ' ') {
14887c478bd9Sstevel@tonic-gate for (n = 0; ; ) {
14897c478bd9Sstevel@tonic-gate while (*s == ' ' || *s == '\t' || *s == '\n')
14907c478bd9Sstevel@tonic-gate s++;
1491*3ee4fc2aSCody Peter Mello if (*s == '\0')
14927c478bd9Sstevel@tonic-gate break;
14937c478bd9Sstevel@tonic-gate n++;
14947c478bd9Sstevel@tonic-gate t = s;
14957c478bd9Sstevel@tonic-gate do
14967c478bd9Sstevel@tonic-gate s++;
14971ee2e5faSnakanon while (*s != ' ' && *s != '\t' &&
14981ee2e5faSnakanon *s != '\n' && *s != '\0')
14991ee2e5faSnakanon ;
15007c478bd9Sstevel@tonic-gate temp = *s;
15017c478bd9Sstevel@tonic-gate *s = '\0';
1502*3ee4fc2aSCody Peter Mello (void) sprintf(num, "%d", n);
15031ee2e5faSnakanon if (is_number(t)) {
1504*3ee4fc2aSCody Peter Mello (void) setsymtab(num, t, atof(t),
15051ee2e5faSnakanon /*LINTED align*/
15061ee2e5faSnakanon STR|NUM, (Array *)ap->sval);
15071ee2e5faSnakanon } else {
15081ee2e5faSnakanon (void) setsymtab(num, t, 0.0,
15091ee2e5faSnakanon /*LINTED align*/
15101ee2e5faSnakanon STR, (Array *)ap->sval);
15111ee2e5faSnakanon }
15127c478bd9Sstevel@tonic-gate *s = temp;
1513*3ee4fc2aSCody Peter Mello if (*s != '\0')
15147c478bd9Sstevel@tonic-gate s++;
15157c478bd9Sstevel@tonic-gate }
1516*3ee4fc2aSCody Peter Mello } else if (sep == '\0') { /* split(s, a, "") => 1 char/elem */
1517*3ee4fc2aSCody Peter Mello for (n = 0; *s != 0; s++) {
1518*3ee4fc2aSCody Peter Mello char buf[2];
1519*3ee4fc2aSCody Peter Mello n++;
1520*3ee4fc2aSCody Peter Mello (void) sprintf(num, "%d", n);
1521*3ee4fc2aSCody Peter Mello buf[0] = *s;
1522*3ee4fc2aSCody Peter Mello buf[1] = '\0';
1523*3ee4fc2aSCody Peter Mello if (isdigit((uschar)buf[0])) {
1524*3ee4fc2aSCody Peter Mello (void) setsymtab(num, buf, atof(buf),
1525*3ee4fc2aSCody Peter Mello /*LINTED align*/
1526*3ee4fc2aSCody Peter Mello STR|NUM, (Array *)ap->sval);
1527*3ee4fc2aSCody Peter Mello } else {
1528*3ee4fc2aSCody Peter Mello (void) setsymtab(num, buf, 0.0,
1529*3ee4fc2aSCody Peter Mello /*LINTED align*/
1530*3ee4fc2aSCody Peter Mello STR, (Array *)ap->sval);
1531*3ee4fc2aSCody Peter Mello }
1532*3ee4fc2aSCody Peter Mello }
1533*3ee4fc2aSCody Peter Mello } else if (*s != '\0') {
15347c478bd9Sstevel@tonic-gate for (;;) {
15357c478bd9Sstevel@tonic-gate n++;
15367c478bd9Sstevel@tonic-gate t = s;
15377c478bd9Sstevel@tonic-gate while (*s != sep && *s != '\n' && *s != '\0')
15387c478bd9Sstevel@tonic-gate s++;
15397c478bd9Sstevel@tonic-gate temp = *s;
15407c478bd9Sstevel@tonic-gate *s = '\0';
1541*3ee4fc2aSCody Peter Mello (void) sprintf(num, "%d", n);
15421ee2e5faSnakanon if (is_number(t)) {
1543*3ee4fc2aSCody Peter Mello (void) setsymtab(num, t, atof(t),
15441ee2e5faSnakanon /*LINTED align*/
15451ee2e5faSnakanon STR|NUM, (Array *)ap->sval);
15461ee2e5faSnakanon } else {
15471ee2e5faSnakanon (void) setsymtab(num, t, 0.0,
15481ee2e5faSnakanon /*LINTED align*/
15491ee2e5faSnakanon STR, (Array *)ap->sval);
15501ee2e5faSnakanon }
15517c478bd9Sstevel@tonic-gate *s = temp;
1552*3ee4fc2aSCody Peter Mello if (*s++ == '\0')
15537c478bd9Sstevel@tonic-gate break;
15547c478bd9Sstevel@tonic-gate }
15557c478bd9Sstevel@tonic-gate }
1556*3ee4fc2aSCody Peter Mello tempfree(ap);
1557*3ee4fc2aSCody Peter Mello tempfree(y);
1558*3ee4fc2aSCody Peter Mello free(origs);
1559*3ee4fc2aSCody Peter Mello free(origfs);
1560*3ee4fc2aSCody Peter Mello x = gettemp();
15617c478bd9Sstevel@tonic-gate x->tval = NUM;
15627c478bd9Sstevel@tonic-gate x->fval = n;
15631ee2e5faSnakanon return (x);
15647c478bd9Sstevel@tonic-gate }
15657c478bd9Sstevel@tonic-gate
15661ee2e5faSnakanon /*ARGSUSED*/
15671ee2e5faSnakanon Cell *
condexpr(Node ** a,int n)1568*3ee4fc2aSCody Peter Mello condexpr(Node **a, int n) /* a[0] ? a[1] : a[2] */
15697c478bd9Sstevel@tonic-gate {
1570*3ee4fc2aSCody Peter Mello Cell *x;
15717c478bd9Sstevel@tonic-gate
15727c478bd9Sstevel@tonic-gate x = execute(a[0]);
15737c478bd9Sstevel@tonic-gate if (istrue(x)) {
1574*3ee4fc2aSCody Peter Mello tempfree(x);
15757c478bd9Sstevel@tonic-gate x = execute(a[1]);
15767c478bd9Sstevel@tonic-gate } else {
1577*3ee4fc2aSCody Peter Mello tempfree(x);
15787c478bd9Sstevel@tonic-gate x = execute(a[2]);
15797c478bd9Sstevel@tonic-gate }
15801ee2e5faSnakanon return (x);
15817c478bd9Sstevel@tonic-gate }
15827c478bd9Sstevel@tonic-gate
15831ee2e5faSnakanon /*ARGSUSED*/
15841ee2e5faSnakanon Cell *
ifstat(Node ** a,int n)1585*3ee4fc2aSCody Peter Mello ifstat(Node **a, int n) /* if (a[0]) a[1]; else a[2] */
15867c478bd9Sstevel@tonic-gate {
1587*3ee4fc2aSCody Peter Mello Cell *x;
15887c478bd9Sstevel@tonic-gate
15897c478bd9Sstevel@tonic-gate x = execute(a[0]);
15907c478bd9Sstevel@tonic-gate if (istrue(x)) {
1591*3ee4fc2aSCody Peter Mello tempfree(x);
15927c478bd9Sstevel@tonic-gate x = execute(a[1]);
1593*3ee4fc2aSCody Peter Mello } else if (a[2] != NULL) {
1594*3ee4fc2aSCody Peter Mello tempfree(x);
15957c478bd9Sstevel@tonic-gate x = execute(a[2]);
15967c478bd9Sstevel@tonic-gate }
15971ee2e5faSnakanon return (x);
15987c478bd9Sstevel@tonic-gate }
15997c478bd9Sstevel@tonic-gate
16001ee2e5faSnakanon /*ARGSUSED*/
16011ee2e5faSnakanon Cell *
whilestat(Node ** a,int n)1602*3ee4fc2aSCody Peter Mello whilestat(Node **a, int n) /* while (a[0]) a[1] */
16037c478bd9Sstevel@tonic-gate {
1604*3ee4fc2aSCody Peter Mello Cell *x;
16057c478bd9Sstevel@tonic-gate
16067c478bd9Sstevel@tonic-gate for (;;) {
16077c478bd9Sstevel@tonic-gate x = execute(a[0]);
16087c478bd9Sstevel@tonic-gate if (!istrue(x))
16091ee2e5faSnakanon return (x);
1610*3ee4fc2aSCody Peter Mello tempfree(x);
16117c478bd9Sstevel@tonic-gate x = execute(a[1]);
16127c478bd9Sstevel@tonic-gate if (isbreak(x)) {
1613*3ee4fc2aSCody Peter Mello x = True;
16141ee2e5faSnakanon return (x);
16157c478bd9Sstevel@tonic-gate }
16167c478bd9Sstevel@tonic-gate if (isnext(x) || isexit(x) || isret(x))
16171ee2e5faSnakanon return (x);
1618*3ee4fc2aSCody Peter Mello tempfree(x);
16197c478bd9Sstevel@tonic-gate }
16207c478bd9Sstevel@tonic-gate }
16217c478bd9Sstevel@tonic-gate
16221ee2e5faSnakanon /*ARGSUSED*/
16231ee2e5faSnakanon Cell *
dostat(Node ** a,int n)1624*3ee4fc2aSCody Peter Mello dostat(Node **a, int n) /* do a[0]; while(a[1]) */
16257c478bd9Sstevel@tonic-gate {
1626*3ee4fc2aSCody Peter Mello Cell *x;
16277c478bd9Sstevel@tonic-gate
16287c478bd9Sstevel@tonic-gate for (;;) {
16297c478bd9Sstevel@tonic-gate x = execute(a[0]);
16307c478bd9Sstevel@tonic-gate if (isbreak(x))
1631*3ee4fc2aSCody Peter Mello return (True);
16327c478bd9Sstevel@tonic-gate if (isnext(x) || isexit(x) || isret(x))
16331ee2e5faSnakanon return (x);
1634*3ee4fc2aSCody Peter Mello tempfree(x);
16357c478bd9Sstevel@tonic-gate x = execute(a[1]);
16367c478bd9Sstevel@tonic-gate if (!istrue(x))
16371ee2e5faSnakanon return (x);
1638*3ee4fc2aSCody Peter Mello tempfree(x);
16397c478bd9Sstevel@tonic-gate }
16407c478bd9Sstevel@tonic-gate }
16417c478bd9Sstevel@tonic-gate
16421ee2e5faSnakanon /*ARGSUSED*/
16431ee2e5faSnakanon Cell *
forstat(Node ** a,int n)1644*3ee4fc2aSCody Peter Mello forstat(Node **a, int n) /* for (a[0]; a[1]; a[2]) a[3] */
16457c478bd9Sstevel@tonic-gate {
1646*3ee4fc2aSCody Peter Mello Cell *x;
16477c478bd9Sstevel@tonic-gate
16487c478bd9Sstevel@tonic-gate x = execute(a[0]);
1649*3ee4fc2aSCody Peter Mello tempfree(x);
16507c478bd9Sstevel@tonic-gate for (;;) {
1651*3ee4fc2aSCody Peter Mello if (a[1] != NULL) {
16527c478bd9Sstevel@tonic-gate x = execute(a[1]);
16531ee2e5faSnakanon if (!istrue(x))
16541ee2e5faSnakanon return (x);
16551ee2e5faSnakanon else
1656*3ee4fc2aSCody Peter Mello tempfree(x);
16577c478bd9Sstevel@tonic-gate }
16587c478bd9Sstevel@tonic-gate x = execute(a[3]);
16597c478bd9Sstevel@tonic-gate if (isbreak(x)) /* turn off break */
1660*3ee4fc2aSCody Peter Mello return (True);
16617c478bd9Sstevel@tonic-gate if (isnext(x) || isexit(x) || isret(x))
16621ee2e5faSnakanon return (x);
1663*3ee4fc2aSCody Peter Mello tempfree(x);
16647c478bd9Sstevel@tonic-gate x = execute(a[2]);
1665*3ee4fc2aSCody Peter Mello tempfree(x);
16667c478bd9Sstevel@tonic-gate }
16677c478bd9Sstevel@tonic-gate }
16687c478bd9Sstevel@tonic-gate
16691ee2e5faSnakanon /*ARGSUSED*/
16701ee2e5faSnakanon Cell *
instat(Node ** a,int n)1671*3ee4fc2aSCody Peter Mello instat(Node **a, int n) /* for (a[0] in a[1]) a[2] */
16727c478bd9Sstevel@tonic-gate {
1673*3ee4fc2aSCody Peter Mello Cell *x, *vp, *arrayp, *cp, *ncp;
16747c478bd9Sstevel@tonic-gate Array *tp;
16757c478bd9Sstevel@tonic-gate int i;
16767c478bd9Sstevel@tonic-gate
16777c478bd9Sstevel@tonic-gate vp = execute(a[0]);
16787c478bd9Sstevel@tonic-gate arrayp = execute(a[1]);
1679*3ee4fc2aSCody Peter Mello if (!isarr(arrayp)) {
1680*3ee4fc2aSCody Peter Mello dprintf(("making %s into an array\n", arrayp->nval));
1681*3ee4fc2aSCody Peter Mello if (freeable(arrayp))
1682*3ee4fc2aSCody Peter Mello xfree(arrayp->sval);
1683*3ee4fc2aSCody Peter Mello arrayp->tval &= ~(STR|NUM|DONTFREE);
1684*3ee4fc2aSCody Peter Mello arrayp->tval |= ARR;
1685*3ee4fc2aSCody Peter Mello arrayp->sval = (char *)makesymtab(NSYMTAB);
1686*3ee4fc2aSCody Peter Mello }
16871ee2e5faSnakanon /*LINTED align*/
16881ee2e5faSnakanon tp = (Array *)arrayp->sval;
1689*3ee4fc2aSCody Peter Mello tempfree(arrayp);
16901ee2e5faSnakanon for (i = 0; i < tp->size; i++) { /* this routine knows too much */
16917c478bd9Sstevel@tonic-gate for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
16921ee2e5faSnakanon (void) setsval(vp, cp->nval);
16937c478bd9Sstevel@tonic-gate ncp = cp->cnext;
16947c478bd9Sstevel@tonic-gate x = execute(a[2]);
16957c478bd9Sstevel@tonic-gate if (isbreak(x)) {
1696*3ee4fc2aSCody Peter Mello tempfree(vp);
1697*3ee4fc2aSCody Peter Mello return (True);
16987c478bd9Sstevel@tonic-gate }
16997c478bd9Sstevel@tonic-gate if (isnext(x) || isexit(x) || isret(x)) {
1700*3ee4fc2aSCody Peter Mello tempfree(vp);
17011ee2e5faSnakanon return (x);
17027c478bd9Sstevel@tonic-gate }
1703*3ee4fc2aSCody Peter Mello tempfree(x);
17047c478bd9Sstevel@tonic-gate }
17057c478bd9Sstevel@tonic-gate }
1706*3ee4fc2aSCody Peter Mello return (True);
17077c478bd9Sstevel@tonic-gate }
17087c478bd9Sstevel@tonic-gate
17091ee2e5faSnakanon /*ARGSUSED*/
17101ee2e5faSnakanon Cell *
bltin(Node ** a,int n)1711*3ee4fc2aSCody Peter Mello bltin(Node **a, int n) /* builtin functions. a[0] is type, a[1] is arg list */
17127c478bd9Sstevel@tonic-gate {
1713*3ee4fc2aSCody Peter Mello Cell *x, *y;
17147c478bd9Sstevel@tonic-gate Awkfloat u;
1715*3ee4fc2aSCody Peter Mello int t;
1716*3ee4fc2aSCody Peter Mello Awkfloat tmp;
1717*3ee4fc2aSCody Peter Mello char *p, *buf;
17187c478bd9Sstevel@tonic-gate Node *nextarg;
1719*3ee4fc2aSCody Peter Mello FILE *fp;
1720*3ee4fc2aSCody Peter Mello void flush_all(void);
1721*3ee4fc2aSCody Peter Mello int status = 0;
17227c478bd9Sstevel@tonic-gate
1723*3ee4fc2aSCody Peter Mello t = ptoi(a[0]);
17247c478bd9Sstevel@tonic-gate x = execute(a[1]);
17257c478bd9Sstevel@tonic-gate nextarg = a[1]->nnext;
17267c478bd9Sstevel@tonic-gate switch (t) {
17277c478bd9Sstevel@tonic-gate case FLENGTH:
1728*3ee4fc2aSCody Peter Mello if (isarr(x)) {
1729*3ee4fc2aSCody Peter Mello /* LINTED align */
1730*3ee4fc2aSCody Peter Mello u = ((Array *)x->sval)->nelem;
1731*3ee4fc2aSCody Peter Mello } else {
1732*3ee4fc2aSCody Peter Mello u = strlen(getsval(x));
1733*3ee4fc2aSCody Peter Mello }
1734*3ee4fc2aSCody Peter Mello break;
17357c478bd9Sstevel@tonic-gate case FLOG:
17367c478bd9Sstevel@tonic-gate u = errcheck(log(getfval(x)), "log"); break;
17377c478bd9Sstevel@tonic-gate case FINT:
17381ee2e5faSnakanon (void) modf(getfval(x), &u); break;
17397c478bd9Sstevel@tonic-gate case FEXP:
17407c478bd9Sstevel@tonic-gate u = errcheck(exp(getfval(x)), "exp"); break;
17417c478bd9Sstevel@tonic-gate case FSQRT:
17427c478bd9Sstevel@tonic-gate u = errcheck(sqrt(getfval(x)), "sqrt"); break;
17437c478bd9Sstevel@tonic-gate case FSIN:
17447c478bd9Sstevel@tonic-gate u = sin(getfval(x)); break;
17457c478bd9Sstevel@tonic-gate case FCOS:
17467c478bd9Sstevel@tonic-gate u = cos(getfval(x)); break;
17477c478bd9Sstevel@tonic-gate case FATAN:
1748*3ee4fc2aSCody Peter Mello if (nextarg == NULL) {
1749*3ee4fc2aSCody Peter Mello WARNING("atan2 requires two arguments; returning 1.0");
17507c478bd9Sstevel@tonic-gate u = 1.0;
17517c478bd9Sstevel@tonic-gate } else {
17527c478bd9Sstevel@tonic-gate y = execute(a[1]->nnext);
17537c478bd9Sstevel@tonic-gate u = atan2(getfval(x), getfval(y));
1754*3ee4fc2aSCody Peter Mello tempfree(y);
17557c478bd9Sstevel@tonic-gate nextarg = nextarg->nnext;
17567c478bd9Sstevel@tonic-gate }
17577c478bd9Sstevel@tonic-gate break;
17587c478bd9Sstevel@tonic-gate case FSYSTEM:
17591ee2e5faSnakanon /* in case something is buffered already */
17601ee2e5faSnakanon (void) fflush(stdout);
1761*3ee4fc2aSCody Peter Mello status = system(getsval(x));
1762*3ee4fc2aSCody Peter Mello u = status;
1763*3ee4fc2aSCody Peter Mello if (status != -1) {
1764*3ee4fc2aSCody Peter Mello if (WIFEXITED(status)) {
1765*3ee4fc2aSCody Peter Mello u = WEXITSTATUS(status);
1766*3ee4fc2aSCody Peter Mello } else if (WIFSIGNALED(status)) {
1767*3ee4fc2aSCody Peter Mello u = WTERMSIG(status) + 256;
1768*3ee4fc2aSCody Peter Mello if (WCOREDUMP(status))
1769*3ee4fc2aSCody Peter Mello u += 256;
1770*3ee4fc2aSCody Peter Mello } else /* something else?!? */
1771*3ee4fc2aSCody Peter Mello u = 0;
1772*3ee4fc2aSCody Peter Mello }
17737c478bd9Sstevel@tonic-gate break;
17747c478bd9Sstevel@tonic-gate case FRAND:
1775*3ee4fc2aSCody Peter Mello /* in principle, rand() returns something in 0..RAND_MAX */
1776*3ee4fc2aSCody Peter Mello u = (Awkfloat) (rand() % RAND_MAX) / RAND_MAX;
17777c478bd9Sstevel@tonic-gate break;
17787c478bd9Sstevel@tonic-gate case FSRAND:
1779*3ee4fc2aSCody Peter Mello if (isrec(x)) /* no argument provided */
17807c478bd9Sstevel@tonic-gate u = time((time_t *)0);
17817c478bd9Sstevel@tonic-gate else
17827c478bd9Sstevel@tonic-gate u = getfval(x);
1783*3ee4fc2aSCody Peter Mello tmp = u;
1784*3ee4fc2aSCody Peter Mello srand((unsigned int) u);
1785*3ee4fc2aSCody Peter Mello u = srand_seed;
1786*3ee4fc2aSCody Peter Mello srand_seed = tmp;
17877c478bd9Sstevel@tonic-gate break;
17887c478bd9Sstevel@tonic-gate case FTOUPPER:
17897c478bd9Sstevel@tonic-gate case FTOLOWER:
17901ee2e5faSnakanon buf = tostring(getsval(x));
17917c478bd9Sstevel@tonic-gate if (t == FTOUPPER) {
17927c478bd9Sstevel@tonic-gate for (p = buf; *p; p++)
1793*3ee4fc2aSCody Peter Mello if (islower((uschar)*p))
1794*3ee4fc2aSCody Peter Mello *p = toupper((uschar)*p);
17957c478bd9Sstevel@tonic-gate } else {
17967c478bd9Sstevel@tonic-gate for (p = buf; *p; p++)
1797*3ee4fc2aSCody Peter Mello if (isupper((uschar)*p))
1798*3ee4fc2aSCody Peter Mello *p = tolower((uschar)*p);
17997c478bd9Sstevel@tonic-gate }
1800*3ee4fc2aSCody Peter Mello tempfree(x);
1801*3ee4fc2aSCody Peter Mello x = gettemp();
18021ee2e5faSnakanon (void) setsval(x, buf);
18031ee2e5faSnakanon free(buf);
18041ee2e5faSnakanon return (x);
1805*3ee4fc2aSCody Peter Mello case FFLUSH:
1806*3ee4fc2aSCody Peter Mello if (isrec(x) || strlen(getsval(x)) == 0) {
1807*3ee4fc2aSCody Peter Mello flush_all(); /* fflush() or fflush("") -> all */
1808*3ee4fc2aSCody Peter Mello u = 0;
1809*3ee4fc2aSCody Peter Mello } else if ((fp = openfile(FFLUSH, getsval(x))) == NULL)
1810*3ee4fc2aSCody Peter Mello u = EOF;
1811*3ee4fc2aSCody Peter Mello else
1812*3ee4fc2aSCody Peter Mello u = fflush(fp);
1813*3ee4fc2aSCody Peter Mello break;
18147c478bd9Sstevel@tonic-gate default: /* can't happen */
1815*3ee4fc2aSCody Peter Mello FATAL("illegal function type %d", t);
18167c478bd9Sstevel@tonic-gate break;
18177c478bd9Sstevel@tonic-gate }
1818*3ee4fc2aSCody Peter Mello tempfree(x);
1819*3ee4fc2aSCody Peter Mello x = gettemp();
18201ee2e5faSnakanon (void) setfval(x, u);
1821*3ee4fc2aSCody Peter Mello if (nextarg != NULL) {
1822*3ee4fc2aSCody Peter Mello WARNING("warning: function has too many arguments");
1823*3ee4fc2aSCody Peter Mello for (; nextarg != NULL; nextarg = nextarg->nnext)
18241ee2e5faSnakanon (void) execute(nextarg);
18257c478bd9Sstevel@tonic-gate }
18261ee2e5faSnakanon return (x);
18277c478bd9Sstevel@tonic-gate }
18287c478bd9Sstevel@tonic-gate
18291ee2e5faSnakanon /*ARGSUSED*/
18301ee2e5faSnakanon Cell *
printstat(Node ** a,int n)1831*3ee4fc2aSCody Peter Mello printstat(Node **a, int n) /* print a[0] */
18327c478bd9Sstevel@tonic-gate {
1833*3ee4fc2aSCody Peter Mello Node *x;
1834*3ee4fc2aSCody Peter Mello Cell *y;
18357c478bd9Sstevel@tonic-gate FILE *fp;
18367c478bd9Sstevel@tonic-gate
1837*3ee4fc2aSCody Peter Mello if (a[1] == NULL) /* a[1] is redirection operator, a[2] is file */
18387c478bd9Sstevel@tonic-gate fp = stdout;
18397c478bd9Sstevel@tonic-gate else
1840*3ee4fc2aSCody Peter Mello fp = redirect(ptoi(a[1]), a[2]);
18417c478bd9Sstevel@tonic-gate for (x = a[0]; x != NULL; x = x->nnext) {
18427c478bd9Sstevel@tonic-gate y = execute(x);
1843*3ee4fc2aSCody Peter Mello (void) fputs(getpssval(y), fp);
1844*3ee4fc2aSCody Peter Mello tempfree(y);
18457c478bd9Sstevel@tonic-gate if (x->nnext == NULL)
1846*3ee4fc2aSCody Peter Mello (void) fputs(getsval(orsloc), fp);
18477c478bd9Sstevel@tonic-gate else
1848*3ee4fc2aSCody Peter Mello (void) fputs(getsval(ofsloc), fp);
18497c478bd9Sstevel@tonic-gate }
1850*3ee4fc2aSCody Peter Mello if (a[1] != NULL)
18511ee2e5faSnakanon (void) fflush(fp);
1852*3ee4fc2aSCody Peter Mello if (ferror(fp))
1853*3ee4fc2aSCody Peter Mello FATAL("write error on %s", filename(fp));
1854*3ee4fc2aSCody Peter Mello return (True);
18557c478bd9Sstevel@tonic-gate }
18567c478bd9Sstevel@tonic-gate
18571ee2e5faSnakanon /*ARGSUSED*/
18581ee2e5faSnakanon Cell *
nullproc(Node ** a,int n)18591ee2e5faSnakanon nullproc(Node **a, int n)
18607c478bd9Sstevel@tonic-gate {
18611ee2e5faSnakanon return (0);
18621ee2e5faSnakanon }
18631ee2e5faSnakanon
18647c478bd9Sstevel@tonic-gate
18651ee2e5faSnakanon static FILE *
redirect(int a,Node * b)1866*3ee4fc2aSCody Peter Mello redirect(int a, Node *b) /* set up all i/o redirections */
18677c478bd9Sstevel@tonic-gate {
18687c478bd9Sstevel@tonic-gate FILE *fp;
18697c478bd9Sstevel@tonic-gate Cell *x;
1870*3ee4fc2aSCody Peter Mello char *fname;
18717c478bd9Sstevel@tonic-gate
18727c478bd9Sstevel@tonic-gate x = execute(b);
18737c478bd9Sstevel@tonic-gate fname = getsval(x);
18747c478bd9Sstevel@tonic-gate fp = openfile(a, fname);
18757c478bd9Sstevel@tonic-gate if (fp == NULL)
1876*3ee4fc2aSCody Peter Mello FATAL("can't open file %s", fname);
1877*3ee4fc2aSCody Peter Mello tempfree(x);
18781ee2e5faSnakanon return (fp);
18797c478bd9Sstevel@tonic-gate }
18807c478bd9Sstevel@tonic-gate
1881*3ee4fc2aSCody Peter Mello struct files {
1882*3ee4fc2aSCody Peter Mello FILE *fp;
1883*3ee4fc2aSCody Peter Mello const char *fname;
1884*3ee4fc2aSCody Peter Mello int mode; /* '|', 'a', 'w' => LE/LT, GT */
1885*3ee4fc2aSCody Peter Mello } *files;
1886*3ee4fc2aSCody Peter Mello
1887*3ee4fc2aSCody Peter Mello int nfiles;
1888*3ee4fc2aSCody Peter Mello
1889*3ee4fc2aSCody Peter Mello void
stdinit(void)1890*3ee4fc2aSCody Peter Mello stdinit(void) /* in case stdin, etc., are not constants */
1891*3ee4fc2aSCody Peter Mello {
1892*3ee4fc2aSCody Peter Mello nfiles = FOPEN_MAX;
1893*3ee4fc2aSCody Peter Mello files = calloc(nfiles, sizeof (*files));
1894*3ee4fc2aSCody Peter Mello if (files == NULL)
1895*3ee4fc2aSCody Peter Mello FATAL("can't allocate file memory for %u files", nfiles);
1896*3ee4fc2aSCody Peter Mello files[0].fp = stdin;
1897*3ee4fc2aSCody Peter Mello files[0].fname = "/dev/stdin";
1898*3ee4fc2aSCody Peter Mello files[0].mode = LT;
1899*3ee4fc2aSCody Peter Mello files[1].fp = stdout;
1900*3ee4fc2aSCody Peter Mello files[1].fname = "/dev/stdout";
1901*3ee4fc2aSCody Peter Mello files[1].mode = GT;
1902*3ee4fc2aSCody Peter Mello files[2].fp = stderr;
1903*3ee4fc2aSCody Peter Mello files[2].fname = "/dev/stderr";
1904*3ee4fc2aSCody Peter Mello files[2].mode = GT;
1905*3ee4fc2aSCody Peter Mello }
1906*3ee4fc2aSCody Peter Mello
19071ee2e5faSnakanon static FILE *
openfile(int a,const char * s)1908*3ee4fc2aSCody Peter Mello openfile(int a, const char *s)
19097c478bd9Sstevel@tonic-gate {
1910*3ee4fc2aSCody Peter Mello int i, m;
1911*3ee4fc2aSCody Peter Mello FILE *fp = NULL;
19127c478bd9Sstevel@tonic-gate
19137c478bd9Sstevel@tonic-gate if (*s == '\0')
1914*3ee4fc2aSCody Peter Mello FATAL("null file name in print or getline");
1915*3ee4fc2aSCody Peter Mello for (i = 0; i < nfiles; i++) {
1916*3ee4fc2aSCody Peter Mello if (files[i].fname && strcmp(s, files[i].fname) == 0) {
19171ee2e5faSnakanon if (a == files[i].mode ||
1918*3ee4fc2aSCody Peter Mello (a == APPEND && files[i].mode == GT)) {
19191ee2e5faSnakanon return (files[i].fp);
19201ee2e5faSnakanon }
1921*3ee4fc2aSCody Peter Mello if (a == FFLUSH)
1922*3ee4fc2aSCody Peter Mello return (files[i].fp);
19231ee2e5faSnakanon }
19241ee2e5faSnakanon }
1925*3ee4fc2aSCody Peter Mello if (a == FFLUSH) /* didn't find it, so don't create it! */
1926*3ee4fc2aSCody Peter Mello return (NULL);
1927*3ee4fc2aSCody Peter Mello
1928*3ee4fc2aSCody Peter Mello for (i = 0; i < nfiles; i++) {
19297c478bd9Sstevel@tonic-gate if (files[i].fp == 0)
19307c478bd9Sstevel@tonic-gate break;
19311ee2e5faSnakanon }
1932*3ee4fc2aSCody Peter Mello if (i >= nfiles) {
1933*3ee4fc2aSCody Peter Mello struct files *nf;
1934*3ee4fc2aSCody Peter Mello int nnf = nfiles + FOPEN_MAX;
1935*3ee4fc2aSCody Peter Mello nf = realloc(files, nnf * sizeof (*nf));
1936*3ee4fc2aSCody Peter Mello if (nf == NULL)
1937*3ee4fc2aSCody Peter Mello FATAL("cannot grow files for %s and %d files", s, nnf);
1938*3ee4fc2aSCody Peter Mello (void) memset(&nf[nfiles], 0, FOPEN_MAX * sizeof (*nf));
1939*3ee4fc2aSCody Peter Mello nfiles = nnf;
1940*3ee4fc2aSCody Peter Mello files = nf;
1941*3ee4fc2aSCody Peter Mello }
19421ee2e5faSnakanon (void) fflush(stdout); /* force a semblance of order */
19437c478bd9Sstevel@tonic-gate m = a;
19447c478bd9Sstevel@tonic-gate if (a == GT) {
1945*3ee4fc2aSCody Peter Mello fp = fopen(s, "wF");
19467c478bd9Sstevel@tonic-gate } else if (a == APPEND) {
1947*3ee4fc2aSCody Peter Mello fp = fopen(s, "aF");
19487c478bd9Sstevel@tonic-gate m = GT; /* so can mix > and >> */
19497c478bd9Sstevel@tonic-gate } else if (a == '|') { /* output pipe */
1950*3ee4fc2aSCody Peter Mello fp = popen(s, "wF");
19517c478bd9Sstevel@tonic-gate } else if (a == LE) { /* input pipe */
1952*3ee4fc2aSCody Peter Mello fp = popen(s, "rF");
19537c478bd9Sstevel@tonic-gate } else if (a == LT) { /* getline <file */
1954*3ee4fc2aSCody Peter Mello fp = strcmp(s, "-") == 0 ?
1955*3ee4fc2aSCody Peter Mello stdin : fopen(s, "rF"); /* "-" is stdin */
19567c478bd9Sstevel@tonic-gate } else /* can't happen */
1957*3ee4fc2aSCody Peter Mello FATAL("illegal redirection %d", a);
19587c478bd9Sstevel@tonic-gate if (fp != NULL) {
19597c478bd9Sstevel@tonic-gate files[i].fname = tostring(s);
19607c478bd9Sstevel@tonic-gate files[i].fp = fp;
19617c478bd9Sstevel@tonic-gate files[i].mode = m;
19627c478bd9Sstevel@tonic-gate }
19631ee2e5faSnakanon return (fp);
19647c478bd9Sstevel@tonic-gate }
19657c478bd9Sstevel@tonic-gate
1966*3ee4fc2aSCody Peter Mello const char *
filename(FILE * fp)1967*3ee4fc2aSCody Peter Mello filename(FILE *fp)
1968*3ee4fc2aSCody Peter Mello {
1969*3ee4fc2aSCody Peter Mello int i;
1970*3ee4fc2aSCody Peter Mello
1971*3ee4fc2aSCody Peter Mello for (i = 0; i < nfiles; i++)
1972*3ee4fc2aSCody Peter Mello if (fp == files[i].fp)
1973*3ee4fc2aSCody Peter Mello return (files[i].fname);
1974*3ee4fc2aSCody Peter Mello return ("???");
1975*3ee4fc2aSCody Peter Mello }
1976*3ee4fc2aSCody Peter Mello
19771ee2e5faSnakanon /*ARGSUSED*/
19781ee2e5faSnakanon Cell *
closefile(Node ** a,int n)19791ee2e5faSnakanon closefile(Node **a, int n)
19807c478bd9Sstevel@tonic-gate {
1981*3ee4fc2aSCody Peter Mello Cell *x;
19827c478bd9Sstevel@tonic-gate int i, stat;
19837c478bd9Sstevel@tonic-gate
19847c478bd9Sstevel@tonic-gate x = execute(a[0]);
19851ee2e5faSnakanon (void) getsval(x);
1986*3ee4fc2aSCody Peter Mello stat = -1;
1987*3ee4fc2aSCody Peter Mello for (i = 0; i < nfiles; i++) {
1988*3ee4fc2aSCody Peter Mello if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) {
19891ee2e5faSnakanon if (ferror(files[i].fp)) {
1990*3ee4fc2aSCody Peter Mello WARNING("i/o error occurred on %s",
1991*3ee4fc2aSCody Peter Mello files[i].fname);
19921ee2e5faSnakanon }
19937c478bd9Sstevel@tonic-gate if (files[i].mode == '|' || files[i].mode == LE)
19947c478bd9Sstevel@tonic-gate stat = pclose(files[i].fp);
19957c478bd9Sstevel@tonic-gate else
19967c478bd9Sstevel@tonic-gate stat = fclose(files[i].fp);
19971ee2e5faSnakanon if (stat == EOF) {
1998*3ee4fc2aSCody Peter Mello WARNING("i/o error occurred closing %s",
1999*3ee4fc2aSCody Peter Mello files[i].fname);
20001ee2e5faSnakanon }
2001*3ee4fc2aSCody Peter Mello if (i > 2) /* don't do /dev/std... */
2002*3ee4fc2aSCody Peter Mello xfree(files[i].fname);
20031ee2e5faSnakanon /* watch out for ref thru this */
20041ee2e5faSnakanon files[i].fname = NULL;
20057c478bd9Sstevel@tonic-gate files[i].fp = NULL;
20067c478bd9Sstevel@tonic-gate }
20071ee2e5faSnakanon }
2008*3ee4fc2aSCody Peter Mello tempfree(x);
2009*3ee4fc2aSCody Peter Mello x = gettemp();
2010*3ee4fc2aSCody Peter Mello (void) setfval(x, (Awkfloat) stat);
2011*3ee4fc2aSCody Peter Mello return (x);
20127c478bd9Sstevel@tonic-gate }
20137c478bd9Sstevel@tonic-gate
20141ee2e5faSnakanon static void
closeall(void)20151ee2e5faSnakanon closeall(void)
20167c478bd9Sstevel@tonic-gate {
20177c478bd9Sstevel@tonic-gate int i, stat;
20187c478bd9Sstevel@tonic-gate
2019*3ee4fc2aSCody Peter Mello for (i = 0; i < nfiles; i++) {
20207c478bd9Sstevel@tonic-gate if (files[i].fp) {
20211ee2e5faSnakanon if (ferror(files[i].fp)) {
2022*3ee4fc2aSCody Peter Mello WARNING("i/o error occurred on %s",
2023*3ee4fc2aSCody Peter Mello files[i].fname);
20241ee2e5faSnakanon }
20257c478bd9Sstevel@tonic-gate if (files[i].mode == '|' || files[i].mode == LE)
20267c478bd9Sstevel@tonic-gate stat = pclose(files[i].fp);
20277c478bd9Sstevel@tonic-gate else
20287c478bd9Sstevel@tonic-gate stat = fclose(files[i].fp);
20291ee2e5faSnakanon if (stat == EOF) {
2030*3ee4fc2aSCody Peter Mello WARNING("i/o error occurred while closing %s",
2031*3ee4fc2aSCody Peter Mello files[i].fname);
20321ee2e5faSnakanon }
20337c478bd9Sstevel@tonic-gate }
20341ee2e5faSnakanon }
20357c478bd9Sstevel@tonic-gate }
20367c478bd9Sstevel@tonic-gate
2037*3ee4fc2aSCody Peter Mello void
flush_all(void)2038*3ee4fc2aSCody Peter Mello flush_all(void)
2039*3ee4fc2aSCody Peter Mello {
2040*3ee4fc2aSCody Peter Mello int i;
2041*3ee4fc2aSCody Peter Mello
2042*3ee4fc2aSCody Peter Mello for (i = 0; i < nfiles; i++)
2043*3ee4fc2aSCody Peter Mello if (files[i].fp)
2044*3ee4fc2aSCody Peter Mello (void) fflush(files[i].fp);
2045*3ee4fc2aSCody Peter Mello }
2046*3ee4fc2aSCody Peter Mello
20471ee2e5faSnakanon /*ARGSUSED*/
20481ee2e5faSnakanon Cell *
sub(Node ** a,int nnn)2049*3ee4fc2aSCody Peter Mello sub(Node **a, int nnn) /* substitute command */
20507c478bd9Sstevel@tonic-gate {
2051*3ee4fc2aSCody Peter Mello char *sptr, *pb, *q;
2052*3ee4fc2aSCody Peter Mello Cell *x, *y, *result;
2053*3ee4fc2aSCody Peter Mello char *t, *buf;
20547c478bd9Sstevel@tonic-gate fa *pfa;
2055*3ee4fc2aSCody Peter Mello size_t bufsz = recsize;
20567c478bd9Sstevel@tonic-gate
2057*3ee4fc2aSCody Peter Mello if ((buf = (char *)malloc(bufsz)) == NULL)
2058*3ee4fc2aSCody Peter Mello FATAL("out of memory in sub");
20597c478bd9Sstevel@tonic-gate x = execute(a[3]); /* target string */
20607c478bd9Sstevel@tonic-gate t = getsval(x);
2061*3ee4fc2aSCody Peter Mello if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */
20621ee2e5faSnakanon pfa = (fa *)a[1]; /* regular expression */
20637c478bd9Sstevel@tonic-gate else {
20647c478bd9Sstevel@tonic-gate y = execute(a[1]);
20657c478bd9Sstevel@tonic-gate pfa = makedfa(getsval(y), 1);
2066*3ee4fc2aSCody Peter Mello tempfree(y);
20677c478bd9Sstevel@tonic-gate }
20687c478bd9Sstevel@tonic-gate y = execute(a[2]); /* replacement string */
2069*3ee4fc2aSCody Peter Mello result = False;
20707c478bd9Sstevel@tonic-gate if (pmatch(pfa, t)) {
20717c478bd9Sstevel@tonic-gate sptr = t;
2072*3ee4fc2aSCody Peter Mello (void) adjbuf(&buf, &bufsz,
2073*3ee4fc2aSCody Peter Mello 1 + patbeg - sptr, recsize, 0, "sub");
2074*3ee4fc2aSCody Peter Mello pb = buf;
2075*3ee4fc2aSCody Peter Mello while (sptr < patbeg)
2076*3ee4fc2aSCody Peter Mello *pb++ = *sptr++;
20777c478bd9Sstevel@tonic-gate sptr = getsval(y);
2078*3ee4fc2aSCody Peter Mello while (*sptr != '\0') {
2079*3ee4fc2aSCody Peter Mello (void) adjbuf(&buf, &bufsz, 5 + pb - buf,
2080*3ee4fc2aSCody Peter Mello recsize, &pb, "sub");
2081*3ee4fc2aSCody Peter Mello if (*sptr == '\\') {
2082*3ee4fc2aSCody Peter Mello backsub(&pb, &sptr);
20837c478bd9Sstevel@tonic-gate } else if (*sptr == '&') {
20847c478bd9Sstevel@tonic-gate sptr++;
2085*3ee4fc2aSCody Peter Mello (void) adjbuf(&buf, &bufsz,
2086*3ee4fc2aSCody Peter Mello 1 + patlen + pb - buf, recsize, &pb, "sub");
2087*3ee4fc2aSCody Peter Mello for (q = patbeg; q < patbeg+patlen; )
2088*3ee4fc2aSCody Peter Mello *pb++ = *q++;
20891ee2e5faSnakanon } else {
2090*3ee4fc2aSCody Peter Mello *pb++ = *sptr++;
20911ee2e5faSnakanon }
20921ee2e5faSnakanon }
2093*3ee4fc2aSCody Peter Mello *pb = '\0';
2094*3ee4fc2aSCody Peter Mello if (pb > buf + bufsz)
2095*3ee4fc2aSCody Peter Mello FATAL("sub result1 %.30s too big; can't happen", buf);
20967c478bd9Sstevel@tonic-gate sptr = patbeg + patlen;
20971ee2e5faSnakanon if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
2098*3ee4fc2aSCody Peter Mello (void) adjbuf(&buf, &bufsz,
2099*3ee4fc2aSCody Peter Mello 1 + strlen(sptr) + pb - buf, 0, &pb, "sub");
2100*3ee4fc2aSCody Peter Mello while ((*pb++ = *sptr++) != '\0')
2101*3ee4fc2aSCody Peter Mello ;
21021ee2e5faSnakanon }
2103*3ee4fc2aSCody Peter Mello if (pb > buf + bufsz)
2104*3ee4fc2aSCody Peter Mello FATAL("sub result2 %.30s too big; can't happen", buf);
2105*3ee4fc2aSCody Peter Mello (void) setsval(x, buf); /* BUG: should be able to avoid copy */
2106*3ee4fc2aSCody Peter Mello result = True;
21077c478bd9Sstevel@tonic-gate }
2108*3ee4fc2aSCody Peter Mello tempfree(x);
2109*3ee4fc2aSCody Peter Mello tempfree(y);
2110*3ee4fc2aSCody Peter Mello free(buf);
21111ee2e5faSnakanon return (result);
21127c478bd9Sstevel@tonic-gate }
21137c478bd9Sstevel@tonic-gate
21141ee2e5faSnakanon /*ARGSUSED*/
21151ee2e5faSnakanon Cell *
gsub(Node ** a,int nnn)2116*3ee4fc2aSCody Peter Mello gsub(Node **a, int nnn) /* global substitute */
21177c478bd9Sstevel@tonic-gate {
2118*3ee4fc2aSCody Peter Mello Cell *x, *y;
2119*3ee4fc2aSCody Peter Mello char *rptr, *sptr, *t, *pb, *q;
2120*3ee4fc2aSCody Peter Mello char *buf;
2121*3ee4fc2aSCody Peter Mello fa *pfa;
21227c478bd9Sstevel@tonic-gate int mflag, tempstat, num;
2123*3ee4fc2aSCody Peter Mello size_t bufsz = recsize;
21247c478bd9Sstevel@tonic-gate
2125*3ee4fc2aSCody Peter Mello if ((buf = (char *)malloc(bufsz)) == NULL)
2126*3ee4fc2aSCody Peter Mello FATAL("out of memory in gsub");
21277c478bd9Sstevel@tonic-gate mflag = 0; /* if mflag == 0, can replace empty string */
21287c478bd9Sstevel@tonic-gate num = 0;
21297c478bd9Sstevel@tonic-gate x = execute(a[3]); /* target string */
21307c478bd9Sstevel@tonic-gate t = getsval(x);
2131*3ee4fc2aSCody Peter Mello if (a[0] == NULL) /* 0 => a[1] is already-compiled regexpr */
2132*3ee4fc2aSCody Peter Mello pfa = (fa *)a[1]; /* regular expression */
21337c478bd9Sstevel@tonic-gate else {
21347c478bd9Sstevel@tonic-gate y = execute(a[1]);
21357c478bd9Sstevel@tonic-gate pfa = makedfa(getsval(y), 1);
2136*3ee4fc2aSCody Peter Mello tempfree(y);
21377c478bd9Sstevel@tonic-gate }
21387c478bd9Sstevel@tonic-gate y = execute(a[2]); /* replacement string */
21397c478bd9Sstevel@tonic-gate if (pmatch(pfa, t)) {
21407c478bd9Sstevel@tonic-gate tempstat = pfa->initstat;
21417c478bd9Sstevel@tonic-gate pfa->initstat = 2;
2142*3ee4fc2aSCody Peter Mello pb = buf;
21437c478bd9Sstevel@tonic-gate rptr = getsval(y);
21447c478bd9Sstevel@tonic-gate do {
2145*3ee4fc2aSCody Peter Mello if (patlen == 0 && *patbeg != '\0') {
21461ee2e5faSnakanon /* matched empty string */
21477c478bd9Sstevel@tonic-gate if (mflag == 0) { /* can replace empty */
21487c478bd9Sstevel@tonic-gate num++;
21497c478bd9Sstevel@tonic-gate sptr = rptr;
2150*3ee4fc2aSCody Peter Mello while (*sptr != '\0') {
2151*3ee4fc2aSCody Peter Mello (void) adjbuf(&buf, &bufsz,
2152*3ee4fc2aSCody Peter Mello 5 + pb - buf, recsize,
2153*3ee4fc2aSCody Peter Mello &pb, "gsub");
2154*3ee4fc2aSCody Peter Mello if (*sptr == '\\') {
2155*3ee4fc2aSCody Peter Mello backsub(&pb, &sptr);
21567c478bd9Sstevel@tonic-gate } else if (*sptr == '&') {
21577c478bd9Sstevel@tonic-gate sptr++;
2158*3ee4fc2aSCody Peter Mello (void) adjbuf(&buf,
2159*3ee4fc2aSCody Peter Mello &bufsz,
2160*3ee4fc2aSCody Peter Mello 1+patlen+pb-buf,
2161*3ee4fc2aSCody Peter Mello recsize,
2162*3ee4fc2aSCody Peter Mello &pb, "gsub");
2163*3ee4fc2aSCody Peter Mello for (
2164*3ee4fc2aSCody Peter Mello q = patbeg;
2165*3ee4fc2aSCody Peter Mello q < patbeg+patlen;
2166*3ee4fc2aSCody Peter Mello *pb++ = *q++)
2167*3ee4fc2aSCody Peter Mello ;
21681ee2e5faSnakanon } else {
2169*3ee4fc2aSCody Peter Mello *pb++ = *sptr++;
21701ee2e5faSnakanon }
21711ee2e5faSnakanon }
21727c478bd9Sstevel@tonic-gate }
2173*3ee4fc2aSCody Peter Mello if (*t == '\0') /* at end */
21747c478bd9Sstevel@tonic-gate goto done;
2175*3ee4fc2aSCody Peter Mello (void) adjbuf(&buf, &bufsz,
2176*3ee4fc2aSCody Peter Mello 2 + pb - buf, recsize, &pb, "gsub");
2177*3ee4fc2aSCody Peter Mello *pb++ = *t++;
2178*3ee4fc2aSCody Peter Mello /* BUG: not sure of this test */
2179*3ee4fc2aSCody Peter Mello if (pb > buf + bufsz)
2180*3ee4fc2aSCody Peter Mello FATAL("gsub result0 %.30s too big; "
2181*3ee4fc2aSCody Peter Mello "can't happen", buf);
21827c478bd9Sstevel@tonic-gate mflag = 0;
21831ee2e5faSnakanon } else { /* matched nonempty string */
21847c478bd9Sstevel@tonic-gate num++;
21857c478bd9Sstevel@tonic-gate sptr = t;
2186*3ee4fc2aSCody Peter Mello (void) adjbuf(&buf, &bufsz,
2187*3ee4fc2aSCody Peter Mello 1 + (patbeg - sptr) + pb - buf,
2188*3ee4fc2aSCody Peter Mello recsize, &pb, "gsub");
2189*3ee4fc2aSCody Peter Mello while (sptr < patbeg)
2190*3ee4fc2aSCody Peter Mello *pb++ = *sptr++;
21917c478bd9Sstevel@tonic-gate sptr = rptr;
2192*3ee4fc2aSCody Peter Mello while (*sptr != '\0') {
2193*3ee4fc2aSCody Peter Mello (void) adjbuf(&buf, &bufsz,
2194*3ee4fc2aSCody Peter Mello 5 + pb - buf, recsize, &pb, "gsub");
2195*3ee4fc2aSCody Peter Mello if (*sptr == '\\') {
2196*3ee4fc2aSCody Peter Mello backsub(&pb, &sptr);
21977c478bd9Sstevel@tonic-gate } else if (*sptr == '&') {
21987c478bd9Sstevel@tonic-gate sptr++;
2199*3ee4fc2aSCody Peter Mello (void) adjbuf(&buf, &bufsz,
2200*3ee4fc2aSCody Peter Mello 1 + patlen + pb - buf,
2201*3ee4fc2aSCody Peter Mello recsize, &pb, "gsub");
2202*3ee4fc2aSCody Peter Mello for (
2203*3ee4fc2aSCody Peter Mello q = patbeg;
2204*3ee4fc2aSCody Peter Mello q < patbeg+patlen;
2205*3ee4fc2aSCody Peter Mello *pb++ = *q++)
2206*3ee4fc2aSCody Peter Mello ;
22071ee2e5faSnakanon } else {
2208*3ee4fc2aSCody Peter Mello *pb++ = *sptr++;
22091ee2e5faSnakanon }
22101ee2e5faSnakanon }
22117c478bd9Sstevel@tonic-gate t = patbeg + patlen;
2212*3ee4fc2aSCody Peter Mello if (patlen == 0 || *(t-1) == '\0' || *t == '\0')
22137c478bd9Sstevel@tonic-gate goto done;
2214*3ee4fc2aSCody Peter Mello if (pb > buf + bufsz)
2215*3ee4fc2aSCody Peter Mello FATAL("gsub result1 %.30s too big; "
2216*3ee4fc2aSCody Peter Mello "can't happen", buf);
22177c478bd9Sstevel@tonic-gate mflag = 1;
22187c478bd9Sstevel@tonic-gate }
22191ee2e5faSnakanon } while (pmatch(pfa, t));
22207c478bd9Sstevel@tonic-gate sptr = t;
2221*3ee4fc2aSCody Peter Mello (void) adjbuf(&buf, &bufsz,
2222*3ee4fc2aSCody Peter Mello 1 + strlen(sptr) + pb - buf, 0, &pb, "gsub");
2223*3ee4fc2aSCody Peter Mello while ((*pb++ = *sptr++) != '\0')
2224*3ee4fc2aSCody Peter Mello ;
22251ee2e5faSnakanon done:
2226*3ee4fc2aSCody Peter Mello if (pb < buf + bufsz)
2227*3ee4fc2aSCody Peter Mello *pb = '\0';
2228*3ee4fc2aSCody Peter Mello else if (*(pb-1) != '\0')
2229*3ee4fc2aSCody Peter Mello FATAL("gsub result2 %.30s truncated; "
2230*3ee4fc2aSCody Peter Mello "can't happen", buf);
2231*3ee4fc2aSCody Peter Mello /* BUG: should be able to avoid copy + free */
22321ee2e5faSnakanon (void) setsval(x, buf);
22337c478bd9Sstevel@tonic-gate pfa->initstat = tempstat;
22347c478bd9Sstevel@tonic-gate }
2235*3ee4fc2aSCody Peter Mello tempfree(x);
2236*3ee4fc2aSCody Peter Mello tempfree(y);
2237*3ee4fc2aSCody Peter Mello x = gettemp();
22387c478bd9Sstevel@tonic-gate x->tval = NUM;
22397c478bd9Sstevel@tonic-gate x->fval = num;
2240*3ee4fc2aSCody Peter Mello free(buf);
22411ee2e5faSnakanon return (x);
22427c478bd9Sstevel@tonic-gate }
2243*3ee4fc2aSCody Peter Mello
2244*3ee4fc2aSCody Peter Mello /*
2245*3ee4fc2aSCody Peter Mello * handle \\& variations; sptr[0] == '\\'
2246*3ee4fc2aSCody Peter Mello */
2247*3ee4fc2aSCody Peter Mello static void
backsub(char ** pb_ptr,char ** sptr_ptr)2248*3ee4fc2aSCody Peter Mello backsub(char **pb_ptr, char **sptr_ptr)
2249*3ee4fc2aSCody Peter Mello {
2250*3ee4fc2aSCody Peter Mello char *pb = *pb_ptr, *sptr = *sptr_ptr;
2251*3ee4fc2aSCody Peter Mello
2252*3ee4fc2aSCody Peter Mello if (sptr[1] == '\\') {
2253*3ee4fc2aSCody Peter Mello if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
2254*3ee4fc2aSCody Peter Mello *pb++ = '\\';
2255*3ee4fc2aSCody Peter Mello *pb++ = '&';
2256*3ee4fc2aSCody Peter Mello sptr += 4;
2257*3ee4fc2aSCody Peter Mello } else if (sptr[2] == '&') { /* \\& -> \ + matched */
2258*3ee4fc2aSCody Peter Mello *pb++ = '\\';
2259*3ee4fc2aSCody Peter Mello sptr += 2;
2260*3ee4fc2aSCody Peter Mello } else { /* \\x -> \\x */
2261*3ee4fc2aSCody Peter Mello *pb++ = *sptr++;
2262*3ee4fc2aSCody Peter Mello *pb++ = *sptr++;
2263*3ee4fc2aSCody Peter Mello }
2264*3ee4fc2aSCody Peter Mello } else if (sptr[1] == '&') { /* literal & */
2265*3ee4fc2aSCody Peter Mello sptr++;
2266*3ee4fc2aSCody Peter Mello *pb++ = *sptr++;
2267*3ee4fc2aSCody Peter Mello } else /* literal \ */
2268*3ee4fc2aSCody Peter Mello *pb++ = *sptr++;
2269*3ee4fc2aSCody Peter Mello
2270*3ee4fc2aSCody Peter Mello *pb_ptr = pb;
2271*3ee4fc2aSCody Peter Mello *sptr_ptr = sptr;
2272*3ee4fc2aSCody Peter Mello }
2273