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