GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/awk/run.c Lines: 578 1261 45.8 %
Date: 2017-11-13 Branches: 364 1037 35.1 %

Line Branch Exec Source
1
/*	$OpenBSD: run.c,v 1.42 2017/10/09 14:51:31 deraadt Exp $	*/
2
/****************************************************************
3
Copyright (C) Lucent Technologies 1997
4
All Rights Reserved
5
6
Permission to use, copy, modify, and distribute this software and
7
its documentation for any purpose and without fee is hereby
8
granted, provided that the above copyright notice appear in all
9
copies and that both that the copyright notice and this
10
permission notice and warranty disclaimer appear in supporting
11
documentation, and that the name Lucent Technologies or any of
12
its entities not be used in advertising or publicity pertaining
13
to distribution of the software without specific, written prior
14
permission.
15
16
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
18
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
19
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
21
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
22
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
23
THIS SOFTWARE.
24
****************************************************************/
25
26
#define DEBUG
27
#include <stdio.h>
28
#include <ctype.h>
29
#include <setjmp.h>
30
#include <limits.h>
31
#include <math.h>
32
#include <string.h>
33
#include <stdlib.h>
34
#include <time.h>
35
#include "awk.h"
36
#include "ytab.h"
37
38
#define tempfree(x)	if (istemp(x)) tfree(x); else
39
40
/*
41
#undef tempfree
42
43
void tempfree(Cell *p) {
44
	if (p->ctype == OCELL && (p->csub < CUNK || p->csub > CFREE)) {
45
		WARNING("bad csub %d in Cell %d %s",
46
			p->csub, p->ctype, p->sval);
47
	}
48
	if (istemp(p))
49
		tfree(p);
50
}
51
*/
52
53
/* do we really need these? */
54
/* #ifdef _NFILE */
55
/* #ifndef FOPEN_MAX */
56
/* #define FOPEN_MAX _NFILE */
57
/* #endif */
58
/* #endif */
59
/*  */
60
/* #ifndef	FOPEN_MAX */
61
/* #define	FOPEN_MAX	40 */	/* max number of open files */
62
/* #endif */
63
/*  */
64
/* #ifndef RAND_MAX */
65
/* #define RAND_MAX	32767 */	/* all that ansi guarantees */
66
/* #endif */
67
68
jmp_buf env;
69
extern	int	pairstack[];
70
extern	Awkfloat	srand_seed;
71
72
Node	*winner = NULL;	/* root of parse tree */
73
Cell	*tmps;		/* free temporary cells for execution */
74
75
static Cell	truecell	={ OBOOL, BTRUE, 0, 0, 1.0, NUM };
76
Cell	*True	= &truecell;
77
static Cell	falsecell	={ OBOOL, BFALSE, 0, 0, 0.0, NUM };
78
Cell	*False	= &falsecell;
79
static Cell	breakcell	={ OJUMP, JBREAK, 0, 0, 0.0, NUM };
80
Cell	*jbreak	= &breakcell;
81
static Cell	contcell	={ OJUMP, JCONT, 0, 0, 0.0, NUM };
82
Cell	*jcont	= &contcell;
83
static Cell	nextcell	={ OJUMP, JNEXT, 0, 0, 0.0, NUM };
84
Cell	*jnext	= &nextcell;
85
static Cell	nextfilecell	={ OJUMP, JNEXTFILE, 0, 0, 0.0, NUM };
86
Cell	*jnextfile	= &nextfilecell;
87
static Cell	exitcell	={ OJUMP, JEXIT, 0, 0, 0.0, NUM };
88
Cell	*jexit	= &exitcell;
89
static Cell	retcell		={ OJUMP, JRET, 0, 0, 0.0, NUM };
90
Cell	*jret	= &retcell;
91
static Cell	tempcell	={ OCELL, CTEMP, 0, "", 0.0, NUM|STR|DONTFREE };
92
93
Node	*curnode = NULL;	/* the node being executed, for debugging */
94
95
void	stdinit(void);
96
void	flush_all(void);
97
98
/* buffer memory management */
99
int adjbuf(char **pbuf, int *psiz, int minlen, int quantum, char **pbptr,
100
	const char *whatrtn)
101
/* pbuf:    address of pointer to buffer being managed
102
 * psiz:    address of buffer size variable
103
 * minlen:  minimum length of buffer needed
104
 * quantum: buffer size quantum
105
 * pbptr:   address of movable pointer into buffer, or 0 if none
106
 * whatrtn: name of the calling routine if failure should cause fatal error
107
 *
108
 * return   0 for realloc failure, !=0 for success
109
 */
110
{
111
5517870
	if (minlen > *psiz) {
112
		char *tbuf;
113
1461
		int rminlen = quantum ? minlen % quantum : 0;
114
1461
		int boff = pbptr ? *pbptr - *pbuf : 0;
115
		/* round up to next multiple of quantum */
116
487
		if (rminlen)
117
487
			minlen += quantum - rminlen;
118
487
		tbuf = (char *) realloc(*pbuf, minlen);
119
487
		DPRINTF( ("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, *pbuf, tbuf) );
120
487
		if (tbuf == NULL) {
121
			if (whatrtn)
122
				FATAL("out of memory in %s", whatrtn);
123
			return 0;
124
		}
125
487
		*pbuf = tbuf;
126
487
		*psiz = minlen;
127
487
		if (pbptr)
128
487
			*pbptr = tbuf + boff;
129
487
	}
130
2758935
	return 1;
131
2758935
}
132
133
void run(Node *a)	/* execution of parse tree starts here */
134
{
135
974
	stdinit();
136
487
	execute(a);
137
487
	closeall();
138
487
}
139
140
Cell *execute(Node *u)	/* execute a node of the parse tree */
141
{
142
	Cell *(*proc)(Node **, int);
143
	Cell *x;
144
	Node *a;
145
146
40669086
	if (u == NULL)
147
310
		return(True);
148
22164052
	for (a = u; ; a = a->nnext) {
149
22164052
		curnode = a;
150
22164052
		if (isvalue(a)) {
151
10904550
			x = (Cell *) (a->narg[0]);
152
10904550
			if (isfld(x) && !donefld)
153
				fldbld();
154
10904550
			else if (isrec(x) && !donerec)
155
				recbld();
156
10904550
			return(x);
157
		}
158

33778506
		if (notlegal(a->nobj))	/* probably a Cell* but too risky to print */
159
			FATAL("illegal statement");
160
		proc = proctab[a->nobj-FIRSTTOKEN];
161
11259367
		x = (*proc)(a->narg, a->nobj);
162
11259367
		if (isfld(x) && !donefld)
163
21073
			fldbld();
164
11238294
		else if (isrec(x) && !donerec)
165
8
			recbld();
166
11259367
		if (isexpr(a))
167
6543546
			return(x);
168
4715821
		if (isjump(x))
169
16700
			return(x);
170
4699121
		if (a->nnext == NULL)
171
2869302
			return(x);
172
1839655
		tempfree(x);
173
	}
174
20334408
}
175
176
177
Cell *program(Node **a, int n)	/* execute an awk program */
178
{				/* a[0] = BEGIN, a[1] = body, a[2] = END */
179
	Cell *x;
180
181
1026
	if (setjmp(env) != 0)
182
		goto ex;
183
487
	if (a[0]) {		/* BEGIN */
184
92
		x = execute(a[0]);
185
92
		if (isexit(x))
186
			return(True);
187
92
		if (isjump(x))
188
			FATAL("illegal break, continue, next or nextfile from BEGIN");
189
92
		tempfree(x);
190
	}
191

556
	if (a[1] || a[2])
192
1197718
		while (getrec(&record, &recsize, 1) > 0) {
193
598419
			x = execute(a[1]);
194
598419
			if (isexit(x))
195
				break;
196
598419
			tempfree(x);
197
		}
198
  ex:
199
487
	if (setjmp(env) != 0)	/* handles exit within END */
200
		goto ex1;
201
487
	if (a[2]) {		/* END */
202
84
		x = execute(a[2]);
203


336
		if (isbreak(x) || isnext(x) || iscont(x))
204
			FATAL("illegal break, continue, next or nextfile from END");
205
84
		tempfree(x);
206
	}
207
  ex1:
208
487
	return(True);
209
487
}
210
211
struct Frame {	/* stack frame for awk function calls */
212
	int nargs;	/* number of arguments in this call */
213
	Cell *fcncell;	/* pointer to Cell for function */
214
	Cell **args;	/* pointer to array of arguments after execute */
215
	Cell *retval;	/* return value */
216
};
217
218
#define	NARGS	50	/* max args in a call */
219
220
struct Frame *frame = NULL;	/* base of stack frames; dynamically allocated */
221
int	nframe = 0;		/* number of frames allocated */
222
struct Frame *fp = NULL;	/* frame pointer. bottom level unused */
223
224
Cell *call(Node **a, int n)	/* function call.  very kludgy and fragile */
225
{
226
	static Cell newcopycell = { OCELL, CCOPY, 0, "", 0.0, NUM|STR|DONTFREE };
227
	int i, ncall, ndef;
228
	int freed = 0; /* handles potential double freeing when fcn & param share a tempcell */
229
	Node *x;
230
12600
	Cell *args[NARGS], *oargs[NARGS];	/* BUG: fixed size arrays */
231
	Cell *y, *z, *fcn;
232
	char *s;
233
234
6300
	fcn = execute(a[0]);	/* the function itself */
235
6300
	s = fcn->nval;
236
6300
	if (!isfcn(fcn))
237
		FATAL("calling undefined function %s", s);
238
6300
	if (frame == NULL) {
239
8
		fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
240
8
		if (frame == NULL)
241
			FATAL("out of space for stack frames calling %s", s);
242
	}
243
25272
	for (ncall = 0, x = a[1]; x != NULL; x = x->nnext)	/* args in call */
244
6336
		ncall++;
245
6300
	ndef = (int) fcn->fval;			/* args in defn */
246
6300
	   DPRINTF( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) );
247
6300
	if (ncall > ndef)
248
		WARNING("function %s called with %d args, uses only %d",
249
			s, ncall, ndef);
250
6300
	if (ncall + ndef > NARGS)
251
		FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS);
252
25272
	for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) {	/* get call args */
253
6336
		   DPRINTF( ("evaluate args[%d], fp=%d:\n", i, (int) (fp-frame)) );
254
6336
		y = execute(x);
255
6336
		oargs[i] = y;
256


6336
		   DPRINTF( ("args[%d]: %s %f <%s>, t=%o\n",
257
			   i, NN(y->nval), y->fval, isarr(y) ? "(array)" : NN(y->sval), y->tval) );
258
6336
		if (isfcn(y))
259
			FATAL("can't use function %s as argument in %s", y->nval, s);
260
6336
		if (isarr(y))
261
			args[i] = y;	/* arrays by ref */
262
		else
263
6336
			args[i] = copycell(y);
264
6336
		tempfree(y);
265
	}
266
12600
	for ( ; i < ndef; i++) {	/* add null args for ones not provided */
267
		args[i] = gettemp();
268
		*args[i] = newcopycell;
269
	}
270
6300
	fp++;	/* now ok to up frame */
271
6300
	if (fp >= frame + nframe) {
272
		int dfp = fp - frame;	/* old index */
273
		frame = reallocarray(frame, (nframe += 100),
274
		    sizeof(struct Frame));
275
		if (frame == NULL)
276
			FATAL("out of space for stack frames in %s", s);
277
		fp = frame + dfp;
278
	}
279
6300
	fp->fcncell = fcn;
280
6300
	fp->args = args;
281
6300
	fp->nargs = ndef;	/* number defined with (excess are locals) */
282
6300
	fp->retval = gettemp();
283
284
6300
	   DPRINTF( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) );
285
6300
	y = execute((Node *)(fcn->sval));	/* execute body */
286
6300
	   DPRINTF( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) );
287
288
25272
	for (i = 0; i < ndef; i++) {
289
6336
		Cell *t = fp->args[i];
290
6336
		if (isarr(t)) {
291
			if (t->csub == CCOPY) {
292
				if (i >= ncall) {
293
					freesymtab(t);
294
					t->csub = CTEMP;
295
					tempfree(t);
296
				} else {
297
					oargs[i]->tval = t->tval;
298
					oargs[i]->tval &= ~(STR|NUM|DONTFREE);
299
					oargs[i]->sval = t->sval;
300
					tempfree(t);
301
				}
302
			}
303
6336
		} else if (t != y) {	/* kludge to prevent freeing twice */
304
6336
			t->csub = CTEMP;
305
12672
			tempfree(t);
306
		} else if (t == y && t->csub == CCOPY) {
307
			t->csub = CTEMP;
308
			tempfree(t);
309
			freed = 1;
310
		}
311
	}
312
6300
	tempfree(fcn);
313

18900
	if (isexit(y) || isnext(y))
314
		return y;
315
6300
	if (freed == 0) {
316
6300
		tempfree(y);	/* don't free twice! */
317
	}
318
6300
	z = fp->retval;			/* return value */
319
6300
	   DPRINTF( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );
320
6300
	fp--;
321
6300
	return(z);
322
6300
}
323
324
Cell *copycell(Cell *x)	/* make a copy of a cell in a temp */
325
{
326
	Cell *y;
327
328
12672
	y = gettemp();
329
6336
	y->csub = CCOPY;	/* prevents freeing until call is over */
330
6336
	y->nval = x->nval;	/* BUG? */
331
6336
	if (isstr(x))
332
6336
		y->sval = tostring(x->sval);
333
6336
	y->fval = x->fval;
334
6336
	y->tval = x->tval & ~(CON|FLD|REC|DONTFREE);	/* copy is not constant or field */
335
							/* is DONTFREE right? */
336
6336
	return y;
337
}
338
339
Cell *arg(Node **a, int n)	/* nth argument of a function */
340
{
341
342
25716
	n = ptoi(a[0]);	/* argument number, counting from 0 */
343
12858
	   DPRINTF( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );
344
12858
	if (n+1 > fp->nargs)
345
		FATAL("argument #%d of function %s was not supplied",
346
			n+1, fp->fcncell->nval);
347
12858
	return fp->args[n];
348
}
349
350
Cell *jump(Node **a, int n)	/* break, continue, next, nextfile, return */
351
{
352
	Cell *y;
353
354

23068
	switch (n) {
355
	case EXIT:
356
52
		if (a[0] != NULL) {
357
4
			y = execute(a[0]);
358
4
			errorflag = (int) getfval(y);
359
4
			tempfree(y);
360
		}
361
		longjmp(env, 1);
362
	case RETURN:
363
6264
		if (a[0] != NULL) {
364
6264
			y = execute(a[0]);
365
6264
			if ((y->tval & (STR|NUM)) == (STR|NUM)) {
366
4
				setsval(fp->retval, getsval(y));
367
4
				fp->retval->fval = getfval(y);
368
4
				fp->retval->tval |= NUM;
369
4
			}
370
6260
			else if (y->tval & STR)
371
5964
				setsval(fp->retval, getsval(y));
372
296
			else if (y->tval & NUM)
373
296
				setfval(fp->retval, getfval(y));
374
			else		/* can't happen */
375
				FATAL("bad type variable %d", y->tval);
376
9246
			tempfree(y);
377
		}
378
6264
		return(jret);
379
	case NEXT:
380
4410
		return(jnext);
381
	case NEXTFILE:
382
		nextfile();
383
		return(jnextfile);
384
	case BREAK:
385
808
		return(jbreak);
386
	case CONTINUE:
387
		return(jcont);
388
	default:	/* can't happen */
389
		FATAL("illegal jump type %d", n);
390
	}
391
	return 0;	/* not reached */
392
11482
}
393
394
Cell *awkgetline(Node **a, int n)	/* get next line from specific input */
395
{		/* a[0] is variable, a[1] is operator, a[2] is filename */
396
	Cell *r, *x;
397
	extern Cell **fldtab;
398
	FILE *fp;
399
	char *buf;
400
	int bufsize = recsize;
401
	int mode;
402
403
	if ((buf = (char *) malloc(bufsize)) == NULL)
404
		FATAL("out of memory in getline");
405
406
	fflush(stdout);	/* in case someone is waiting for a prompt */
407
	r = gettemp();
408
	if (a[1] != NULL) {		/* getline < file */
409
		x = execute(a[2]);		/* filename */
410
		mode = ptoi(a[1]);
411
		if (mode == '|')		/* input pipe */
412
			mode = LE;	/* arbitrary flag */
413
		fp = openfile(mode, getsval(x));
414
		tempfree(x);
415
		if (fp == NULL)
416
			n = -1;
417
		else
418
			n = readrec(&buf, &bufsize, fp);
419
		if (n <= 0) {
420
			;
421
		} else if (a[0] != NULL) {	/* getline var <file */
422
			x = execute(a[0]);
423
			setsval(x, buf);
424
			tempfree(x);
425
		} else {			/* getline <file */
426
			setsval(fldtab[0], buf);
427
			if (is_number(fldtab[0]->sval)) {
428
				fldtab[0]->fval = atof(fldtab[0]->sval);
429
				fldtab[0]->tval |= NUM;
430
			}
431
		}
432
	} else {			/* bare getline; use current input */
433
		if (a[0] == NULL)	/* getline */
434
			n = getrec(&record, &recsize, 1);
435
		else {			/* getline var */
436
			n = getrec(&buf, &bufsize, 0);
437
			x = execute(a[0]);
438
			setsval(x, buf);
439
			tempfree(x);
440
		}
441
	}
442
	setfval(r, (Awkfloat) n);
443
	free(buf);
444
	return r;
445
}
446
447
Cell *getnf(Node **a, int n)	/* get NF */
448
{
449
25040
	if (donefld == 0)
450
192
		fldbld();
451
12520
	return (Cell *) a[0];
452
}
453
454
Cell *array(Node **a, int n)	/* a[0] is symtab, a[1] is list of subscripts */
455
{
456
	Cell *x, *y, *z;
457
	char *s;
458
	Node *np;
459
7152
	char *buf;
460
3576
	int bufsz = recsize;
461
3576
	int nsub = strlen(*SUBSEP);
462
463
3576
	if ((buf = (char *) malloc(bufsz)) == NULL)
464
		FATAL("out of memory in array");
465
466
3576
	x = execute(a[0]);	/* Cell* for symbol table */
467
3576
	buf[0] = 0;
468
14304
	for (np = a[1]; np; np = np->nnext) {
469
3576
		y = execute(np);	/* subscript */
470
3576
		s = getsval(y);
471
3576
		if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "array"))
472
			FATAL("out of memory for %s[%s...]", x->nval, buf);
473
3576
		strlcat(buf, s, bufsz);
474
3576
		if (np->nnext)
475
			strlcat(buf, *SUBSEP, bufsz);
476
3930
		tempfree(y);
477
	}
478
3576
	if (!isarr(x)) {
479
		   DPRINTF( ("making %s into an array\n", NN(x->nval)) );
480
		if (freeable(x))
481
			xfree(x->sval);
482
		x->tval &= ~(STR|NUM|DONTFREE);
483
		x->tval |= ARR;
484
		x->sval = (char *) makesymtab(NSYMTAB);
485
	}
486
3576
	z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
487
3576
	z->ctype = OCELL;
488
3576
	z->csub = CVAR;
489
3576
	tempfree(x);
490
3576
	free(buf);
491
3576
	return(z);
492
3576
}
493
494
Cell *awkdelete(Node **a, int n)	/* a[0] is symtab, a[1] is list of subscripts */
495
{
496
	Cell *x, *y;
497
	Node *np;
498
	char *s;
499
	int nsub = strlen(*SUBSEP);
500
501
	x = execute(a[0]);	/* Cell* for symbol table */
502
	if (!isarr(x))
503
		return True;
504
	if (a[1] == 0) {	/* delete the elements, not the table */
505
		freesymtab(x);
506
		x->tval &= ~STR;
507
		x->tval |= ARR;
508
		x->sval = (char *) makesymtab(NSYMTAB);
509
	} else {
510
		int bufsz = recsize;
511
		char *buf;
512
		if ((buf = (char *) malloc(bufsz)) == NULL)
513
			FATAL("out of memory in adelete");
514
		buf[0] = 0;
515
		for (np = a[1]; np; np = np->nnext) {
516
			y = execute(np);	/* subscript */
517
			s = getsval(y);
518
			if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "awkdelete"))
519
				FATAL("out of memory deleting %s[%s...]", x->nval, buf);
520
			strlcat(buf, s, bufsz);
521
			if (np->nnext)
522
				strlcat(buf, *SUBSEP, bufsz);
523
			tempfree(y);
524
		}
525
		freeelem(x, buf);
526
		free(buf);
527
	}
528
	tempfree(x);
529
	return True;
530
}
531
532
Cell *intest(Node **a, int n)	/* a[0] is index (list), a[1] is symtab */
533
{
534
	Cell *x, *ap, *k;
535
	Node *p;
536
	char *buf;
537
	char *s;
538
	int bufsz = recsize;
539
	int nsub = strlen(*SUBSEP);
540
541
	ap = execute(a[1]);	/* array name */
542
	if (!isarr(ap)) {
543
		   DPRINTF( ("making %s into an array\n", ap->nval) );
544
		if (freeable(ap))
545
			xfree(ap->sval);
546
		ap->tval &= ~(STR|NUM|DONTFREE);
547
		ap->tval |= ARR;
548
		ap->sval = (char *) makesymtab(NSYMTAB);
549
	}
550
	if ((buf = (char *) malloc(bufsz)) == NULL) {
551
		FATAL("out of memory in intest");
552
	}
553
	buf[0] = 0;
554
	for (p = a[0]; p; p = p->nnext) {
555
		x = execute(p);	/* expr */
556
		s = getsval(x);
557
		if (!adjbuf(&buf, &bufsz, strlen(buf)+strlen(s)+nsub+1, recsize, 0, "intest"))
558
			FATAL("out of memory deleting %s[%s...]", x->nval, buf);
559
		strlcat(buf, s, bufsz);
560
		tempfree(x);
561
		if (p->nnext)
562
			strlcat(buf, *SUBSEP, bufsz);
563
	}
564
	k = lookup(buf, (Array *) ap->sval);
565
	tempfree(ap);
566
	free(buf);
567
	if (k == NULL)
568
		return(False);
569
	else
570
		return(True);
571
}
572
573
574
Cell *matchop(Node **a, int n)	/* ~ and match() */
575
{
576
	Cell *x, *y;
577
	char *s, *t;
578
	int i;
579
	fa *pfa;
580
	int (*mf)(fa *, const char *) = match, mode = 0;
581
582
81288
	if (n == MATCHFCN) {
583
		mf = pmatch;
584
		mode = 1;
585
1212
	}
586
40644
	x = execute(a[1]);	/* a[1] = target text */
587
40644
	s = getsval(x);
588
40644
	if (a[0] == 0)		/* a[1] == 0: already-compiled reg expr */
589
40644
		i = (*mf)((fa *) a[2], s);
590
	else {
591
		y = execute(a[2]);	/* a[2] = regular expr */
592
		t = getsval(y);
593
		pfa = makedfa(t, mode);
594
		i = (*mf)(pfa, s);
595
		tempfree(y);
596
	}
597
40644
	tempfree(x);
598
40644
	if (n == MATCHFCN) {
599
1212
		int start = patbeg - s + 1;
600
1212
		if (patlen < 0)
601
			start = 0;
602
1212
		setfval(rstartloc, (Awkfloat) start);
603
1212
		setfval(rlengthloc, (Awkfloat) patlen);
604
1212
		x = gettemp();
605
1212
		x->tval = NUM;
606
1212
		x->fval = start;
607
		return x;
608

70118
	} else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
609
9150
		return(True);
610
	else
611
30282
		return(False);
612
40644
}
613
614
615
Cell *boolop(Node **a, int n)	/* a[0] || a[1], a[0] && a[1], !a[0] */
616
{
617
	Cell *x, *y;
618
	int i;
619
620
59678
	x = execute(a[0]);
621
29839
	i = istrue(x);
622
29839
	tempfree(x);
623

29839
	switch (n) {
624
	case BOR:
625
18726
		if (i) return(True);
626
14790
		y = execute(a[1]);
627
14790
		i = istrue(y);
628
14790
		tempfree(y);
629
15824
		if (i) return(True);
630
13756
		else return(False);
631
	case AND:
632
13913
		if ( !i ) return(False);
633
11441
		y = execute(a[1]);
634
11441
		i = istrue(y);
635
11441
		tempfree(y);
636
12806
		if (i) return(True);
637
10076
		else return(False);
638
	case NOT:
639
410
		if (i) return(False);
640
398
		else return(True);
641
	default:	/* can't happen */
642
		FATAL("unknown boolean operator %d", n);
643
	}
644
	return 0;	/*NOTREACHED*/
645
29839
}
646
647
Cell *relop(Node **a, int n)	/* a[0 < a[1], etc. */
648
{
649
	int i;
650
	Cell *x, *y;
651
	Awkfloat j;
652
653
4230324
	x = execute(a[0]);
654
2115162
	y = execute(a[1]);
655

3671797
	if (x->tval&NUM && y->tval&NUM) {
656
1556630
		j = x->fval - y->fval;
657
3701061
		i = j<0? -1: (j>0? 1: 0);
658
1556630
	} else {
659
558532
		i = strcmp(getsval(x), getsval(y));
660
	}
661
3020671
	tempfree(x);
662
2121651
	tempfree(y);
663

2115162
	switch (n) {
664
2205153
	case LT:	if (i<0) return(True);
665
401249
			else return(False);
666
113536
	case LE:	if (i<=0) return(True);
667
2968
			else return(False);
668
1207513
	case NE:	if (i!=0) return(True);
669
84237
			else return(False);
670
115153
	case EQ:	if (i == 0) return(True);
671
77645
			else return(False);
672
5253
	case GE:	if (i>=0) return(True);
673
4073
			else return(False);
674
7454
	case GT:	if (i>0) return(True);
675
6090
			else return(False);
676
	default:	/* can't happen */
677
		FATAL("unknown relational operator %d", n);
678
	}
679
	return 0;	/*NOTREACHED*/
680
2115162
}
681
682
void tfree(Cell *a)	/* free a tempcell */
683
{
684
4435156
	if (freeable(a)) {
685

1170697
		   DPRINTF( ("freeing %s %s %o\n", NN(a->nval), NN(a->sval), a->tval) );
686
2341394
		xfree(a->sval);
687
	}
688
2217578
	if (a == tmps)
689
		FATAL("tempcell list is curdled");
690
2217578
	a->cnext = tmps;
691
2217578
	tmps = a;
692
2217578
}
693
694
Cell *gettemp(void)	/* get a tempcell */
695
{	int i;
696
	Cell *x;
697
698
4435156
	if (!tmps) {
699
139
		tmps = (Cell *) calloc(100, sizeof(Cell));
700
139
		if (!tmps)
701
			FATAL("out of space for temporaries");
702
27800
		for(i = 1; i < 100; i++)
703
13761
			tmps[i-1].cnext = &tmps[i];
704
139
		tmps[i-1].cnext = 0;
705
139
	}
706
2217578
	x = tmps;
707
2217578
	tmps = x->cnext;
708
2217578
	*x = tempcell;
709
2217578
	return(x);
710
}
711
712
Cell *indirect(Node **a, int n)	/* $( a[0] ) */
713
{
714
	Awkfloat val;
715
	Cell *x;
716
	int m;
717
	char *s;
718
719
5197454
	x = execute(a[0]);
720
2598727
	val = getfval(x);	/* freebsd: defend against super large field numbers */
721
2598727
	if ((Awkfloat)INT_MAX < val)
722
		FATAL("trying to access out of range field %s", x->nval);
723
2598727
	m = (int) val;
724

5099761
	if (m == 0 && !is_number(s = getsval(x)))	/* suspicion! */
725
		FATAL("illegal field $(%s), name \"%s\"", s, x->nval);
726
		/* BUG: can x->nval ever be null??? */
727
2598727
	tempfree(x);
728
2598727
	x = fieldadr(m);
729
2598727
	x->ctype = OCELL;	/* BUG?  why are these needed? */
730
2598727
	x->csub = CFLD;
731
2598727
	return(x);
732
}
733
734
Cell *substr(Node **a, int nnn)		/* substr(a[0], a[1], a[2]) */
735
{
736
	int k, m, n;
737
	char *s;
738
	int temp;
739
	Cell *x, *y, *z = 0;
740
741
145024
	x = execute(a[0]);
742
72512
	y = execute(a[1]);
743
72512
	if (a[2] != 0)
744
70499
		z = execute(a[2]);
745
72512
	s = getsval(x);
746
72512
	k = strlen(s) + 1;
747
72512
	if (k <= 1) {
748
2
		tempfree(x);
749
2
		tempfree(y);
750
2
		if (a[2] != 0) {
751
2
			tempfree(z);
752
		}
753
2
		x = gettemp();
754
2
		setsval(x, "");
755
2
		return(x);
756
	}
757
72510
	m = (int) getfval(y);
758
72510
	if (m <= 0)
759
		m = 1;
760
72510
	else if (m > k)
761
		m = k;
762
72510
	tempfree(y);
763
72510
	if (a[2] != 0) {
764
70497
		n = (int) getfval(z);
765
137463
		tempfree(z);
766
	} else
767
2013
		n = k - 1;
768
72510
	if (n < 0)
769
		n = 0;
770
72510
	else if (n > k - m)
771
5
		n = k - m;
772
72510
	   DPRINTF( ("substr: m=%d, n=%d, s=%s\n", m, n, s) );
773
72510
	y = gettemp();
774
72510
	temp = s[n+m-1];	/* with thanks to John Linderman */
775
72510
	s[n+m-1] = '\0';
776
72510
	setsval(y, s + m - 1);
777
72510
	s[n+m-1] = temp;
778
72510
	tempfree(x);
779
72510
	return(y);
780
72512
}
781
782
Cell *sindex(Node **a, int nnn)		/* index(a[0], a[1]) */
783
{
784
	Cell *x, *y, *z;
785
	char *s1, *s2, *p1, *p2, *q;
786
	Awkfloat v = 0.0;
787
788
	x = execute(a[0]);
789
	s1 = getsval(x);
790
	y = execute(a[1]);
791
	s2 = getsval(y);
792
793
	z = gettemp();
794
	for (p1 = s1; *p1 != '\0'; p1++) {
795
		for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
796
			;
797
		if (*p2 == '\0') {
798
			v = (Awkfloat) (p1 - s1 + 1);	/* origin 1 */
799
			break;
800
		}
801
	}
802
	tempfree(x);
803
	tempfree(y);
804
	setfval(z, v);
805
	return(z);
806
}
807
808
#define	MAXNUMSIZE	50
809
810
int format(char **pbuf, int *pbufsize, const char *s, Node *a)	/* printf-like conversions */
811
{
812
287418
	char *fmt;
813
143709
	char *p, *t;
814
	const char *os;
815
	Cell *x;
816
	int flag = 0, n;
817
	int fmtwd; /* format width */
818
143709
	int fmtsz = recsize;
819
143709
	char *buf = *pbuf;
820
143709
	int bufsize = *pbufsize;
821
822
	os = s;
823
143709
	p = buf;
824
143709
	if ((fmt = (char *) malloc(fmtsz)) == NULL)
825
		FATAL("out of memory in format()");
826
1423388
	while (*s) {
827
931320
		adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format1");
828
931320
		if (*s != '%') {
829
726670
			*p++ = *s++;
830
726670
			continue;
831
		}
832
204650
		if (*(s+1) == '%') {
833
			*p++ = '%';
834
			s += 2;
835
			continue;
836
		}
837
		/* have to be real careful in case this is a huge number, eg, %100000d */
838
204650
		fmtwd = atoi(s+1);
839
204650
		if (fmtwd < 0)
840
770
			fmtwd = -fmtwd;
841
204650
		adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format2");
842
853424
		for (t = fmt; (*t++ = *s) != '\0'; s++) {
843
426712
			if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3"))
844
				FATAL("format item %.30s... ran format() out of memory", os);
845


1040662
			if (isalpha((uschar)*s) && *s != 'l' && *s != 'h' && *s != 'L')
846
				break;	/* the ansi panoply */
847
222062
			if (*s == '*') {
848
				if (a == NULL)
849
					FATAL("not enough args in printf(%s)", os);
850
				x = execute(a);
851
				a = a->nnext;
852
				snprintf(t-1, fmt + fmtsz - (t-1), "%d", fmtwd=(int) getfval(x));
853
				if (fmtwd < 0)
854
					fmtwd = -fmtwd;
855
				adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format");
856
				t = fmt + strlen(fmt);
857
				tempfree(x);
858
			}
859
		}
860
204650
		*t = '\0';
861
204650
		if (fmtwd < 0)
862
			fmtwd = -fmtwd;
863
204650
		adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format4");
864
865



204650
		switch (*s) {
866
		case 'f': case 'e': case 'g': case 'E': case 'G':
867
			flag = 'f';
868
			break;
869
		case 'd': case 'i':
870
			flag = 'd';
871
43867
			if(*(s-1) == 'l') break;
872
43867
			*(t-1) = 'l';
873
43867
			*t = 'd';
874
43867
			*++t = '\0';
875
43867
			break;
876
		case 'o': case 'x': case 'X': case 'u':
877
764
			flag = *(s-1) == 'l' ? 'd' : 'u';
878
764
			break;
879
		case 's':
880
			flag = 's';
881
158999
			break;
882
		case 'c':
883
			flag = 'c';
884
1020
			break;
885
		default:
886
			WARNING("weird printf conversion %s", fmt);
887
			flag = '?';
888
			break;
889
		}
890
204650
		if (a == NULL)
891
			FATAL("not enough args in printf(%s)", os);
892
204650
		x = execute(a);
893
204650
		a = a->nnext;
894
		n = MAXNUMSIZE;
895
204650
		if (fmtwd > n)
896
			n = fmtwd;
897
204650
		adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format5");
898

204650
		switch (flag) {
899
		case '?':	/* unknown, so dump it too */
900
			snprintf(p, buf + bufsize - p, "%s", fmt);
901
			t = getsval(x);
902
			n = strlen(t);
903
			if (fmtwd > n)
904
				n = fmtwd;
905
			adjbuf(&buf, &bufsize, 1+strlen(p)+n+p-buf, recsize, &p, "format6");
906
			p += strlen(p);
907
			snprintf(p, buf + bufsize - p, "%s", t);
908
			break;
909
		case 'f':	snprintf(p, buf + bufsize - p, fmt, getfval(x)); break;
910
43867
		case 'd':	snprintf(p, buf + bufsize - p, fmt, (long) getfval(x)); break;
911
764
		case 'u':	snprintf(p, buf + bufsize - p, fmt, (int) getfval(x)); break;
912
		case 's':
913
158999
			t = getsval(x);
914
158999
			n = strlen(t);
915
158999
			if (fmtwd > n)
916
770
				n = fmtwd;
917
158999
			if (!adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format7"))
918
				FATAL("huge string/format (%d chars) in printf %.30s... ran format() out of memory", n, t);
919
158999
			snprintf(p, buf + bufsize - p, fmt, t);
920
158999
			break;
921
		case 'c':
922
1020
			if (isnum(x)) {
923
1020
				if ((int)getfval(x))
924
1020
					snprintf(p, buf + bufsize - p, fmt, (int) getfval(x));
925
				else {
926
					*p++ = '\0'; /* explicit null byte */
927
					*p = '\0';   /* next output will start here */
928
				}
929
			} else
930
				snprintf(p, buf + bufsize - p, fmt, getsval(x)[0]);
931
			break;
932
		default:
933
			FATAL("can't happen: bad conversion %c in format()", flag);
934
		}
935
205544
		tempfree(x);
936
204650
		p += strlen(p);
937
204650
		s++;
938
	}
939
143709
	*p = '\0';
940
143709
	free(fmt);
941
287418
	for ( ; a; a = a->nnext)		/* evaluate any remaining args */
942
		execute(a);
943
143709
	*pbuf = buf;
944
143709
	*pbufsize = bufsize;
945
287418
	return p - buf;
946
143709
}
947
948
Cell *awksprintf(Node **a, int n)		/* sprintf(a[0]) */
949
{
950
	Cell *x;
951
	Node *y;
952
20392
	char *buf;
953
10196
	int bufsz=3*recsize;
954
955
10196
	if ((buf = (char *) malloc(bufsz)) == NULL)
956
		FATAL("out of memory in awksprintf");
957
10196
	y = a[0]->nnext;
958
10196
	x = execute(a[0]);
959
10196
	if (format(&buf, &bufsz, getsval(x), y) == -1)
960
		FATAL("sprintf string %.30s... too long.  can't happen.", buf);
961
10196
	tempfree(x);
962
10196
	x = gettemp();
963
10196
	x->sval = buf;
964
10196
	x->tval = STR;
965
10196
	return(x);
966
10196
}
967
968
Cell *awkprintf(Node **a, int n)		/* printf */
969
{	/* a[0] is list of args, starting with format string */
970
	/* a[1] is redirection operator, a[2] is redirection file */
971
	FILE *fp;
972
	Cell *x;
973
	Node *y;
974
267026
	char *buf;
975
	int len;
976
133513
	int bufsz=3*recsize;
977
978
133513
	if ((buf = (char *) malloc(bufsz)) == NULL)
979
		FATAL("out of memory in awkprintf");
980
133513
	y = a[0]->nnext;
981
133513
	x = execute(a[0]);
982
133513
	if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
983
		FATAL("printf string %.30s... too long.  can't happen.", buf);
984
133513
	tempfree(x);
985
133513
	if (a[1] == NULL) {
986
		/* fputs(buf, stdout); */
987
133513
		fwrite(buf, len, 1, stdout);
988

267026
		if (ferror(stdout))
989
			FATAL("write error on stdout");
990
	} else {
991
		fp = redirect(ptoi(a[1]), a[2]);
992
		/* fputs(buf, fp); */
993
		fwrite(buf, len, 1, fp);
994
		fflush(fp);
995
		if (ferror(fp))
996
			FATAL("write error on %s", filename(fp));
997
	}
998
133513
	free(buf);
999
267026
	return(True);
1000
133513
}
1001
1002
Cell *arith(Node **a, int n)	/* a[0] + a[1], etc.  also -a[0] */
1003
{
1004
	Awkfloat i, j = 0;
1005
338664
	double v;
1006
	Cell *x, *y, *z;
1007
1008
169332
	x = execute(a[0]);
1009
169332
	i = getfval(x);
1010
182445
	tempfree(x);
1011
169332
	if (n != UMINUS) {
1012
168492
		y = execute(a[1]);
1013
168492
		j = getfval(y);
1014
179625
		tempfree(y);
1015
	}
1016
169332
	z = gettemp();
1017


169332
	switch (n) {
1018
	case ADD:
1019
25765
		i += j;
1020
25765
		break;
1021
	case MINUS:
1022
2146
		i -= j;
1023
2146
		break;
1024
	case MULT:
1025
1911
		i *= j;
1026
1911
		break;
1027
	case DIVIDE:
1028
		if (j == 0)
1029
			FATAL("division by zero");
1030
		i /= j;
1031
		break;
1032
	case MOD:
1033
138670
		if (j == 0)
1034
			FATAL("division by zero in mod");
1035
138670
		modf(i/j, &v);
1036
138670
		i = i - j * v;
1037
138670
		break;
1038
	case UMINUS:
1039
840
		i = -i;
1040
840
		break;
1041
	case POWER:
1042
		if (j >= 0 && modf(j, &v) == 0.0)	/* pos integer exponent */
1043
			i = ipow(i, (int) j);
1044
		else
1045
			i = errcheck(pow(i, j), "pow");
1046
		break;
1047
	default:	/* can't happen */
1048
		FATAL("illegal arithmetic operator %d", n);
1049
	}
1050
169332
	setfval(z, i);
1051
169332
	return(z);
1052
169332
}
1053
1054
double ipow(double x, int n)	/* x**n.  ought to be done by pow, but isn't always */
1055
{
1056
	double v;
1057
1058
	if (n <= 0)
1059
		return 1;
1060
	v = ipow(x, n/2);
1061
	if (n % 2 == 0)
1062
		return v * v;
1063
	else
1064
		return x * v * v;
1065
}
1066
1067
Cell *incrdecr(Node **a, int n)		/* a[0]++, etc. */
1068
{
1069
	Cell *x, *z;
1070
	int k;
1071
	Awkfloat xf;
1072
1073
2078418
	x = execute(a[0]);
1074
1039209
	xf = getfval(x);
1075
1039209
	k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
1076
1039209
	if (n == PREINCR || n == PREDECR) {
1077
175788
		setfval(x, xf + k);
1078
175788
		return(x);
1079
	}
1080
863421
	z = gettemp();
1081
863421
	setfval(z, xf);
1082
863421
	setfval(x, xf + k);
1083
863421
	tempfree(x);
1084
863421
	return(z);
1085
1039209
}
1086
1087
Cell *assign(Node **a, int n)	/* a[0] = a[1], a[0] += a[1], etc. */
1088
{		/* this is subtle; don't muck with it. */
1089
	Cell *x, *y;
1090
	Awkfloat xf, yf;
1091
1262452
	double v;
1092
1093
631226
	y = execute(a[1]);
1094
631226
	x = execute(a[0]);
1095
631226
	if (n == ASSIGN) {	/* ordinary assignment */
1096

620933
		if (x == y && !(x->tval & (FLD|REC)))	/* self-assignment: */
1097
			;		/* leave alone unless it's a field */
1098
620933
		else if ((y->tval & (STR|NUM)) == (STR|NUM)) {
1099
406834
			setsval(x, getsval(y));
1100
406834
			x->fval = getfval(y);
1101
406834
			x->tval |= NUM;
1102
406834
		}
1103
214099
		else if (isstr(y))
1104
196176
			setsval(x, getsval(y));
1105
17923
		else if (isnum(y))
1106
17923
			setfval(x, getfval(y));
1107
		else
1108
			funnyvar(y, "read value of");
1109
816834
		tempfree(y);
1110
620933
		return(x);
1111
	}
1112
10293
	xf = getfval(x);
1113
10293
	yf = getfval(y);
1114

10293
	switch (n) {
1115
	case ADDEQ:
1116
10293
		xf += yf;
1117
10293
		break;
1118
	case SUBEQ:
1119
		xf -= yf;
1120
		break;
1121
	case MULTEQ:
1122
		xf *= yf;
1123
		break;
1124
	case DIVEQ:
1125
		if (yf == 0)
1126
			FATAL("division by zero in /=");
1127
		xf /= yf;
1128
		break;
1129
	case MODEQ:
1130
		if (yf == 0)
1131
			FATAL("division by zero in %%=");
1132
		modf(xf/yf, &v);
1133
		xf = xf - yf * v;
1134
		break;
1135
	case POWEQ:
1136
		if (yf >= 0 && modf(yf, &v) == 0.0)	/* pos integer exponent */
1137
			xf = ipow(xf, (int) yf);
1138
		else
1139
			xf = errcheck(pow(xf, yf), "pow");
1140
		break;
1141
	default:
1142
		FATAL("illegal assignment operator %d", n);
1143
		break;
1144
	}
1145
10601
	tempfree(y);
1146
10293
	setfval(x, xf);
1147
10293
	return(x);
1148
631226
}
1149
1150
Cell *cat(Node **a, int q)	/* a[0] cat a[1] */
1151
{
1152
	Cell *x, *y, *z;
1153
	int n1, n2;
1154
	char *s;
1155
	size_t len;
1156
1157
1190770
	x = execute(a[0]);
1158
595385
	y = execute(a[1]);
1159
595385
	getsval(x);
1160
595385
	getsval(y);
1161
595385
	n1 = strlen(x->sval);
1162
595385
	n2 = strlen(y->sval);
1163
595385
	len = n1 + n2 + 1;
1164
595385
	s = (char *) malloc(len);
1165
595385
	if (s == NULL)
1166
		FATAL("out of space concatenating %.15s... and %.15s...",
1167
			x->sval, y->sval);
1168
595385
	strlcpy(s, x->sval, len);
1169
595385
	strlcpy(s+n1, y->sval, len - n1);
1170
600979
	tempfree(x);
1171
604331
	tempfree(y);
1172
595385
	z = gettemp();
1173
595385
	z->sval = s;
1174
595385
	z->tval = STR;
1175
595385
	return(z);
1176
}
1177
1178
Cell *pastat(Node **a, int n)	/* a[0] { a[1] } */
1179
{
1180
	Cell *x;
1181
1182
2081714
	if (a[0] == 0)
1183
90261
		x = execute(a[1]);
1184
	else {
1185
950596
		x = execute(a[0]);
1186
950596
		if (istrue(x)) {
1187
473678
			tempfree(x);
1188
473678
			x = execute(a[1]);
1189
473678
		}
1190
	}
1191
1040805
	return x;
1192
}
1193
1194
Cell *dopa2(Node **a, int n)	/* a[0], a[1] { a[2] } */
1195
{
1196
	Cell *x;
1197
	int pair;
1198
1199
	pair = ptoi(a[3]);
1200
	if (pairstack[pair] == 0) {
1201
		x = execute(a[0]);
1202
		if (istrue(x))
1203
			pairstack[pair] = 1;
1204
		tempfree(x);
1205
	}
1206
	if (pairstack[pair] == 1) {
1207
		x = execute(a[1]);
1208
		if (istrue(x))
1209
			pairstack[pair] = 0;
1210
		tempfree(x);
1211
		x = execute(a[2]);
1212
		return(x);
1213
	}
1214
	return(False);
1215
}
1216
1217
Cell *split(Node **a, int nnn)	/* split(a[0], a[1], a[2]); a[3] is type */
1218
{
1219
	Cell *x = 0, *y, *ap;
1220
	char *s;
1221
	int sep;
1222
	char *t, temp, num[50], *fs = 0;
1223
	int n, tempstat, arg3type;
1224
1225
	y = execute(a[0]);	/* source string */
1226
	s = getsval(y);
1227
	arg3type = ptoi(a[3]);
1228
	if (a[2] == 0)		/* fs string */
1229
		fs = *FS;
1230
	else if (arg3type == STRING) {	/* split(str,arr,"string") */
1231
		x = execute(a[2]);
1232
		fs = getsval(x);
1233
	} else if (arg3type == REGEXPR)
1234
		fs = "(regexpr)";	/* split(str,arr,/regexpr/) */
1235
	else
1236
		FATAL("illegal type of split");
1237
	sep = *fs;
1238
	ap = execute(a[1]);	/* array name */
1239
	freesymtab(ap);
1240
	   DPRINTF( ("split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs) );
1241
	ap->tval &= ~STR;
1242
	ap->tval |= ARR;
1243
	ap->sval = (char *) makesymtab(NSYMTAB);
1244
1245
	n = 0;
1246
        if (arg3type == REGEXPR && strlen((char*)((fa*)a[2])->restr) == 0) {
1247
		/* split(s, a, //); have to arrange that it looks like empty sep */
1248
		arg3type = 0;
1249
		fs = "";
1250
		sep = 0;
1251
	}
1252
	if (*s != '\0' && (strlen(fs) > 1 || arg3type == REGEXPR)) {	/* reg expr */
1253
		fa *pfa;
1254
		if (arg3type == REGEXPR) {	/* it's ready already */
1255
			pfa = (fa *) a[2];
1256
		} else {
1257
			pfa = makedfa(fs, 1);
1258
		}
1259
		if (nematch(pfa,s)) {
1260
			tempstat = pfa->initstat;
1261
			pfa->initstat = 2;
1262
			do {
1263
				n++;
1264
				snprintf(num, sizeof num, "%d", n);
1265
				temp = *patbeg;
1266
				*patbeg = '\0';
1267
				if (is_number(s))
1268
					setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
1269
				else
1270
					setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1271
				*patbeg = temp;
1272
				s = patbeg + patlen;
1273
				if (*(patbeg+patlen-1) == 0 || *s == 0) {
1274
					n++;
1275
					snprintf(num, sizeof num, "%d", n);
1276
					setsymtab(num, "", 0.0, STR, (Array *) ap->sval);
1277
					pfa->initstat = tempstat;
1278
					goto spdone;
1279
				}
1280
			} while (nematch(pfa,s));
1281
			pfa->initstat = tempstat; 	/* bwk: has to be here to reset */
1282
							/* cf gsub and refldbld */
1283
		}
1284
		n++;
1285
		snprintf(num, sizeof num, "%d", n);
1286
		if (is_number(s))
1287
			setsymtab(num, s, atof(s), STR|NUM, (Array *) ap->sval);
1288
		else
1289
			setsymtab(num, s, 0.0, STR, (Array *) ap->sval);
1290
  spdone:
1291
		pfa = NULL;
1292
	} else if (sep == ' ') {
1293
		for (n = 0; ; ) {
1294
			while (*s == ' ' || *s == '\t' || *s == '\n')
1295
				s++;
1296
			if (*s == 0)
1297
				break;
1298
			n++;
1299
			t = s;
1300
			do
1301
				s++;
1302
			while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
1303
			temp = *s;
1304
			*s = '\0';
1305
			snprintf(num, sizeof num, "%d", n);
1306
			if (is_number(t))
1307
				setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1308
			else
1309
				setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1310
			*s = temp;
1311
			if (*s != 0)
1312
				s++;
1313
		}
1314
	} else if (sep == 0) {	/* new: split(s, a, "") => 1 char/elem */
1315
		for (n = 0; *s != 0; s++) {
1316
			char buf[2];
1317
			n++;
1318
			snprintf(num, sizeof num, "%d", n);
1319
			buf[0] = *s;
1320
			buf[1] = 0;
1321
			if (isdigit((uschar)buf[0]))
1322
				setsymtab(num, buf, atof(buf), STR|NUM, (Array *) ap->sval);
1323
			else
1324
				setsymtab(num, buf, 0.0, STR, (Array *) ap->sval);
1325
		}
1326
	} else if (*s != 0) {
1327
		for (;;) {
1328
			n++;
1329
			t = s;
1330
			while (*s != sep && *s != '\n' && *s != '\0')
1331
				s++;
1332
			temp = *s;
1333
			*s = '\0';
1334
			snprintf(num, sizeof num, "%d", n);
1335
			if (is_number(t))
1336
				setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1337
			else
1338
				setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1339
			*s = temp;
1340
			if (*s++ == 0)
1341
				break;
1342
		}
1343
	}
1344
	tempfree(ap);
1345
	tempfree(y);
1346
	if (a[2] != 0 && arg3type == STRING) {
1347
		tempfree(x);
1348
	}
1349
	x = gettemp();
1350
	x->tval = NUM;
1351
	x->fval = n;
1352
	return(x);
1353
}
1354
1355
Cell *condexpr(Node **a, int n)	/* a[0] ? a[1] : a[2] */
1356
{
1357
	Cell *x;
1358
1359
88
	x = execute(a[0]);
1360
44
	if (istrue(x)) {
1361
4
		tempfree(x);
1362
4
		x = execute(a[1]);
1363
4
	} else {
1364
40
		tempfree(x);
1365
40
		x = execute(a[2]);
1366
	}
1367
44
	return(x);
1368
}
1369
1370
Cell *ifstat(Node **a, int n)	/* if (a[0]) a[1]; else a[2] */
1371
{
1372
	Cell *x;
1373
1374
340734
	x = execute(a[0]);
1375
170367
	if (istrue(x)) {
1376
88145
		tempfree(x);
1377
88145
		x = execute(a[1]);
1378
170367
	} else if (a[2] != 0) {
1379
44513
		tempfree(x);
1380
44513
		x = execute(a[2]);
1381
44513
	}
1382
170336
	return(x);
1383
}
1384
1385
Cell *whilestat(Node **a, int n)	/* while (a[0]) a[1] */
1386
{
1387
	Cell *x;
1388
1389
349536
	for (;;) {
1390
349532
		x = execute(a[0]);
1391
349532
		if (!istrue(x))
1392
4
			return(x);
1393
349528
		tempfree(x);
1394
349528
		x = execute(a[1]);
1395
349528
		if (isbreak(x)) {
1396
			x = True;
1397
			return(x);
1398
		}
1399


1398112
		if (isnext(x) || isexit(x) || isret(x))
1400
			return(x);
1401
349528
		tempfree(x);
1402
	}
1403
4
}
1404
1405
Cell *dostat(Node **a, int n)	/* do a[0]; while(a[1]) */
1406
{
1407
	Cell *x;
1408
1409
	for (;;) {
1410
		x = execute(a[0]);
1411
		if (isbreak(x))
1412
			return True;
1413
		if (isnext(x) || isexit(x) || isret(x))
1414
			return(x);
1415
		tempfree(x);
1416
		x = execute(a[1]);
1417
		if (!istrue(x))
1418
			return(x);
1419
		tempfree(x);
1420
	}
1421
}
1422
1423
Cell *forstat(Node **a, int n)	/* for (a[0]; a[1]; a[2]) a[3] */
1424
{
1425
	Cell *x;
1426
1427
5408
	x = execute(a[0]);
1428
2704
	tempfree(x);
1429
618392
	for (;;) {
1430
618392
		if (a[1]!=0) {
1431
618392
			x = execute(a[1]);
1432
620288
			if (!istrue(x)) return(x);
1433
616496
			else tempfree(x);
1434
		}
1435
616496
		x = execute(a[3]);
1436
616496
		if (isbreak(x))		/* turn off break */
1437
808
			return True;
1438


2462752
		if (isnext(x) || isexit(x) || isret(x))
1439
			return(x);
1440
616290
		tempfree(x);
1441
615688
		x = execute(a[2]);
1442
1116546
		tempfree(x);
1443
	}
1444
2704
}
1445
1446
Cell *instat(Node **a, int n)	/* for (a[0] in a[1]) a[2] */
1447
{
1448
	Cell *x, *vp, *arrayp, *cp, *ncp;
1449
	Array *tp;
1450
	int i;
1451
1452
	vp = execute(a[0]);
1453
	arrayp = execute(a[1]);
1454
	if (!isarr(arrayp)) {
1455
		return True;
1456
	}
1457
	tp = (Array *) arrayp->sval;
1458
	tempfree(arrayp);
1459
	for (i = 0; i < tp->size; i++) {	/* this routine knows too much */
1460
		for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1461
			setsval(vp, cp->nval);
1462
			ncp = cp->cnext;
1463
			x = execute(a[2]);
1464
			if (isbreak(x)) {
1465
				tempfree(vp);
1466
				return True;
1467
			}
1468
			if (isnext(x) || isexit(x) || isret(x)) {
1469
				tempfree(vp);
1470
				return(x);
1471
			}
1472
			tempfree(x);
1473
		}
1474
	}
1475
	return True;
1476
}
1477
1478
Cell *bltin(Node **a, int n)	/* builtin functions. a[0] is type, a[1] is arg list */
1479
{
1480
	Cell *x, *y;
1481
985768
	Awkfloat u;
1482
	int t;
1483
	Awkfloat tmp;
1484
	char *p, *buf;
1485
	Node *nextarg;
1486
	FILE *fp;
1487
1488
492884
	t = ptoi(a[0]);
1489
492884
	x = execute(a[1]);
1490
492884
	nextarg = a[1]->nnext;
1491





492884
	switch (t) {
1492
	case FLENGTH:
1493
12884
		if (isarr(x))
1494
			u = ((Array *) x->sval)->nelem;	/* GROT.  should be function*/
1495
		else
1496
12884
			u = strlen(getsval(x));
1497
		break;
1498
	case FLOG:
1499
		u = errcheck(log(getfval(x)), "log"); break;
1500
	case FINT:
1501
		modf(getfval(x), &u); break;
1502
	case FEXP:
1503
		u = errcheck(exp(getfval(x)), "exp"); break;
1504
	case FSQRT:
1505
		u = errcheck(sqrt(getfval(x)), "sqrt"); break;
1506
	case FSIN:
1507
		u = sin(getfval(x)); break;
1508
	case FCOS:
1509
		u = cos(getfval(x)); break;
1510
	case FATAN:
1511
		if (nextarg == 0) {
1512
			WARNING("atan2 requires two arguments; returning 1.0");
1513
			u = 1.0;
1514
		} else {
1515
			y = execute(a[1]->nnext);
1516
			u = atan2(getfval(x), getfval(y));
1517
			tempfree(y);
1518
			nextarg = nextarg->nnext;
1519
		}
1520
		break;
1521
	case FCOMPL:
1522
		u = ~((int)getfval(x));
1523
		break;
1524
	case FAND:
1525
		if (nextarg == 0) {
1526
			WARNING("and requires two arguments; returning 0");
1527
			u = 0;
1528
			break;
1529
		}
1530
		y = execute(a[1]->nnext);
1531
		u = ((int)getfval(x)) & ((int)getfval(y));
1532
		tempfree(y);
1533
		nextarg = nextarg->nnext;
1534
		break;
1535
	case FFOR:
1536
		if (nextarg == 0) {
1537
			WARNING("or requires two arguments; returning 0");
1538
			u = 0;
1539
			break;
1540
		}
1541
		y = execute(a[1]->nnext);
1542
		u = ((int)getfval(x)) | ((int)getfval(y));
1543
		tempfree(y);
1544
		nextarg = nextarg->nnext;
1545
		break;
1546
	case FXOR:
1547
		if (nextarg == 0) {
1548
			WARNING("xor requires two arguments; returning 0");
1549
			u = 0;
1550
			break;
1551
		}
1552
		y = execute(a[1]->nnext);
1553
		u = ((int)getfval(x)) ^ ((int)getfval(y));
1554
		tempfree(y);
1555
		nextarg = nextarg->nnext;
1556
		break;
1557
	case FLSHIFT:
1558
		if (nextarg == 0) {
1559
			WARNING("lshift requires two arguments; returning 0");
1560
			u = 0;
1561
			break;
1562
		}
1563
		y = execute(a[1]->nnext);
1564
		u = ((int)getfval(x)) << ((int)getfval(y));
1565
		tempfree(y);
1566
		nextarg = nextarg->nnext;
1567
		break;
1568
	case FRSHIFT:
1569
		if (nextarg == 0) {
1570
			WARNING("rshift requires two arguments; returning 0");
1571
			u = 0;
1572
			break;
1573
		}
1574
		y = execute(a[1]->nnext);
1575
		u = ((int)getfval(x)) >> ((int)getfval(y));
1576
		tempfree(y);
1577
		nextarg = nextarg->nnext;
1578
		break;
1579
	case FSYSTEM:
1580
		fflush(stdout);		/* in case something is buffered already */
1581
		u = (Awkfloat) system(getsval(x)) / 256;   /* 256 is unix-dep */
1582
		break;
1583
	case FRAND:
1584
480000
		u = (Awkfloat) (random() & RAND_MAX) / ((u_int)RAND_MAX + 1);
1585
480000
		break;
1586
	case FSRAND:
1587
		if (isrec(x)) {		/* no argument provided */
1588
			u = time(NULL);
1589
			tmp = u;
1590
			srandom((unsigned int) u);
1591
		} else {
1592
			u = getfval(x);
1593
			tmp = u;
1594
			srandom_deterministic((unsigned int) u);
1595
		}
1596
		u = srand_seed;
1597
		srand_seed = tmp;
1598
		break;
1599
	case FTOUPPER:
1600
	case FTOLOWER:
1601
		buf = tostring(getsval(x));
1602
		if (t == FTOUPPER) {
1603
			for (p = buf; *p; p++)
1604
				if (islower((uschar) *p))
1605
					*p = toupper((uschar)*p);
1606
		} else {
1607
			for (p = buf; *p; p++)
1608
				if (isupper((uschar) *p))
1609
					*p = tolower((uschar)*p);
1610
		}
1611
		tempfree(x);
1612
		x = gettemp();
1613
		setsval(x, buf);
1614
		free(buf);
1615
		return x;
1616
	case FFLUSH:
1617
		if (isrec(x) || strlen(getsval(x)) == 0) {
1618
			flush_all();	/* fflush() or fflush("") -> all */
1619
			u = 0;
1620
		} else if ((fp = openfile(FFLUSH, getsval(x))) == NULL)
1621
			u = EOF;
1622
		else
1623
			u = fflush(fp);
1624
		break;
1625
	default:	/* can't happen */
1626
		FATAL("illegal function type %d", t);
1627
		break;
1628
	}
1629
492884
	tempfree(x);
1630
492884
	x = gettemp();
1631
492884
	setfval(x, u);
1632
492884
	if (nextarg != 0) {
1633
		WARNING("warning: function has too many arguments");
1634
		for ( ; nextarg; nextarg = nextarg->nnext)
1635
			execute(nextarg);
1636
	}
1637
492884
	return(x);
1638
492884
}
1639
1640
Cell *printstat(Node **a, int n)	/* print a[0] */
1641
{
1642
	Node *x;
1643
	Cell *y;
1644
	FILE *fp;
1645
1646
4139244
	if (a[1] == 0)	/* a[1] is redirection operator, a[2] is file */
1647
628765
		fp = stdout;
1648
	else
1649
1440857
		fp = redirect(ptoi(a[1]), a[2]);
1650
8298088
	for (x = a[0]; x != NULL; x = x->nnext) {
1651
2079422
		y = execute(x);
1652
2079422
		fputs(getpssval(y), fp);
1653
2561179
		tempfree(y);
1654
2079422
		if (x->nnext == NULL)
1655
2069622
			fputs(*ORS, fp);
1656
		else
1657
9800
			fputs(*OFS, fp);
1658
	}
1659
2069622
	if (a[1] != 0)
1660
1440857
		fflush(fp);
1661

4139244
	if (ferror(fp))
1662
		FATAL("write error on %s", filename(fp));
1663
2069622
	return(True);
1664
}
1665
1666
Cell *nullproc(Node **a, int n)
1667
{
1668
	n = n;
1669
	a = a;
1670
	return 0;
1671
}
1672
1673
1674
FILE *redirect(int a, Node *b)	/* set up all i/o redirections */
1675
{
1676
	FILE *fp;
1677
	Cell *x;
1678
	char *fname;
1679
1680
2881714
	x = execute(b);
1681
1440857
	fname = getsval(x);
1682
1440857
	fp = openfile(a, fname);
1683
1440857
	if (fp == NULL)
1684
		FATAL("can't open file %s", fname);
1685
1440857
	tempfree(x);
1686
1440857
	return fp;
1687
}
1688
1689
struct files {
1690
	FILE	*fp;
1691
	const char	*fname;
1692
	int	mode;	/* '|', 'a', 'w' => LE/LT, GT */
1693
} *files;
1694
1695
int nfiles;
1696
1697
void stdinit(void)	/* in case stdin, etc., are not constants */
1698
{
1699
974
	nfiles = FOPEN_MAX;
1700
487
	files = calloc(nfiles, sizeof(*files));
1701
487
	if (files == NULL)
1702
		FATAL("can't allocate file memory for %u files", nfiles);
1703
487
        files[0].fp = stdin;
1704
487
	files[0].fname = "/dev/stdin";
1705
487
	files[0].mode = LT;
1706
487
        files[1].fp = stdout;
1707
487
	files[1].fname = "/dev/stdout";
1708
487
	files[1].mode = GT;
1709
487
        files[2].fp = stderr;
1710
487
	files[2].fname = "/dev/stderr";
1711
487
	files[2].mode = GT;
1712
487
}
1713
1714
FILE *openfile(int a, const char *us)
1715
{
1716
	const char *s = us;
1717
	int i, m;
1718
	FILE *fp = 0;
1719
1720
2881714
	if (*s == '\0')
1721
		FATAL("null file name in print or getline");
1722
11537624
	for (i=0; i < nfiles; i++)
1723

11537104
		if (files[i].fname && strcmp(s, files[i].fname) == 0) {
1724

1440829
			if (a == files[i].mode || (a==APPEND && files[i].mode==GT))
1725
1440829
				return files[i].fp;
1726
			if (a == FFLUSH)
1727
				return files[i].fp;
1728
		}
1729
28
	if (a == FFLUSH)	/* didn't find it, so don't create it! */
1730
		return NULL;
1731
1732
248
	for (i=0; i < nfiles; i++)
1733
124
		if (files[i].fp == 0)
1734
			break;
1735
28
	if (i >= nfiles) {
1736
		struct files *nf;
1737
		int nnf = nfiles + FOPEN_MAX;
1738
		nf = reallocarray(files, nnf, sizeof(*nf));
1739
		if (nf == NULL)
1740
			FATAL("cannot grow files for %s and %d files", s, nnf);
1741
		memset(&nf[nfiles], 0, FOPEN_MAX * sizeof(*nf));
1742
		nfiles = nnf;
1743
		files = nf;
1744
	}
1745
28
	fflush(stdout);	/* force a semblance of order */
1746
	m = a;
1747
28
	if (a == GT) {
1748
28
		fp = fopen(s, "w");
1749
28
	} else if (a == APPEND) {
1750
		fp = fopen(s, "a");
1751
		m = GT;	/* so can mix > and >> */
1752
	} else if (a == '|') {	/* output pipe */
1753
		fp = popen(s, "w");
1754
	} else if (a == LE) {	/* input pipe */
1755
		fp = popen(s, "r");
1756
	} else if (a == LT) {	/* getline <file */
1757
		fp = strcmp(s, "-") == 0 ? stdin : fopen(s, "r");	/* "-" is stdin */
1758
	} else	/* can't happen */
1759
		FATAL("illegal redirection %d", a);
1760
28
	if (fp != NULL) {
1761
28
		files[i].fname = tostring(s);
1762
28
		files[i].fp = fp;
1763
28
		files[i].mode = m;
1764
28
	}
1765
28
	return fp;
1766
1440857
}
1767
1768
const char *filename(FILE *fp)
1769
{
1770
	int i;
1771
1772
	for (i = 0; i < nfiles; i++)
1773
		if (fp == files[i].fp)
1774
			return files[i].fname;
1775
	return "???";
1776
}
1777
1778
Cell *closefile(Node **a, int n)
1779
{
1780
	Cell *x;
1781
	int i, stat;
1782
1783
	n = n;
1784
	x = execute(a[0]);
1785
	getsval(x);
1786
	stat = -1;
1787
	for (i = 0; i < nfiles; i++) {
1788
		if (files[i].fname && strcmp(x->sval, files[i].fname) == 0) {
1789
			if (ferror(files[i].fp))
1790
				WARNING( "i/o error occurred on %s", files[i].fname );
1791
			if (files[i].mode == '|' || files[i].mode == LE)
1792
				stat = pclose(files[i].fp);
1793
			else
1794
				stat = fclose(files[i].fp);
1795
			if (stat == EOF)
1796
				WARNING( "i/o error occurred closing %s", files[i].fname );
1797
			if (i > 2)	/* don't do /dev/std... */
1798
				xfree(files[i].fname);
1799
			files[i].fname = NULL;	/* watch out for ref thru this */
1800
			files[i].fp = NULL;
1801
		}
1802
	}
1803
	tempfree(x);
1804
	x = gettemp();
1805
	setfval(x, (Awkfloat) stat);
1806
	return(x);
1807
}
1808
1809
void closeall(void)
1810
{
1811
	int i, stat;
1812
1813
20941
	for (i = 0; i < FOPEN_MAX; i++) {
1814
9740
		if (files[i].fp) {
1815

2978
			if (ferror(files[i].fp))
1816
				WARNING( "i/o error occurred on %s", files[i].fname );
1817

2978
			if (files[i].mode == '|' || files[i].mode == LE)
1818
				stat = pclose(files[i].fp);
1819
			else
1820
1489
				stat = fclose(files[i].fp);
1821
1489
			if (stat == EOF)
1822
				WARNING( "i/o error occurred while closing %s", files[i].fname );
1823
		}
1824
	}
1825
487
}
1826
1827
void flush_all(void)
1828
{
1829
	int i;
1830
1831
	for (i = 0; i < nfiles; i++)
1832
		if (files[i].fp)
1833
			fflush(files[i].fp);
1834
}
1835
1836
void backsub(char **pb_ptr, char **sptr_ptr);
1837
1838
Cell *sub(Node **a, int nnn)	/* substitute command */
1839
{
1840
	char *sptr, *pb, *q;
1841
	Cell *x, *y, *result;
1842
	char *t, *buf;
1843
	fa *pfa;
1844
	int bufsz = recsize;
1845
1846
	if ((buf = (char *) malloc(bufsz)) == NULL)
1847
		FATAL("out of memory in sub");
1848
	x = execute(a[3]);	/* target string */
1849
	t = getsval(x);
1850
	if (a[0] == 0)		/* 0 => a[1] is already-compiled regexpr */
1851
		pfa = (fa *) a[1];	/* regular expression */
1852
	else {
1853
		y = execute(a[1]);
1854
		pfa = makedfa(getsval(y), 1);
1855
		tempfree(y);
1856
	}
1857
	y = execute(a[2]);	/* replacement string */
1858
	result = False;
1859
	if (pmatch(pfa, t)) {
1860
		sptr = t;
1861
		adjbuf(&buf, &bufsz, 1+patbeg-sptr, recsize, 0, "sub");
1862
		pb = buf;
1863
		while (sptr < patbeg)
1864
			*pb++ = *sptr++;
1865
		sptr = getsval(y);
1866
		while (*sptr != 0) {
1867
			adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "sub");
1868
			if (*sptr == '\\') {
1869
				backsub(&pb, &sptr);
1870
			} else if (*sptr == '&') {
1871
				sptr++;
1872
				adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "sub");
1873
				for (q = patbeg; q < patbeg+patlen; )
1874
					*pb++ = *q++;
1875
			} else
1876
				*pb++ = *sptr++;
1877
		}
1878
		*pb = '\0';
1879
		if (pb > buf + bufsz)
1880
			FATAL("sub result1 %.30s too big; can't happen", buf);
1881
		sptr = patbeg + patlen;
1882
		if ((patlen == 0 && *patbeg) || (patlen && *(sptr-1))) {
1883
			adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "sub");
1884
			while ((*pb++ = *sptr++) != 0)
1885
				;
1886
		}
1887
		if (pb > buf + bufsz)
1888
			FATAL("sub result2 %.30s too big; can't happen", buf);
1889
		setsval(x, buf);	/* BUG: should be able to avoid copy */
1890
		result = True;
1891
	}
1892
	tempfree(x);
1893
	tempfree(y);
1894
	free(buf);
1895
	return result;
1896
}
1897
1898
Cell *gsub(Node **a, int nnn)	/* global substitute */
1899
{
1900
	Cell *x, *y;
1901
	char *rptr, *sptr, *t, *pb, *q;
1902
	char *buf;
1903
	fa *pfa;
1904
	int mflag, tempstat, num;
1905
	int bufsz = recsize;
1906
1907
	if ((buf = (char *) malloc(bufsz)) == NULL)
1908
		FATAL("out of memory in gsub");
1909
	mflag = 0;	/* if mflag == 0, can replace empty string */
1910
	num = 0;
1911
	x = execute(a[3]);	/* target string */
1912
	t = getsval(x);
1913
	if (a[0] == 0)		/* 0 => a[1] is already-compiled regexpr */
1914
		pfa = (fa *) a[1];	/* regular expression */
1915
	else {
1916
		y = execute(a[1]);
1917
		pfa = makedfa(getsval(y), 1);
1918
		tempfree(y);
1919
	}
1920
	y = execute(a[2]);	/* replacement string */
1921
	if (pmatch(pfa, t)) {
1922
		tempstat = pfa->initstat;
1923
		pfa->initstat = 2;
1924
		pb = buf;
1925
		rptr = getsval(y);
1926
		do {
1927
			if (patlen == 0 && *patbeg != 0) {	/* matched empty string */
1928
				if (mflag == 0) {	/* can replace empty */
1929
					num++;
1930
					sptr = rptr;
1931
					while (*sptr != 0) {
1932
						adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1933
						if (*sptr == '\\') {
1934
							backsub(&pb, &sptr);
1935
						} else if (*sptr == '&') {
1936
							sptr++;
1937
							adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1938
							for (q = patbeg; q < patbeg+patlen; )
1939
								*pb++ = *q++;
1940
						} else
1941
							*pb++ = *sptr++;
1942
					}
1943
				}
1944
				if (*t == 0)	/* at end */
1945
					goto done;
1946
				adjbuf(&buf, &bufsz, 2+pb-buf, recsize, &pb, "gsub");
1947
				*pb++ = *t++;
1948
				if (pb > buf + bufsz)	/* BUG: not sure of this test */
1949
					FATAL("gsub result0 %.30s too big; can't happen", buf);
1950
				mflag = 0;
1951
			}
1952
			else {	/* matched nonempty string */
1953
				num++;
1954
				sptr = t;
1955
				adjbuf(&buf, &bufsz, 1+(patbeg-sptr)+pb-buf, recsize, &pb, "gsub");
1956
				while (sptr < patbeg)
1957
					*pb++ = *sptr++;
1958
				sptr = rptr;
1959
				while (*sptr != 0) {
1960
					adjbuf(&buf, &bufsz, 5+pb-buf, recsize, &pb, "gsub");
1961
					if (*sptr == '\\') {
1962
						backsub(&pb, &sptr);
1963
					} else if (*sptr == '&') {
1964
						sptr++;
1965
						adjbuf(&buf, &bufsz, 1+patlen+pb-buf, recsize, &pb, "gsub");
1966
						for (q = patbeg; q < patbeg+patlen; )
1967
							*pb++ = *q++;
1968
					} else
1969
						*pb++ = *sptr++;
1970
				}
1971
				t = patbeg + patlen;
1972
				if (patlen == 0 || *t == 0 || *(t-1) == 0)
1973
					goto done;
1974
				if (pb > buf + bufsz)
1975
					FATAL("gsub result1 %.30s too big; can't happen", buf);
1976
				mflag = 1;
1977
			}
1978
		} while (pmatch(pfa,t));
1979
		sptr = t;
1980
		adjbuf(&buf, &bufsz, 1+strlen(sptr)+pb-buf, 0, &pb, "gsub");
1981
		while ((*pb++ = *sptr++) != 0)
1982
			;
1983
	done:	if (pb < buf + bufsz)
1984
			*pb = '\0';
1985
		else if (*(pb-1) != '\0')
1986
			FATAL("gsub result2 %.30s truncated; can't happen", buf);
1987
		setsval(x, buf);	/* BUG: should be able to avoid copy + free */
1988
		pfa->initstat = tempstat;
1989
	}
1990
	tempfree(x);
1991
	tempfree(y);
1992
	x = gettemp();
1993
	x->tval = NUM;
1994
	x->fval = num;
1995
	free(buf);
1996
	return(x);
1997
}
1998
1999
void backsub(char **pb_ptr, char **sptr_ptr)	/* handle \\& variations */
2000
{						/* sptr[0] == '\\' */
2001
	char *pb = *pb_ptr, *sptr = *sptr_ptr;
2002
2003
	if (sptr[1] == '\\') {
2004
		if (sptr[2] == '\\' && sptr[3] == '&') { /* \\\& -> \& */
2005
			*pb++ = '\\';
2006
			*pb++ = '&';
2007
			sptr += 4;
2008
		} else if (sptr[2] == '&') {	/* \\& -> \ + matched */
2009
			*pb++ = '\\';
2010
			sptr += 2;
2011
		} else {			/* \\x -> \\x */
2012
			*pb++ = *sptr++;
2013
			*pb++ = *sptr++;
2014
		}
2015
	} else if (sptr[1] == '&') {	/* literal & */
2016
		sptr++;
2017
		*pb++ = *sptr++;
2018
	} else				/* literal \ */
2019
		*pb++ = *sptr++;
2020
2021
	*pb_ptr = pb;
2022
	*sptr_ptr = sptr;
2023
}