1 /*	$OpenBSD: run.c,v 1.34 2013/09/29 15:42:25 deraadt Exp $	*/
2 /****************************************************************
3 Copyright (C) Lucent Technologies 1997
4 All Rights Reserved
5 
6 Permission to use, copy, modify, and distribute this software and
7 its documentation for any purpose and without fee is hereby
8 granted, provided that the above copyright notice appear in all
9 copies and that both that the copyright notice and this
10 permission notice and warranty disclaimer appear in supporting
11 documentation, and that the name Lucent Technologies or any of
12 its entities not be used in advertising or publicity pertaining
13 to distribution of the software without specific, written prior
14 permission.
15 
16 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
18 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
19 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
21 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
22 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
23 THIS SOFTWARE.
24 ****************************************************************/
25 
26 #define DEBUG
27 #include <stdio.h>
28 #include <ctype.h>
29 #include <setjmp.h>
30 #include <limits.h>
31 #include <math.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <time.h>
35 #include "awk.h"
36 #include "awkgram.h"
37 
38 __RCSID("$MirOS: src/usr.bin/awk/run.c,v 1.5 2014/03/23 20:18:27 tg Exp $");
39 
40 #define tempfree(x)	do { if (istemp(x)) tfree(x); } while (/* CONSTCOND */ 0)
41 
42 /*
43 #undef tempfree
44 
45 void tempfree(Cell *p) {
46 	if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) {
47 		WARNING("bad csub %d in Cell %d %s",
48 			p->csub, p->ctype, p->sval);
49 	}
50 	if (istemp(p))
51 		tfree(p);
52 }
53 */
54 
55 /* do we really need these? */
56 /* #ifdef _NFILE */
57 /* #ifndef FOPEN_MAX */
58 /* #define FOPEN_MAX _NFILE */
59 /* #endif */
60 /* #endif */
61 /*  */
62 /* #ifndef	FOPEN_MAX */
63 /* #define	FOPEN_MAX	40 */	/* max number of open files */
64 /* #endif */
65 /*  */
66 /* #ifndef RAND_MAX */
67 /* #define RAND_MAX	32767 */	/* all that ansi guarantees */
68 /* #endif */
69 
70 jmp_buf env;
71 
72 Node	*winner = NULL;	/* root of parse tree */
73 Cell	*tmps;		/* free temporary cells for execution */
74 
75 static Cell	truecell	={ OBOOL, BTRUE, 0, 0, 1.0, NUM, NULL };
76 Cell	*True	= &truecell;
77 static Cell	falsecell	={ OBOOL, BFALSE, 0, 0, 0.0, NUM, NULL };
78 Cell	*False	= &falsecell;
79 static Cell	breakcell	={ OJUMP, JBREAK, 0, 0, 0.0, NUM, NULL };
80 Cell	*jbreak	= &breakcell;
81 static Cell	contcell	={ OJUMP, JCONT, 0, 0, 0.0, NUM, NULL };
82 Cell	*jcont	= &contcell;
83 static Cell	nextcell	={ OJUMP, JNEXT, 0, 0, 0.0, NUM, NULL };
84 Cell	*jnext	= &nextcell;
85 static Cell	nextfilecell	={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM, NULL };
86 Cell	*jnextfile	= &nextfilecell;
87 static Cell	exitcell	={ OJUMP, JEXIT, 0, 0, 0.0, NUM, NULL };
88 Cell	*jexit	= &exitcell;
89 static Cell	retcell		={ OJUMP, JRET, 0, 0, 0.0, NUM, NULL };
90 Cell	*jret	= &retcell;
91 static char tempcell_i[] = "";
92 static Cell	tempcell	={ OCELL, CTEMP, 0, tempcell_i, 0.0, NUM|STR|DONTFREE, NULL };
93 
94 Node	*curnode = NULL;	/* the node being executed, for debugging */
95 
96 void	stdinit(void);
97 void	flush_all(void);
98 
99 /* buffer memory management */
adjbuf(char ** pbuf,int * psiz,int minlen,int quantum,char ** pbptr,const char * whatrtn)100 int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,
101 	const char *whatrtn)
102 /* pbuf:    address of pointer to buffer being managed
103  * psiz:    address of buffer size variable
104  * minlen:  minimum length of buffer needed
105  * quantum: buffer size quantum
106  * pbptr:   address of movable pointer into buffer, or 0 if none
107  * whatrtn: name of the calling routine if failure should cause fatal error
108  *
109  * return   0 for realloc failure, !=0 for success
110  */
111 {
112 	if (minlen > *psiz) {
113 		char *tbuf;
114 		int rminlen = quantum ? minlen % quantum : 0;
115 		int boff = pbptr ? *pbptr - *pbuf : 0;
116 		/* round up to next multiple of quantum */
117 		if (rminlen)
118 			minlen += quantum - rminlen;
119 		tbuf = (char *) realloc(*pbuf, minlen);
120 		dprintf( ("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, *pbuf, tbuf) );
121 		if (tbuf == NULL) {
122 			if (whatrtn)
123 				FATAL("out of memory in %s", whatrtn);
124 			return 0;
125 		}
126 		*pbuf = tbuf;
127 		*psiz = minlen;
128 		if (pbptr)
129 			*pbptr = tbuf + boff;
130 	}
131 	return 1;
132 }
133 
run(Node * a)134 void run(Node *a)	/* execution of parse tree starts here */
135 {
136 	stdinit();
137 	execute(a);
138 	closeall();
139 }
140 
execute(Node * u)141 Cell *execute(Node *u)	/* execute a node of the parse tree */
142 {
143 	Cell *(*proc)(Node **, int);
144 	Cell *x;
145 	Node *a;
146 
147 	if (u == NULL)
148 		return(True);
149 	for (a = u; ; a = a->nnext) {
150 		curnode = a;
151 		if (isvalue(a)) {
152 			x = (Cell *) (a->narg[0]);
153 			if (isfld(x) && !donefld)
154 				fldbld();
155 			else if (isrec(x) && !donerec)
156 				recbld();
157 			return(x);
158 		}
159 		if (notlegal(a->nobj))	/* probably a Cell* but too risky to print */
160 			FATAL("illegal statement");
161 		proc = proctab[a->nobj-FIRSTTOKEN];
162 		x = (*proc)(a->narg, a->nobj);
163 		if (isfld(x) && !donefld)
164 			fldbld();
165 		else if (isrec(x) && !donerec)
166 			recbld();
167 		if (isexpr(a))
168 			return(x);
169 		if (isjump(x))
170 			return(x);
171 		if (a->nnext == NULL)
172 			return(x);
173 		tempfree(x);
174 	}
175 }
176 
177 
program(Node ** a,int n)178 Cell *program(Node **a, int n)	/* execute an awk program */
179 {				/* a[0] = BEGIN, a[1] = body, a[2] = END */
180 	Cell *x;
181 
182 	if (setjmp(env) != 0)
183 		goto ex;
184 	if (a[0]) {		/* BEGIN */
185 		x = execute(a[0]);
186 		if (isexit(x))
187 			return(True);
188 		if (isjump(x))
189 			FATAL("illegal break, continue, next or nextfile from BEGIN");
190 		tempfree(x);
191 	}
192 	if (a[1] || a[2])
193 		while (getrec(&record, &recsize, 1) > 0) {
194 			x = execute(a[1]);
195 			if (isexit(x))
196 				break;
197 			tempfree(x);
198 		}
199   ex:
200 	if (setjmp(env) != 0)	/* handles exit within END */
201 		goto ex1;
202 	if (a[2]) {		/* END */
203 		x = execute(a[2]);
204 		if (isbreak(x) || isnext(x) || iscont(x))
205 			FATAL("illegal break, continue, next or nextfile from END");
206 		tempfree(x);
207 	}
208   ex1:
209 	return(True);
210 }
211 
212 struct Frame {	/* stack frame for awk function calls */
213 	int nargs;	/* number of arguments in this call */
214 	Cell *fcncell;	/* pointer to Cell for function */
215 	Cell **args;	/* pointer to array of arguments after execute */
216 	Cell *retval;	/* return value */
217 };
218 
219 #define	NARGS	50	/* max args in a call */
220 
221 struct Frame *frame = NULL;	/* base of stack frames; dynamically allocated */
222 int	nframe = 0;		/* number of frames allocated */
223 #define fp fptr
224 struct Frame *fp = NULL;	/* frame pointer. bottom level unused */
225 
call(Node ** a,int n)226 Cell *call(Node **a, int n)	/* function call.  very kludgy and fragile */
227 {
228 	static char newcopycell_i[] = "";
229 	static Cell newcopycell = { OCELL, CCOPY, 0, newcopycell_i, 0.0, NUM|STR|DONTFREE, NULL };
230 	int i, ncall, ndef;
231 	int freed = 0; /* handles potential double freeing when fcn & param share a tempcell */
232 	Node *x;
233 	Cell *args[NARGS], *oargs[NARGS];	/* BUG: fixed size arrays */
234 	Cell *y, *z, *fcn;
235 	char *s;
236 
237 	fcn = execute(a[0]);	/* the function itself */
238 	s = fcn->nval;
239 	if (!isfcn(fcn))
240 		FATAL("calling undefined function %s", s);
241 	if (frame == NULL) {
242 		fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
243 		if (frame == NULL)
244 			FATAL("out of space for stack frames calling %s", s);
245 	}
246 	for (ncall = 0, x = a[1]; x != NULL; x = x->nnext)	/* args in call */
247 		ncall++;
248 	ndef = (int) fcn->fval;			/* args in defn */
249 	   dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) );
250 	if (ncall > ndef)
251 		WARNING("function %s called with %d args, uses only %d",
252 			s, ncall, ndef);
253 	if (ncall + ndef > NARGS)
254 		FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS);
255 	for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) {	/* get call args */
256 		   dprintf( ("evaluate args[%d], fp=%d:\n", i, (int) (fp-frame)) );
257 		y = execute(x);
258 		oargs[i] = y;
259 		   dprintf( ("args[%d]: %s %f <%s>, t=%o\n",
260 			   i, NN(y->nval), y->fval, isarr(y) ? "(array)" : NN(y->sval), y->tval) );
261 		if (isfcn(y))
262 			FATAL("can't use function %s as argument in %s", y->nval, s);
263 		if (isarr(y))
264 			args[i] = y;	/* arrays by ref */
265 		else
266 			args[i] = copycell(y);
267 		tempfree(y);
268 	}
269 	for ( ; i < ndef; i++) {	/* add null args for ones not provided */
270 		args[i] = gettemp();
271 		*args[i] = newcopycell;
272 	}
273 	fp++;	/* now ok to up frame */
274 	if (fp >= frame + nframe) {
275 		int dfp = fp - frame;	/* old index */
276 		frame = (struct Frame *)
277 			realloc((char *) frame, (nframe += 100) * sizeof(struct Frame));
278 		if (frame == NULL)
279 			FATAL("out of space for stack frames in %s", s);
280 		fp = frame + dfp;
281 	}
282 	fp->fcncell = fcn;
283 	fp->args = args;
284 	fp->nargs = ndef;	/* number defined with (excess are locals) */
285 	fp->retval = gettemp();
286 
287 	   dprintf( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) );
288 	y = execute((Node *)(fcn->sval));	/* execute body */
289 	   dprintf( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) );
290 
291 	for (i = 0; i < ndef; i++) {
292 		Cell *t = fp->args[i];
293 		if (isarr(t)) {
294 			if (t->csub == CCOPY) {
295 				if (i >= ncall) {
296 					freesymtab(t);
297 					t->csub = CTEMP;
298 					tempfree(t);
299 				} else {
300 					oargs[i]->tval = t->tval;
301 					oargs[i]->tval &= ~(STR|NUM|DONTFREE);
302 					oargs[i]->sval = t->sval;
303 					tempfree(t);
304 				}
305 			}
306 		} else if (t != y) {	/* kludge to prevent freeing twice */
307 			t->csub = CTEMP;
308 			tempfree(t);
309 		} else if (t == y && t->csub == CCOPY) {
310 			t->csub = CTEMP;
311 			tempfree(t);
312 			freed = 1;
313 		}
314 	}
315 	tempfree(fcn);
316 	if (isexit(y) || isnext(y))
317 		return y;
318 	if (freed == 0) {
319 		tempfree(y);	/* don't free twice! */
320 	}
321 	z = fp->retval;			/* return value */
322 	   dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );
323 	fp--;
324 	return(z);
325 }
326 
copycell(Cell * x)327 Cell *copycell(Cell *x)	/* make a copy of a cell in a temp */
328 {
329 	Cell *y;
330 
331 	y = gettemp();
332 	y->csub = CCOPY;	/* prevents freeing until call is over */
333 	y->nval = x->nval;	/* BUG? */
334 	if (isstr(x))
335 		y->sval = tostring(x->sval);
336 	y->fval = x->fval;
337 	y->tval = x->tval & ~(CON|FLD|REC|DONTFREE);	/* copy is not constant or field */
338 							/* is DONTFREE right? */
339 	return y;
340 }
341 
arg(Node ** a,int n)342 Cell *arg(Node **a, int n)	/* nth argument of a function */
343 {
344 
345 	n = ptoi(a[0]);	/* argument number, counting from 0 */
346 	   dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );
347 	if (n+1 > fp->nargs)
348 		FATAL("argument #%d of function %s was not supplied",
349 			n+1, fp->fcncell->nval);
350 	return fp->args[n];
351 }
352 
jump(Node ** a,int n)353 Cell *jump(Node **a, int n)	/* break, continue, next, nextfile, return */
354 {
355 	Cell *y;
356 
357 	switch (n) {
358 	case EXIT:
359 		if (a[0] != NULL) {
360 			y = execute(a[0]);
361 			errorflag = (int) getfval(y);
362 			tempfree(y);
363 		}
364 		longjmp(env, 1);
365 	case RETURN:
366 		if (a[0] != NULL) {
367 			y = execute(a[0]);
368 			if ((y->tval & (STR|NUM)) == (STR|NUM)) {
369 				setsval(fp->retval, getsval(y));
370 				fp->retval->fval = getfval(y);
371 				fp->retval->tval |= NUM;
372 			}
373 			else if (y->tval & STR)
374 				setsval(fp->retval, getsval(y));
375 			else if (y->tval & NUM)
376 				setfval(fp->retval, getfval(y));
377 			else		/* can't happen */
378 				FATAL("bad type variable %d", y->tval);
379 			tempfree(y);
380 		}
381 		return(jret);
382 	case NEXT:
383 		return(jnext);
384 	case NEXTFILE:
385 		nextfile();
386 		return(jnextfile);
387 	case BREAK:
388 		return(jbreak);
389 	case CONTINUE:
390 		return(jcont);
391 	default:	/* can't happen */
392 		FATAL("illegal jump type %d", n);
393 	}
394 	return 0;	/* not reached */
395 }
396 #undef fp
397 
awkgetline(Node ** a,int n)398 Cell *awkgetline(Node **a, int n)	/* get next line from specific input */
399 {		/* a[0] is variable, a[1] is operator, a[2] is filename */
400 	Cell *r, *x;
401 	extern Cell **fldtab;
402 	FILE *fp;
403 	char *buf;
404 	int bufsize = recsize;
405 	int mode;
406 
407 	if ((buf = (char *) malloc(bufsize)) == NULL)
408 		FATAL("out of memory in getline");
409 
410 	fflush(stdout);	/* in case someone is waiting for a prompt */
411 	r = gettemp();
412 	if (a[1] != NULL) {		/* getline < file */
413 		x = execute(a[2]);		/* filename */
414 		mode = ptoi(a[1]);
415 		if (mode == '|')		/* input pipe */
416 			mode = LE;	/* arbitrary flag */
417 		fp = openfile(mode, getsval(x));
418 		tempfree(x);
419 		if (fp == NULL)
420 			n = -1;
421 		else
422 			n = readrec(&buf, &bufsize, fp);
423 		if (n <= 0) {
424 			;
425 		} else if (a[0] != NULL) {	/* getline var <file */
426 			x = execute(a[0]);
427 			setsval(x, buf);
428 			tempfree(x);
429 		} else {			/* getline <file */
430 			setsval(fldtab[0], buf);
431 			if (is_number(fldtab[0]->sval)) {
432 				fldtab[0]->fval = atof(fldtab[0]->sval);
433 				fldtab[0]->tval |= NUM;
434 			}
435 		}
436 	} else {			/* bare getline; use current input */
437 		if (a[0] == NULL)	/* getline */
438 			n = getrec(&record, &recsize, 1);
439 		else {			/* getline var */
440 			n = getrec(&buf, &bufsize, 0);
441 			x = execute(a[0]);
442 			setsval(x, buf);
443 			tempfree(x);
444 		}
445 	}
446 	setfval(r, (Awkfloat) n);
447 	free(buf);
448 	return r;
449 }
450 
getnf(Node ** a,int n)451 Cell *getnf(Node **a, int n)	/* get NF */
452 {
453 	if (donefld == 0)
454 		fldbld();
455 	return (Cell *) a[0];
456 }
457 
array(Node ** a,int n)458 Cell *array(Node **a, int n)	/* a[0] is symtab, a[1] is list of subscripts */
459 {
460 	Cell *x, *y, *z;
461 	char *s;
462 	Node *np;
463 	char *buf;
464 	int bufsz = recsize;
465 	int nsub = strlen(*SUBSEP);
466 
467 	if ((buf = (char *) malloc(bufsz)) == NULL)
468 		FATAL("out of memory in array");
469 
470 	x = execute(a[0]);	/* Cell* for symbol table */
471 	buf[0] = 0;
472 	for (np = a[1]; np; np = np->nnext) {
473 		y = execute(np);	/* subscript */
474 		s = getsval(y);
475 		if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "array"))
476 			FATAL("out of memory for %s[%s...]", x->nval, buf);
477 		strlcat(buf, s, bufsz);
478 		if (np->nnext)
479 			strlcat(buf, *SUBSEP, bufsz);
480 		tempfree(y);
481 	}
482 	if (!isarr(x)) {
483 		   dprintf( ("making %s into an array\n", NN(x->nval)) );
484 		if (freeable(x))
485 			xfree(x->sval);
486 		x->tval &= ~(STR|NUM|DONTFREE);
487 		x->tval |= ARR;
488 		x->sval = (char *) makesymtab(NSYMTAB);
489 	}
490 	z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
491 	z->ctype = OCELL;
492 	z->csub = CVAR;
493 	tempfree(x);
494 	free(buf);
495 	return(z);
496 }
497 
awkdelete(Node ** a,int n)498 Cell *awkdelete(Node **a, int n)	/* a[0] is symtab, a[1] is list of subscripts */
499 {
500 	Cell *x, *y;
501 	Node *np;
502 	char *s;
503 	int nsub = strlen(*SUBSEP);
504 
505 	x = execute(a[0]);	/* Cell* for symbol table */
506 	if (!isarr(x))
507 		return True;
508 	if (a[1] == 0) {	/* delete the elements, not the table */
509 		freesymtab(x);
510 		x->tval &= ~STR;
511 		x->tval |= ARR;
512 		x->sval = (char *) makesymtab(NSYMTAB);
513 	} else {
514 		int bufsz = recsize;
515 		char *buf;
516 		if ((buf = (char *) malloc(bufsz)) == NULL)
517 			FATAL("out of memory in adelete");
518 		buf[0] = 0;
519 		for (np = a[1]; np; np = np->nnext) {
520 			y = execute(np);	/* subscript */
521 			s = getsval(y);
522 			if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "awkdelete"))
523 				FATAL("out of memory deleting %s[%s...]", x->nval, buf);
524 			strlcat(buf, s, bufsz);
525 			if (np->nnext)
526 				strlcat(buf, *SUBSEP, bufsz);
527 			tempfree(y);
528 		}
529 		freeelem(x, buf);
530 		free(buf);
531 	}
532 	tempfree(x);
533 	return True;
534 }
535 
intest(Node ** a,int n)536 Cell *intest(Node **a, int n)	/* a[0] is index (list), a[1] is symtab */
537 {
538 	Cell *x, *ap, *k;
539 	Node *p;
540 	char *buf;
541 	char *s;
542 	int bufsz = recsize;
543 	int nsub = strlen(*SUBSEP);
544 
545 	ap = execute(a[1]);	/* array name */
546 	if (!isarr(ap)) {
547 		   dprintf( ("making %s into an array\n", ap->nval) );
548 		if (freeable(ap))
549 			xfree(ap->sval);
550 		ap->tval &= ~(STR|NUM|DONTFREE);
551 		ap->tval |= ARR;
552 		ap->sval = (char *) makesymtab(NSYMTAB);
553 	}
554 	if ((buf = (char *) malloc(bufsz)) == NULL) {
555 		FATAL("out of memory in intest");
556 	}
557 	buf[0] = 0;
558 	for (p = a[0]; p; p = p->nnext) {
559 		x = execute(p);	/* expr */
560 		s = getsval(x);
561 		if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "intest"))
562 			FATAL("out of memory deleting %s[%s...]", x->nval, buf);
563 		strlcat(buf, s, bufsz);
564 		tempfree(x);
565 		if (p->nnext)
566 			strlcat(buf, *SUBSEP, bufsz);
567 	}
568 	k = lookup(buf, (Array *) ap->sval);
569 	tempfree(ap);
570 	free(buf);
571 	if (k == NULL)
572 		return(False);
573 	else
574 		return(True);
575 }
576 
577 
matchop(Node ** a,int n)578 Cell *matchop(Node **a, int n)	/* ~ and match() */
579 {
580 	Cell *x, *y;
581 	char *s, *t;
582 	int i;
583 	fa *pfa;
584 	int (*mf)(fa *, const char *) = match, mode = 0;
585 
586 	if (n == MATCHFCN) {
587 		mf = pmatch;
588 		mode = 1;
589 	}
590 	x = execute(a[1]);	/* a[1] = target text */
591 	s = getsval(x);
592 	if (a[0] == 0)		/* a[1] == 0: already-compiled reg expr */
593 		i = (*mf)((fa *) a[2], s);
594 	else {
595 		y = execute(a[2]);	/* a[2] = regular expr */
596 		t = getsval(y);
597 		pfa = makedfa(t, mode);
598 		i = (*mf)(pfa, s);
599 		tempfree(y);
600 	}
601 	tempfree(x);
602 	if (n == MATCHFCN) {
603 		int start = patbeg - s + 1;
604 		if (patlen < 0)
605 			start = 0;
606 		setfval(rstartloc, (Awkfloat) start);
607 		setfval(rlengthloc, (Awkfloat) patlen);
608 		x = gettemp();
609 		x->tval = NUM;
610 		x->fval = start;
611 		return x;
612 	} else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
613 		return(True);
614 	else
615 		return(False);
616 }
617 
618 
boolop(Node ** a,int n)619 Cell *boolop(Node **a, int n)	/* a[0] || a[1], a[0] && a[1], !a[0] */
620 {
621 	Cell *x, *y;
622 	int i;
623 
624 	x = execute(a[0]);
625 	i = istrue(x);
626 	tempfree(x);
627 	switch (n) {
628 	case BOR:
629 		if (i) return(True);
630 		y = execute(a[1]);
631 		i = istrue(y);
632 		tempfree(y);
633 		if (i) return(True);
634 		else return(False);
635 	case AND:
636 		if ( !i ) return(False);
637 		y = execute(a[1]);
638 		i = istrue(y);
639 		tempfree(y);
640 		if (i) return(True);
641 		else return(False);
642 	case NOT:
643 		if (i) return(False);
644 		else return(True);
645 	default:	/* can't happen */
646 		FATAL("unknown boolean operator %d", n);
647 	}
648 	return 0;	/*NOTREACHED*/
649 }
650 
relop(Node ** a,int n)651 Cell *relop(Node **a, int n)	/* a[0 < a[1], etc. */
652 {
653 	int i;
654 	Cell *x, *y;
655 	Awkfloat j;
656 
657 	x = execute(a[0]);
658 	y = execute(a[1]);
659 	if (x->tval&NUM && y->tval&NUM) {
660 		j = x->fval - y->fval;
661 		i = j<0? -1: (j>0? 1: 0);
662 	} else {
663 		i = strcmp(getsval(x), getsval(y));
664 	}
665 	tempfree(x);
666 	tempfree(y);
667 	switch (n) {
668 	case LT:	if (i<0) return(True);
669 			else return(False);
670 	case LE:	if (i<=0) return(True);
671 			else return(False);
672 	case NE:	if (i!=0) return(True);
673 			else return(False);
674 	case EQ:	if (i == 0) return(True);
675 			else return(False);
676 	case GE:	if (i>=0) return(True);
677 			else return(False);
678 	case GT:	if (i>0) return(True);
679 			else return(False);
680 	default:	/* can't happen */
681 		FATAL("unknown relational operator %d", n);
682 	}
683 	return 0;	/*NOTREACHED*/
684 }
685 
tfree(Cell * a)686 void tfree(Cell *a)	/* free a tempcell */
687 {
688 	if (freeable(a)) {
689 		   dprintf( ("freeing %s %s %o\n", NN(a->nval), NN(a->sval), a->tval) );
690 		xfree(a->sval);
691 	}
692 	if (a == tmps)
693 		FATAL("tempcell list is curdled");
694 	a->cnext = tmps;
695 	tmps = a;
696 }
697 
gettemp(void)698 Cell *gettemp(void)	/* get a tempcell */
699 {	int i;
700 	Cell *x;
701 
702 	if (!tmps) {
703 		tmps = (Cell *) calloc(100, sizeof(Cell));
704 		if (!tmps)
705 			FATAL("out of space for temporaries");
706 		for(i = 1; i < 100; i++)
707 			tmps[i-1].cnext = &tmps[i];
708 		tmps[i-1].cnext = 0;
709 	}
710 	x = tmps;
711 	tmps = x->cnext;
712 	*x = tempcell;
713 	return(x);
714 }
715 
indirect(Node ** a,int n)716 Cell *indirect(Node **a, int n)	/* $( a[0] ) */
717 {
718 	Awkfloat val;
719 	Cell *x;
720 	int m;
721 	char *s;
722 
723 	x = execute(a[0]);
724 	val = getfval(x);	/* freebsd: defend against super large field numbers */
725 	if ((Awkfloat)INT_MAX < val)
726 		FATAL("trying to access out of range field %s", x->nval);
727 	m = (int) val;
728 	if (m == 0 && !is_number(s = getsval(x)))	/* suspicion! */
729 		FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
730 		/* BUG: can x->nval ever be null??? */
731 	tempfree(x);
732 	x = fieldadr(m);
733 	x->ctype = OCELL;	/* BUG?  why are these needed? */
734 	x->csub = CFLD;
735 	return(x);
736 }
737 
substr(Node ** a,int nnn)738 Cell *substr(Node **a, int nnn)		/* substr(a[0], a[1], a[2]) */
739 {
740 	int k, m, n;
741 	char *s;
742 	int temp;
743 	Cell *x, *y, *z = 0;
744 
745 	x = execute(a[0]);
746 	y = execute(a[1]);
747 	if (a[2] != 0)
748 		z = execute(a[2]);
749 	s = getsval(x);
750 	k = strlen(s) + 1;
751 	if (k <= 1) {
752 		tempfree(x);
753 		tempfree(y);
754 		if (a[2] != 0) {
755 			tempfree(z);
756 		}
757 		x = gettemp();
758 		setsval(x, "");
759 		return(x);
760 	}
761 	m = (int) getfval(y);
762 	if (m <= 0)
763 		m = 1;
764 	else if (m > k)
765 		m = k;
766 	tempfree(y);
767 	if (a[2] != 0) {
768 		n = (int) getfval(z);
769 		tempfree(z);
770 	} else
771 		n = k - 1;
772 	if (n < 0)
773 		n = 0;
774 	else if (n > k - m)
775 		n = k - m;
776 	   dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) );
777 	y = gettemp();
778 	temp = s[n+m-1];	/* with thanks to John Linderman */
779 	s[n+m-1] = '\0';
780 	setsval(y, s + m - 1);
781 	s[n+m-1] = temp;
782 	tempfree(x);
783 	return(y);
784 }
785 
sindex(Node ** a,int nnn)786 Cell *sindex(Node **a, int nnn)		/* index(a[0], a[1]) */
787 {
788 	Cell *x, *y, *z;
789 	char *s1, *s2, *p1, *p2, *q;
790 	Awkfloat v = 0.0;
791 
792 	x = execute(a[0]);
793 	s1 = getsval(x);
794 	y = execute(a[1]);
795 	s2 = getsval(y);
796 
797 	z = gettemp();
798 	for (p1 = s1; *p1 != '\0'; p1++) {
799 		for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
800 			;
801 		if (*p2 == '\0') {
802 			v = (Awkfloat) (p1 - s1 + 1);	/* origin 1 */
803 			break;
804 		}
805 	}
806 	tempfree(x);
807 	tempfree(y);
808 	setfval(z, v);
809 	return(z);
810 }
811 
812 #define	MAXNUMSIZE	50
813 
format(char ** pbuf,int * pbufsize,const char * s,Node * a)814 int format(char **pbuf, int *pbufsize, const char *s, Node *a)	/* printf-like conversions */
815 {
816 	char *fmt;
817 	char *p, *t;
818 	const char *os;
819 	Cell *x;
820 	int flag = 0, n;
821 	int fmtwd; /* format width */
822 	int fmtsz = recsize;
823 	char *buf = *pbuf;
824 	int bufsize = *pbufsize;
825 
826 	os = s;
827 	p = buf;
828 	if ((fmt = (char *) malloc(fmtsz)) == NULL)
829 		FATAL("out of memory in format()");
830 	while (*s) {
831 		adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format1");
832 		if (*s != '%') {
833 			*p++ = *s++;
834 			continue;
835 		}
836 		if (*(s+1) == '%') {
837 			*p++ = '%';
838 			s += 2;
839 			continue;
840 		}
841 		/* have to be real careful in case this is a huge number, eg, %100000d */
842 		fmtwd = atoi(s+1);
843 		if (fmtwd < 0)
844 			fmtwd = -fmtwd;
845 		adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format2");
846 		for (t = fmt; (*t++ = *s) != '\0'; s++) {
847 			if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3"))
848 				FATAL("format item %.30s... ran format() out of memory", os);
849 			if (isalpha((uschar)*s) && *s != 'l' && *s != 'h' && *s != 'L')
850 				break;	/* the ansi panoply */
851 			if (*s == '*') {
852 				if (a == NULL)
853 					FATAL("not enough args in printf(%s)", os);
854 				x = execute(a);
855 				a = a->nnext;
856 				snprintf(t-1, fmt + fmtsz - (t-1), "%d", fmtwd=(int) getfval(x));
857 				if (fmtwd < 0)
858 					fmtwd = -fmtwd;
859 				adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
860 				t = fmt + strlen(fmt);
861 				tempfree(x);
862 			}
863 		}
864 		*t = '\0';
865 		if (fmtwd < 0)
866 			fmtwd = -fmtwd;
867 		adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format4");
868 
869 		switch (*s) {
870 		case 'f': case 'e': case 'g': case 'E': case 'G':
871 			flag = 'f';
872 			break;
873 		case 'd': case 'i':
874 			flag = 'd';
875 			if(*(s-1) == 'l') break;
876 			*(t-1) = 'l';
877 			*t = 'd';
878 			*++t = '\0';
879 			break;
880 		case 'o': case 'x': case 'X': case 'u':
881 			flag = *(s-1) == 'l' ? 'd' : 'u';
882 			break;
883 		case 's':
884 			flag = 's';
885 			break;
886 		case 'c':
887 			flag = 'c';
888 			break;
889 		default:
890 			WARNING("weird printf conversion %s", fmt);
891 			flag = '?';
892 			break;
893 		}
894 		if (a == NULL)
895 			FATAL("not enough args in printf(%s)", os);
896 		x = execute(a);
897 		a = a->nnext;
898 		n = MAXNUMSIZE;
899 		if (fmtwd > n)
900 			n = fmtwd;
901 		adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format5");
902 		switch (flag) {
903 		case '?':	/* unknown, so dump it too */
904 			snprintf(p, buf + bufsize - p, "%s", fmt);
905 			t = getsval(x);
906 			n = strlen(t);
907 			if (fmtwd > n)
908 				n = fmtwd;
909 			adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format6");
910 			p += strlen(p);
911 			snprintf(p, buf + bufsize - p, "%s", t);
912 			break;
913 		case 'f':	snprintf(p, buf + bufsize - p, fmt, getfval(x)); break;
914 		case 'd':	snprintf(p, buf + bufsize - p, fmt, (long) getfval(x)); break;
915 		case 'u':	snprintf(p, buf + bufsize - p, fmt, (int) getfval(x)); break;
916 		case 's':
917 			t = getsval(x);
918 			n = strlen(t);
919 			if (fmtwd > n)
920 				n = fmtwd;
921 			if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format7"))
922 				FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t);
923 			snprintf(p, buf + bufsize - p, fmt, t);
924 			break;
925 		case 'c':
926 			if (isnum(x)) {
927 				if (getfval(x))
928 					snprintf(p, buf + bufsize - p, fmt, (int) getfval(x));
929 				else {
930 					*p++ = '\0'; /* explicit null byte */
931 					*p = '\0';   /* next output will start here */
932 				}
933 			} else
934 				snprintf(p, buf + bufsize - p, fmt, getsval(x)[0]);
935 			break;
936 		default:
937 			FATAL("can't happen: bad conversion %c in format()", flag);
938 		}
939 		tempfree(x);
940 		p += strlen(p);
941 		s++;
942 	}
943 	*p = '\0';
944 	free(fmt);
945 	for ( ; a; a = a->nnext)		/* evaluate any remaining args */
946 		execute(a);
947 	*pbuf = buf;
948 	*pbufsize = bufsize;
949 	return p - buf;
950 }
951 
awksprintf(Node ** a,int n)952 Cell *awksprintf(Node **a, int n)		/* sprintf(a[0]) */
953 {
954 	Cell *x;
955 	Node *y;
956 	char *buf;
957 	int bufsz=3*recsize;
958 
959 	if ((buf = (char *) malloc(bufsz)) == NULL)
960 		FATAL("out of memory in awksprintf");
961 	y = a[0]->nnext;
962 	x = execute(a[0]);
963 	if (format(&buf, &bufsz, getsval(x), y) == -1)
964 		FATAL("sprintf string %.30s... too long.  can't happen.", buf);
965 	tempfree(x);
966 	x = gettemp();
967 	x->sval = buf;
968 	x->tval = STR;
969 	return(x);
970 }
971 
awkprintf(Node ** a,int n)972 Cell *awkprintf(Node **a, int n)		/* printf */
973 {	/* a[0] is list of args, starting with format string */
974 	/* a[1] is redirection operator, a[2] is redirection file */
975 	FILE *fp;
976 	Cell *x;
977 	Node *y;
978 	char *buf;
979 	int len;
980 	int bufsz=3*recsize;
981 
982 	if ((buf = (char *) malloc(bufsz)) == NULL)
983 		FATAL("out of memory in awkprintf");
984 	y = a[0]->nnext;
985 	x = execute(a[0]);
986 	if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
987 		FATAL("printf string %.30s... too long.  can't happen.", buf);
988 	tempfree(x);
989 	if (a[1] == NULL) {
990 		/* fputs(buf, stdout); */
991 		fwrite(buf, len, 1, stdout);
992 		if (ferror(stdout))
993 			FATAL("write error on stdout");
994 	} else {
995 		fp = redirect(ptoi(a[1]), a[2]);
996 		/* fputs(buf, fp); */
997 		fwrite(buf, len, 1, fp);
998 		fflush(fp);
999 		if (ferror(fp))
1000 			FATAL("write error on %s", filename(fp));
1001 	}
1002 	free(buf);
1003 	return(True);
1004 }
1005 
arith(Node ** a,int n)1006 Cell *arith(Node **a, int n)	/* a[0] + a[1], etc.  also -a[0] */
1007 {
1008 	Awkfloat i, j = 0;
1009 	double v;
1010 	Cell *x, *y, *z;
1011 
1012 	x = execute(a[0]);
1013 	i = getfval(x);
1014 	tempfree(x);
1015 	if (n != UMINUS) {
1016 		y = execute(a[1]);
1017 		j = getfval(y);
1018 		tempfree(y);
1019 	}
1020 	z = gettemp();
1021 	switch (n) {
1022 	case ADD:
1023 		i += j;
1024 		break;
1025 	case MINUS:
1026 		i -= j;
1027 		break;
1028 	case MULT:
1029 		i *= j;
1030 		break;
1031 	case DIVIDE:
1032 		if (j == 0)
1033 			FATAL("division by zero");
1034 		i /= j;
1035 		break;
1036 	case MOD:
1037 		if (j == 0)
1038 			FATAL("division by zero in mod");
1039 		modf(i/j, &v);
1040 		i = i - j * v;
1041 		break;
1042 	case UMINUS:
1043 		i = -i;
1044 		break;
1045 	case POWER:
1046 		if (j >= 0 && modf(j, &v) == 0.0)	/* pos integer exponent */
1047 			i = ipow(i, (int) j);
1048 		else
1049 			i = errcheck(pow(i, j), "pow");
1050 		break;
1051 	default:	/* can't happen */
1052 		FATAL("illegal arithmetic operator %d", n);
1053 	}
1054 	setfval(z, i);
1055 	return(z);
1056 }
1057 
ipow(double x,int n)1058 double ipow(double x, int n)	/* x**n.  ought to be done by pow, but isn't always */
1059 {
1060 	double v;
1061 
1062 	if (n <= 0)
1063 		return 1;
1064 	v = ipow(x, n/2);
1065 	if (n % 2 == 0)
1066 		return v * v;
1067 	else
1068 		return x * v * v;
1069 }
1070 
incrdecr(Node ** a,int n)1071 Cell *incrdecr(Node **a, int n)		/* a[0]++, etc. */
1072 {
1073 	Cell *x, *z;
1074 	int k;
1075 	Awkfloat xf;
1076 
1077 	x = execute(a[0]);
1078 	xf = getfval(x);
1079 	k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
1080 	if (n == PREINCR || n == PREDECR) {
1081 		setfval(x, xf + k);
1082 		return(x);
1083 	}
1084 	z = gettemp();
1085 	setfval(z, xf);
1086 	setfval(x, xf + k);
1087 	tempfree(x);
1088 	return(z);
1089 }
1090 
assign(Node ** a,int n)1091 Cell *assign(Node **a, int n)	/* a[0] = a[1], a[0] += a[1], etc. */
1092 {		/* this is subtle; don't muck with it. */
1093 	Cell *x, *y;
1094 	Awkfloat xf, yf;
1095 	double v;
1096 
1097 	y = execute(a[1]);
1098 	x = execute(a[0]);
1099 	if (n == ASSIGN) {	/* ordinary assignment */
1100 		if (x == y && !(x->tval & (FLD|REC)))	/* self-assignment: */
1101 			;		/* leave alone unless it's a field */
1102 		else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
1103 			setsval(x, getsval(y));
1104 			x->fval = getfval(y);
1105 			x->tval |= NUM;
1106 		}
1107 		else if (isstr(y))
1108 			setsval(x, getsval(y));
1109 		else if (isnum(y))
1110 			setfval(x, getfval(y));
1111 		else
1112 			funnyvar(y, "read value of");
1113 		tempfree(y);
1114 		return(x);
1115 	}
1116 	xf = getfval(x);
1117 	yf = getfval(y);
1118 	switch (n) {
1119 	case ADDEQ:
1120 		xf += yf;
1121 		break;
1122 	case SUBEQ:
1123 		xf -= yf;
1124 		break;
1125 	case MULTEQ:
1126 		xf *= yf;
1127 		break;
1128 	case DIVEQ:
1129 		if (yf == 0)
1130 			FATAL("division by zero in /=");
1131 		xf /= yf;
1132 		break;
1133 	case MODEQ:
1134 		if (yf == 0)
1135 			FATAL("division by zero in %%=");
1136 		modf(xf/yf, &v);
1137 		xf = xf - yf * v;
1138 		break;
1139 	case POWEQ:
1140 		if (yf >= 0 && modf(yf, &v) == 0.0)	/* pos integer exponent */
1141 			xf = ipow(xf, (int) yf);
1142 		else
1143 			xf = errcheck(pow(xf, yf), "pow");
1144 		break;
1145 	default:
1146 		FATAL("illegal assignment operator %d", n);
1147 		break;
1148 	}
1149 	tempfree(y);
1150 	setfval(x, xf);
1151 	return(x);
1152 }
1153 
cat(Node ** a,int q)1154 Cell *cat(Node **a, int q)	/* a[0] cat a[1] */
1155 {
1156 	Cell *x, *y, *z;
1157 	int n1, n2;
1158 	char *s;
1159 	size_t len;
1160 
1161 	x = execute(a[0]);
1162 	y = execute(a[1]);
1163 	getsval(x);
1164 	getsval(y);
1165 	n1 = strlen(x->sval);
1166 	n2 = strlen(y->sval);
1167 	len = n1 + n2 + 1;
1168 	s = (char *) malloc(len);
1169 	if (s == NULL)
1170 		FATAL("out of space concatenating %.15s... and %.15s...",
1171 			x->sval, y->sval);
1172 	strlcpy(s, x->sval, len);
1173 	strlcpy(s+n1, y->sval, len - n1);
1174 	tempfree(x);
1175 	tempfree(y);
1176 	z = gettemp();
1177 	z->sval = s;
1178 	z->tval = STR;
1179 	return(z);
1180 }
1181 
pastat(Node ** a,int n)1182 Cell *pastat(Node **a, int n)	/* a[0] { a[1] } */
1183 {
1184 	Cell *x;
1185 
1186 	if (a[0] == 0)
1187 		x = execute(a[1]);
1188 	else {
1189 		x = execute(a[0]);
1190 		if (istrue(x)) {
1191 			tempfree(x);
1192 			x = execute(a[1]);
1193 		}
1194 	}
1195 	return x;
1196 }
1197 
dopa2(Node ** a,int n)1198 Cell *dopa2(Node **a, int n)	/* a[0], a[1] { a[2] } */
1199 {
1200 	Cell *x;
1201 	int pair;
1202 
1203 	pair = ptoi(a[3]);
1204 	if (pairstack[pair] == 0) {
1205 		x = execute(a[0]);
1206 		if (istrue(x))
1207 			pairstack[pair] = 1;
1208 		tempfree(x);
1209 	}
1210 	if (pairstack[pair] == 1) {
1211 		x = execute(a[1]);
1212 		if (istrue(x))
1213 			pairstack[pair] = 0;
1214 		tempfree(x);
1215 		x = execute(a[2]);
1216 		return(x);
1217 	}
1218 	return(False);
1219 }
1220 
split(Node ** a,int nnn)1221 Cell *split(Node **a, int nnn)	/* split(a[0], a[1], a[2]); a[3] is type */
1222 {
1223 	static char nullfs[] = "";
1224 	static char refs[] = "(regexpr)";
1225 	Cell *x = 0, *y, *ap;
1226 	char *s;
1227 	int sep;
1228 	char *t, temp, num[50], *fs = 0;
1229 	int n, tempstat, arg3type;
1230 
1231 	y = execute(a[0]);	/* source string */
1232 	s = getsval(y);
1233 	arg3type = ptoi(a[3]);
1234 	if (a[2] == 0)		/* fs string */
1235 		fs = *FS;
1236 	else if (arg3type == STRING) {	/* split(str,arr,"string") */
1237 		x = execute(a[2]);
1238 		fs = getsval(x);
1239 	} else if (arg3type == REGEXPR)
1240 		fs = refs;	/* split(str,arr,/regexpr/) */
1241 	else
1242 		FATAL("illegal type of split");
1243 	sep = *fs;
1244 	ap = execute(a[1]);	/* array name */
1245 	freesymtab(ap);
1246 	   dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs) );
1247 	ap->tval &= ~STR;
1248 	ap->tval |= ARR;
1249 	ap->sval = (char *) makesymtab(NSYMTAB);
1250 
1251 	n = 0;
1252         if (arg3type == REGEXPR && strlen((char*)((fa*)a[2])->restr) == 0) {
1253 		/* split(s, a, //); have to arrange that it looks like empty sep */
1254 		arg3type = 0;
1255 		fs = nullfs;
1256 		sep = 0;
1257 	}
1258 	if (*s != '\0' && (strlen(fs) > 1 || arg3type == REGEXPR)) {	/* reg expr */
1259 		fa *pfa;
1260 		if (arg3type == REGEXPR) {	/* it's ready already */
1261 			pfa = (fa *) a[2];
1262 		} else {
1263 			pfa = makedfa(fs, 1);
1264 		}
1265 		if (nematch(pfa,s)) {
1266 			tempstat = pfa->initstat;
1267 			pfa->initstat = 2;
1268 			do {
1269 				n++;
1270 				snprintf(num, sizeof num, "%d", n);
1271 				temp = *patbeg;
1272 				*patbeg = '\0';
1273 				if (is_number(s))
1274 					setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
1275 				else
1276 					setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1277 				*patbeg = temp;
1278 				s = patbeg + patlen;
1279 				if (*(patbeg+patlen-1) == 0 || *s == 0) {
1280 					n++;
1281 					snprintf(num, sizeof num, "%d", n);
1282 					setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
1283 					pfa->initstat = tempstat;
1284 					goto spdone;
1285 				}
1286 			} while (nematch(pfa,s));
1287 			pfa->initstat = tempstat; 	/* bwk: has to be here to reset */
1288 							/* cf gsub and refldbld */
1289 		}
1290 		n++;
1291 		snprintf(num, sizeof num, "%d", n);
1292 		if (is_number(s))
1293 			setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
1294 		else
1295 			setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1296   spdone:
1297 		pfa = NULL;
1298 	} else if (sep == ' ') {
1299 		for (n = 0; ; ) {
1300 			while (*s == ' ' || *s == '\t' || *s == '\n')
1301 				s++;
1302 			if (*s == 0)
1303 				break;
1304 			n++;
1305 			t = s;
1306 			do
1307 				s++;
1308 			while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
1309 			temp = *s;
1310 			*s = '\0';
1311 			snprintf(num, sizeof num, "%d", n);
1312 			if (is_number(t))
1313 				setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1314 			else
1315 				setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1316 			*s = temp;
1317 			if (*s != 0)
1318 				s++;
1319 		}
1320 	} else if (sep == 0) {	/* new: split(s, a, "") => 1 char/elem */
1321 		for (n = 0; *s != 0; s++) {
1322 			char buf[2];
1323 			n++;
1324 			snprintf(num, sizeof num, "%d", n);
1325 			buf[0] = *s;
1326 			buf[1] = 0;
1327 			if (isdigit((uschar)buf[0]))
1328 				setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval);
1329 			else
1330 				setsymtab(num, buf, 0.0, STR, (Array *) ap->sval);
1331 		}
1332 	} else if (*s != 0) {
1333 		for (;;) {
1334 			n++;
1335 			t = s;
1336 			while (*s != sep && *s != '\n' && *s != '\0')
1337 				s++;
1338 			temp = *s;
1339 			*s = '\0';
1340 			snprintf(num, sizeof num, "%d", n);
1341 			if (is_number(t))
1342 				setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1343 			else
1344 				setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1345 			*s = temp;
1346 			if (*s++ == 0)
1347 				break;
1348 		}
1349 	}
1350 	tempfree(ap);
1351 	tempfree(y);
1352 	if (a[2] != 0 && arg3type == STRING) {
1353 		tempfree(x);
1354 	}
1355 	x = gettemp();
1356 	x->tval = NUM;
1357 	x->fval = n;
1358 	return(x);
1359 }
1360 
condexpr(Node ** a,int n)1361 Cell *condexpr(Node **a, int n)	/* a[0] ? a[1] : a[2] */
1362 {
1363 	Cell *x;
1364 
1365 	x = execute(a[0]);
1366 	if (istrue(x)) {
1367 		tempfree(x);
1368 		x = execute(a[1]);
1369 	} else {
1370 		tempfree(x);
1371 		x = execute(a[2]);
1372 	}
1373 	return(x);
1374 }
1375 
ifstat(Node ** a,int n)1376 Cell *ifstat(Node **a, int n)	/* if (a[0]) a[1]; else a[2] */
1377 {
1378 	Cell *x;
1379 
1380 	x = execute(a[0]);
1381 	if (istrue(x)) {
1382 		tempfree(x);
1383 		x = execute(a[1]);
1384 	} else if (a[2] != 0) {
1385 		tempfree(x);
1386 		x = execute(a[2]);
1387 	}
1388 	return(x);
1389 }
1390 
whilestat(Node ** a,int n)1391 Cell *whilestat(Node **a, int n)	/* while (a[0]) a[1] */
1392 {
1393 	Cell *x;
1394 
1395 	for (;;) {
1396 		x = execute(a[0]);
1397 		if (!istrue(x))
1398 			return(x);
1399 		tempfree(x);
1400 		x = execute(a[1]);
1401 		if (isbreak(x)) {
1402 			x = True;
1403 			return(x);
1404 		}
1405 		if (isnext(x) || isexit(x) || isret(x))
1406 			return(x);
1407 		tempfree(x);
1408 	}
1409 }
1410 
dostat(Node ** a,int n)1411 Cell *dostat(Node **a, int n)	/* do a[0]; while(a[1]) */
1412 {
1413 	Cell *x;
1414 
1415 	for (;;) {
1416 		x = execute(a[0]);
1417 		if (isbreak(x))
1418 			return True;
1419 		if (isnext(x) || isexit(x) || isret(x))
1420 			return(x);
1421 		tempfree(x);
1422 		x = execute(a[1]);
1423 		if (!istrue(x))
1424 			return(x);
1425 		tempfree(x);
1426 	}
1427 }
1428 
forstat(Node ** a,int n)1429 Cell *forstat(Node **a, int n)	/* for (a[0]; a[1]; a[2]) a[3] */
1430 {
1431 	Cell *x;
1432 
1433 	x = execute(a[0]);
1434 	tempfree(x);
1435 	for (;;) {
1436 		if (a[1]!=0) {
1437 			x = execute(a[1]);
1438 			if (!istrue(x)) return(x);
1439 			else tempfree(x);
1440 		}
1441 		x = execute(a[3]);
1442 		if (isbreak(x))		/* turn off break */
1443 			return True;
1444 		if (isnext(x) || isexit(x) || isret(x))
1445 			return(x);
1446 		tempfree(x);
1447 		x = execute(a[2]);
1448 		tempfree(x);
1449 	}
1450 }
1451 
instat(Node ** a,int n)1452 Cell *instat(Node **a, int n)	/* for (a[0] in a[1]) a[2] */
1453 {
1454 	Cell *x, *vp, *arrayp, *cp, *ncp;
1455 	Array *tp;
1456 	int i;
1457 
1458 	vp = execute(a[0]);
1459 	arrayp = execute(a[1]);
1460 	if (!isarr(arrayp)) {
1461 		return True;
1462 	}
1463 	tp = (Array *) arrayp->sval;
1464 	tempfree(arrayp);
1465 	for (i = 0; i < tp->size; i++) {	/* this routine knows too much */
1466 		for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1467 			setsval(vp, cp->nval);
1468 			ncp = cp->cnext;
1469 			x = execute(a[2]);
1470 			if (isbreak(x)) {
1471 				tempfree(vp);
1472 				return True;
1473 			}
1474 			if (isnext(x) || isexit(x) || isret(x)) {
1475 				tempfree(vp);
1476 				return(x);
1477 			}
1478 			tempfree(x);
1479 		}
1480 	}
1481 	return True;
1482 }
1483 
bltin(Node ** a,int n)1484 Cell *bltin(Node **a, int n)	/* builtin functions. a[0] is type, a[1] is arg list */
1485 {
1486 	Cell *x, *y;
1487 	Awkfloat u;
1488 	int t;
1489 	char *p, *buf;
1490 	Node *nextarg;
1491 	FILE *fp;
1492 
1493 	t = ptoi(a[0]);
1494 	x = execute(a[1]);
1495 	nextarg = a[1]->nnext;
1496 	switch (t) {
1497 	case FLENGTH:
1498 		if (isarr(x))
1499 			u = ((Array *) x->sval)->nelem;	/* GROT.  should be function*/
1500 		else
1501 			u = strlen(getsval(x));
1502 		break;
1503 	case FLOG:
1504 		u = errcheck(log(getfval(x)), "log"); break;
1505 	case FINT:
1506 		modf(getfval(x), &u); break;
1507 	case FEXP:
1508 		u = errcheck(exp(getfval(x)), "exp"); break;
1509 	case FSQRT:
1510 		u = errcheck(sqrt(getfval(x)), "sqrt"); break;
1511 	case FSIN:
1512 		u = sin(getfval(x)); break;
1513 	case FCOS:
1514 		u = cos(getfval(x)); break;
1515 	case FATAN:
1516 		if (nextarg == 0) {
1517 			WARNING("atan2 requires two arguments; returning 1.0");
1518 			u = 1.0;
1519 		} else {
1520 			y = execute(a[1]->nnext);
1521 			u = atan2(getfval(x), getfval(y));
1522 			tempfree(y);
1523 			nextarg = nextarg->nnext;
1524 		}
1525 		break;
1526 	case FCOMPL:
1527 		u = ~((int)getfval(x));
1528 		break;
1529 	case FAND:
1530 		if (nextarg == 0) {
1531 			WARNING("and requires two arguments; returning 0");
1532 			u = 0;
1533 			break;
1534 		}
1535 		y = execute(a[1]->nnext);
1536 		u = ((int)getfval(x)) & ((int)getfval(y));
1537 		tempfree(y);
1538 		nextarg = nextarg->nnext;
1539 		break;
1540 	case FFOR:
1541 		if (nextarg == 0) {
1542 			WARNING("or requires two arguments; returning 0");
1543 			u = 0;
1544 			break;
1545 		}
1546 		y = execute(a[1]->nnext);
1547 		u = ((int)getfval(x)) | ((int)getfval(y));
1548 		tempfree(y);
1549 		nextarg = nextarg->nnext;
1550 		break;
1551 	case FXOR:
1552 		if (nextarg == 0) {
1553 			WARNING("or requires two arguments; returning 0");
1554 			u = 0;
1555 			break;
1556 		}
1557 		y = execute(a[1]->nnext);
1558 		u = ((int)getfval(x)) ^ ((int)getfval(y));
1559 		tempfree(y);
1560 		nextarg = nextarg->nnext;
1561 		break;
1562 	case FLSHIFT:
1563 		if (nextarg == 0) {
1564 			WARNING("or requires two arguments; returning 0");
1565 			u = 0;
1566 			break;
1567 		}
1568 		y = execute(a[1]->nnext);
1569 		u = ((int)getfval(x)) << ((int)getfval(y));
1570 		tempfree(y);
1571 		nextarg = nextarg->nnext;
1572 		break;
1573 	case FRSHIFT:
1574 		if (nextarg == 0) {
1575 			WARNING("or requires two arguments; returning 0");
1576 			u = 0;
1577 			break;
1578 		}
1579 		y = execute(a[1]->nnext);
1580 		u = ((int)getfval(x)) >> ((int)getfval(y));
1581 		tempfree(y);
1582 		nextarg = nextarg->nnext;
1583 		break;
1584 	case FSYSTEM:
1585 		fflush(stdout);		/* in case something is buffered already */
1586 		u = (Awkfloat) system(getsval(x)) / 256;   /* 256 is unix-dep */
1587 		break;
1588 	case FSRAND:
1589 		if (!isrec(x)) {
1590 			/* an argument was provided */
1591 			u = getfval(x);
1592 			arc4random_pushb_fast(&u, sizeof(u));
1593 		}
1594 		/* FALLTHROUGH */
1595 	case FRAND:
1596 		u = (Awkfloat)arc4random() / 4294967296.;
1597 		break;
1598 	case FTOUPPER:
1599 	case FTOLOWER:
1600 		buf = tostring(getsval(x));
1601 		if (t == FTOUPPER) {
1602 			for (p = buf; *p; p++)
1603 				if (islower((uschar) *p))
1604 					*p = toupper((uschar)*p);
1605 		} else {
1606 			for (p = buf; *p; p++)
1607 				if (isupper((uschar) *p))
1608 					*p = tolower((uschar)*p);
1609 		}
1610 		tempfree(x);
1611 		x = gettemp();
1612 		setsval(x, buf);
1613 		free(buf);
1614 		return x;
1615 	case FFLUSH:
1616 		if (isrec(x) || strlen(getsval(x)) == 0) {
1617 			flush_all();	/* fflush() or fflush("") -> all */
1618 			u = 0;
1619 		} else if ((fp = openfile(FFLUSH, getsval(x))) == NULL)
1620 			u = EOF;
1621 		else
1622 			u = fflush(fp);
1623 		break;
1624 	default:	/* can't happen */
1625 		FATAL("illegal function type %d", t);
1626 		break;
1627 	}
1628 	tempfree(x);
1629 	x = gettemp();
1630 	setfval(x, u);
1631 	if (nextarg != 0) {
1632 		WARNING("warning: function has too many arguments");
1633 		for ( ; nextarg; nextarg = nextarg->nnext)
1634 			execute(nextarg);
1635 	}
1636 	return(x);
1637 }
1638 
printstat(Node ** a,int n)1639 Cell *printstat(Node **a, int n)	/* print a[0] */
1640 {
1641 	Node *x;
1642 	Cell *y;
1643 	FILE *fp;
1644 
1645 	if (a[1] == 0)	/* a[1] is redirection operator, a[2] is file */
1646 		fp = stdout;
1647 	else
1648 		fp = redirect(ptoi(a[1]), a[2]);
1649 	for (x = a[0]; x != NULL; x = x->nnext) {
1650 		y = execute(x);
1651 		fputs(getpssval(y), fp);
1652 		tempfree(y);
1653 		if (x->nnext == NULL)
1654 			fputs(*ORS, fp);
1655 		else
1656 			fputs(*OFS, fp);
1657 	}
1658 	if (a[1] != 0)
1659 		fflush(fp);
1660 	if (ferror(fp))
1661 		FATAL("write error on %s", filename(fp));
1662 	return(True);
1663 }
1664 
nullproc(Node ** a,int n)1665 Cell *nullproc(Node **a, int n)
1666 {
1667 	n = n;
1668 	a = a;
1669 	return 0;
1670 }
1671 
1672 
redirect(int a,Node * b)1673 FILE *redirect(int a, Node *b)	/* set up all i/o redirections */
1674 {
1675 	FILE *fp;
1676 	Cell *x;
1677 	char *fname;
1678 
1679 	x = execute(b);
1680 	fname = getsval(x);
1681 	fp = openfile(a, fname);
1682 	if (fp == NULL)
1683 		FATAL("can't open file %s", fname);
1684 	tempfree(x);
1685 	return fp;
1686 }
1687 
1688 struct files {
1689 	FILE	*fp;
1690 	char	*fname;
1691 	int	mode;	/* '|', 'a', 'w' => LE/LT, GT */
1692 } *files;
1693 
1694 int nfiles;
1695 
stdinit(void)1696 void stdinit(void)	/* in case stdin, etc., are not constants */
1697 {
1698 	nfiles = FOPEN_MAX;
1699 	files = calloc(nfiles, sizeof(*files));
1700 	if (files == NULL)
1701 		FATAL("can't allocate file memory for %u files", nfiles);
1702         files[0].fp = stdin;
1703 	files[0].fname = strdup("/dev/stdin");
1704 	files[0].mode = LT;
1705         files[1].fp = stdout;
1706 	files[1].fname = strdup("/dev/stdout");
1707 	files[1].mode = GT;
1708         files[2].fp = stderr;
1709 	files[2].fname = strdup("/dev/stderr");
1710 	files[2].mode = GT;
1711 }
1712 
openfile(int a,const char * us)1713 FILE *openfile(int a, const char *us)
1714 {
1715 	const char *s = us;
1716 	int i, m;
1717 	FILE *fp = 0;
1718 
1719 	if (*s == '\0')
1720 		FATAL("null file name in print or getline");
1721 	for (i=0; i < nfiles; i++)
1722 		if (files[i].fname && strcmp(s, files[i].fname) == 0) {
1723 			if (a == files[i].mode || (a==APPEND && files[i].mode==GT))
1724 				return files[i].fp;
1725 			if (a == FFLUSH)
1726 				return files[i].fp;
1727 		}
1728 	if (a == FFLUSH)	/* didn't find it, so don't create it! */
1729 		return NULL;
1730 
1731 	for (i=0; i < nfiles; i++)
1732 		if (files[i].fp == 0)
1733 			break;
1734 	if (i >= nfiles) {
1735 		struct files *nf;
1736 		int nnf = nfiles + FOPEN_MAX;
1737 		nf = realloc(files, nnf * sizeof(*nf));
1738 		if (nf == NULL)
1739 			FATAL("cannot grow files for %s and %d files", s, nnf);
1740 		memset(&nf[nfiles], 0, FOPEN_MAX * sizeof(*nf));
1741 		nfiles = nnf;
1742 		files = nf;
1743 	}
1744 	fflush(stdout);	/* force a semblance of order */
1745 	m = a;
1746 	if (a == GT) {
1747 		fp = fopen(s, "w");
1748 	} else if (a == APPEND) {
1749 		fp = fopen(s, "a");
1750 		m = GT;	/* so can mix > and >> */
1751 	} else if (a == '|') {	/* output pipe */
1752 		fp = popen(s, "w");
1753 	} else if (a == LE) {	/* input pipe */
1754 		fp = popen(s, "r");
1755 	} else if (a == LT) {	/* getline <file */
1756 		fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r");	/* "-" is stdin */
1757 	} else	/* can't happen */
1758 		FATAL("illegal redirection %d", a);
1759 	if (fp != NULL) {
1760 		files[i].fname = tostring(s);
1761 		files[i].fp = fp;
1762 		files[i].mode = m;
1763 	}
1764 	return fp;
1765 }
1766 
filename(FILE * fp)1767 const char *filename(FILE *fp)
1768 {
1769 	int i;
1770 
1771 	for (i = 0; i < nfiles; i++)
1772 		if (fp == files[i].fp)
1773 			return files[i].fname;
1774 	return "???";
1775 }
1776 
closefile(Node ** a,int n)1777 Cell *closefile(Node **a, int n)
1778 {
1779 	Cell *x;
1780 	int i, stat;
1781 
1782 	n = n;
1783 	x = execute(a[0]);
1784 	getsval(x);
1785 	stat = -1;
1786 	for (i = 0; i < nfiles; i++) {
1787 		if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) {
1788 			if (ferror(files[i].fp))
1789 				WARNING( "i/o error occurred on %s", files[i].fname );
1790 			if (files[i].mode == '|' || files[i].mode == LE)
1791 				stat = pclose(files[i].fp);
1792 			else
1793 				stat = fclose(files[i].fp);
1794 			if (stat == EOF)
1795 				WARNING( "i/o error occurred closing %s", files[i].fname );
1796 			if (i > 2)	/* don't do /dev/std... */
1797 				xfree(files[i].fname);
1798 			files[i].fname = NULL;	/* watch out for ref thru this */
1799 			files[i].fp = NULL;
1800 		}
1801 	}
1802 	tempfree(x);
1803 	x = gettemp();
1804 	setfval(x, (Awkfloat) stat);
1805 	return(x);
1806 }
1807 
closeall(void)1808 void closeall(void)
1809 {
1810 	int i, stat;
1811 
1812 	for (i = 0; i < FOPEN_MAX; i++) {
1813 		if (files[i].fp) {
1814 			if (ferror(files[i].fp))
1815 				WARNING( "i/o error occurred on %s", files[i].fname );
1816 			if (files[i].mode == '|' || files[i].mode == LE)
1817 				stat = pclose(files[i].fp);
1818 			else
1819 				stat = fclose(files[i].fp);
1820 			if (stat == EOF)
1821 				WARNING( "i/o error occurred while closing %s", files[i].fname );
1822 		}
1823 	}
1824 }
1825 
flush_all(void)1826 void flush_all(void)
1827 {
1828 	int i;
1829 
1830 	for (i = 0; i < nfiles; i++)
1831 		if (files[i].fp)
1832 			fflush(files[i].fp);
1833 }
1834 
1835 void backsub(char **pb_ptr, char **sptr_ptr);
1836 
sub(Node ** a,int nnn)1837 Cell *sub(Node **a, int nnn)	/* substitute command */
1838 {
1839 	char *sptr, *pb, *q;
1840 	Cell *x, *y, *result;
1841 	char *t, *buf;
1842 	fa *pfa;
1843 	int bufsz = recsize;
1844 
1845 	if ((buf = (char *) malloc(bufsz)) == NULL)
1846 		FATAL("out of memory in sub");
1847 	x = execute(a[3]);	/* target string */
1848 	t = getsval(x);
1849 	if (a[0] == 0)		/* 0 => a[1] is already-compiled regexpr */
1850 		pfa = (fa *) a[1];	/* regular expression */
1851 	else {
1852 		y = execute(a[1]);
1853 		pfa = makedfa(getsval(y), 1);
1854 		tempfree(y);
1855 	}
1856 	y = execute(a[2]);	/* replacement string */
1857 	result = False;
1858 	if (pmatch(pfa, t)) {
1859 		sptr = t;
1860 		adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub");
1861 		pb = buf;
1862 		while (sptr < patbeg)
1863 			*pb++ = *sptr++;
1864 		sptr = getsval(y);
1865 		while (*sptr != 0) {
1866 			adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub");
1867 			if (*sptr == '\\') {
1868 				backsub(&pb, &sptr);
1869 			} else if (*sptr == '&') {
1870 				sptr++;
1871 				adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub");
1872 				for (q = patbeg; q < patbeg+patlen; )
1873 					*pb++ = *q++;
1874 			} else
1875 				*pb++ = *sptr++;
1876 		}
1877 		*pb = '\0';
1878 		if (pb > buf + bufsz)
1879 			FATAL("sub result1 %.30s too big; can't happen", buf);
1880 		sptr = patbeg + patlen;
1881 		if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
1882 			adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
1883 			while ((*pb++ = *sptr++) != 0)
1884 				;
1885 		}
1886 		if (pb > buf + bufsz)
1887 			FATAL("sub result2 %.30s too big; can't happen", buf);
1888 		setsval(x, buf);	/* BUG: should be able to avoid copy */
1889 		result = True;
1890 	}
1891 	tempfree(x);
1892 	tempfree(y);
1893 	free(buf);
1894 	return result;
1895 }
1896 
gsub(Node ** a,int nnn)1897 Cell *gsub(Node **a, int nnn)	/* global substitute */
1898 {
1899 	Cell *x, *y;
1900 	char *rptr, *sptr, *t, *pb, *q;
1901 	char *buf;
1902 	fa *pfa;
1903 	int mflag, tempstat, num;
1904 	int bufsz = recsize;
1905 
1906 	if ((buf = (char *) malloc(bufsz)) == NULL)
1907 		FATAL("out of memory in gsub");
1908 	mflag = 0;	/* if mflag == 0, can replace empty string */
1909 	num = 0;
1910 	x = execute(a[3]);	/* target string */
1911 	t = getsval(x);
1912 	if (a[0] == 0)		/* 0 => a[1] is already-compiled regexpr */
1913 		pfa = (fa *) a[1];	/* regular expression */
1914 	else {
1915 		y = execute(a[1]);
1916 		pfa = makedfa(getsval(y), 1);
1917 		tempfree(y);
1918 	}
1919 	y = execute(a[2]);	/* replacement string */
1920 	if (pmatch(pfa, t)) {
1921 		tempstat = pfa->initstat;
1922 		pfa->initstat = 2;
1923 		pb = buf;
1924 		rptr = getsval(y);
1925 		do {
1926 			if (patlen == 0 && *patbeg != 0) {	/* matched empty string */
1927 				if (mflag == 0) {	/* can replace empty */
1928 					num++;
1929 					sptr = rptr;
1930 					while (*sptr != 0) {
1931 						adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1932 						if (*sptr == '\\') {
1933 							backsub(&pb, &sptr);
1934 						} else if (*sptr == '&') {
1935 							sptr++;
1936 							adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1937 							for (q = patbeg; q < patbeg+patlen; )
1938 								*pb++ = *q++;
1939 						} else
1940 							*pb++ = *sptr++;
1941 					}
1942 				}
1943 				if (*t == 0)	/* at end */
1944 					goto done;
1945 				adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
1946 				*pb++ = *t++;
1947 				if (pb > buf + bufsz)	/* BUG: not sure of this test */
1948 					FATAL("gsub result0 %.30s too big; can't happen", buf);
1949 				mflag = 0;
1950 			}
1951 			else {	/* matched nonempty string */
1952 				num++;
1953 				sptr = t;
1954 				adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub");
1955 				while (sptr < patbeg)
1956 					*pb++ = *sptr++;
1957 				sptr = rptr;
1958 				while (*sptr != 0) {
1959 					adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1960 					if (*sptr == '\\') {
1961 						backsub(&pb, &sptr);
1962 					} else if (*sptr == '&') {
1963 						sptr++;
1964 						adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1965 						for (q = patbeg; q < patbeg+patlen; )
1966 							*pb++ = *q++;
1967 					} else
1968 						*pb++ = *sptr++;
1969 				}
1970 				t = patbeg + patlen;
1971 				if (patlen == 0 || *t == 0 || *(t-1) == 0)
1972 					goto done;
1973 				if (pb > buf + bufsz)
1974 					FATAL("gsub result1 %.30s too big; can't happen", buf);
1975 				mflag = 1;
1976 			}
1977 		} while (pmatch(pfa,t));
1978 		sptr = t;
1979 		adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
1980 		while ((*pb++ = *sptr++) != 0)
1981 			;
1982 	done:	if (pb < buf + bufsz)
1983 			*pb = '\0';
1984 		else if (*(pb-1) != '\0')
1985 			FATAL("gsub result2 %.30s truncated; can't happen", buf);
1986 		setsval(x, buf);	/* BUG: should be able to avoid copy + free */
1987 		pfa->initstat = tempstat;
1988 	}
1989 	tempfree(x);
1990 	tempfree(y);
1991 	x = gettemp();
1992 	x->tval = NUM;
1993 	x->fval = num;
1994 	free(buf);
1995 	return(x);
1996 }
1997 
backsub(char ** pb_ptr,char ** sptr_ptr)1998 void backsub(char **pb_ptr, char **sptr_ptr)	/* handle \\& variations */
1999 {						/* sptr[0] == '\\' */
2000 	char *pb = *pb_ptr, *sptr = *sptr_ptr;
2001 
2002 	if (sptr[1] == '\\') {
2003 		if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
2004 			*pb++ = '\\';
2005 			*pb++ = '&';
2006 			sptr += 4;
2007 		} else if (sptr[2] == '&') {	/* \\& -> \ + matched */
2008 			*pb++ = '\\';
2009 			sptr += 2;
2010 		} else {			/* \\x -> \\x */
2011 			*pb++ = *sptr++;
2012 			*pb++ = *sptr++;
2013 		}
2014 	} else if (sptr[1] == '&') {	/* literal & */
2015 		sptr++;
2016 		*pb++ = *sptr++;
2017 	} else				/* literal \ */
2018 		*pb++ = *sptr++;
2019 
2020 	*pb_ptr = pb;
2021 	*sptr_ptr = sptr;
2022 }
2023