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