GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/awk/run.c Lines: 663 1261 52.6 %
Date: 2017-11-07 Branches: 429 1037 41.4 %

Line Branch Exec Source
1
/*	$OpenBSD: run.c,v 1.41 2017/09/15 14:19:56 ajacoutot 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
14928910
	if (minlen > *psiz) {
112
		char *tbuf;
113
2946
		int rminlen = quantum ? minlen % quantum : 0;
114
2946
		int boff = pbptr ? *pbptr - *pbuf : 0;
115
		/* round up to next multiple of quantum */
116
982
		if (rminlen)
117
981
			minlen += quantum - rminlen;
118
982
		tbuf = (char *) realloc(*pbuf, minlen);
119
982
		dprintf( ("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, *pbuf, tbuf) );
120
982
		if (tbuf == NULL) {
121
			if (whatrtn)
122
				FATAL("out of memory in %s", whatrtn);
123
			return 0;
124
		}
125
982
		*pbuf = tbuf;
126
982
		*psiz = minlen;
127
982
		if (pbptr)
128
982
			*pbptr = tbuf + boff;
129
982
	}
130
7464455
	return 1;
131
7464455
}
132
133
void run(Node *a)	/* execution of parse tree starts here */
134
{
135
1962
	stdinit();
136
981
	execute(a);
137
981
	closeall();
138
981
}
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
92533518
	if (u == NULL)
147
695
		return(True);
148
50346409
	for (a = u; ; a = a->nnext) {
149
50346409
		curnode = a;
150
50346409
		if (isvalue(a)) {
151
24890939
			x = (Cell *) (a->narg[0]);
152
24890939
			if (isfld(x) && !donefld)
153
				fldbld();
154
24890939
			else if (isrec(x) && !donerec)
155
				recbld();
156
24890939
			return(x);
157
		}
158

76366410
		if (notlegal(a->nobj))	/* probably a Cell* but too risky to print */
159
			FATAL("illegal statement");
160
		proc = proctab[a->nobj-FIRSTTOKEN];
161
25455074
		x = (*proc)(a->narg, a->nobj);
162
25455074
		if (isfld(x) && !donefld)
163
36454
			fldbld();
164
25418620
		else if (isrec(x) && !donerec)
165
18
			recbld();
166
25455074
		if (isexpr(a))
167
14702713
			return(x);
168
10752361
		if (isjump(x))
169
17523
			return(x);
170
10734838
		if (a->nnext == NULL)
171
6654493
			return(x);
172
4102889
		tempfree(x);
173
	}
174
46266363
}
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
2115
	if (setjmp(env) != 0)
182
		goto ex;
183
981
	if (a[0]) {		/* BEGIN */
184
195
		x = execute(a[0]);
185
195
		if (isexit(x))
186
			return(True);
187
195
		if (isjump(x))
188
			FATAL("illegal break, continue, next or nextfile from BEGIN");
189
195
		tempfree(x);
190
	}
191

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


796
		if (isbreak(x) || isnext(x) || iscont(x))
204
			FATAL("illegal break, continue, next or nextfile from END");
205
199
		tempfree(x);
206
	}
207
  ex1:
208
981
	return(True);
209
981
}
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
12900
	Cell *args[NARGS], *oargs[NARGS];	/* BUG: fixed size arrays */
231
	Cell *y, *z, *fcn;
232
	char *s;
233
234
6450
	fcn = execute(a[0]);	/* the function itself */
235
6450
	s = fcn->nval;
236
6450
	if (!isfcn(fcn))
237
		FATAL("calling undefined function %s", s);
238
6450
	if (frame == NULL) {
239
10
		fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
240
10
		if (frame == NULL)
241
			FATAL("out of space for stack frames calling %s", s);
242
	}
243
25872
	for (ncall = 0, x = a[1]; x != NULL; x = x->nnext)	/* args in call */
244
6486
		ncall++;
245
6450
	ndef = (int) fcn->fval;			/* args in defn */
246
6450
	   dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) );
247
6450
	if (ncall > ndef)
248
		WARNING("function %s called with %d args, uses only %d",
249
			s, ncall, ndef);
250
6450
	if (ncall + ndef > NARGS)
251
		FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS);
252
25872
	for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) {	/* get call args */
253
6486
		   dprintf( ("evaluate args[%d], fp=%d:\n", i, (int) (fp-frame)) );
254
6486
		y = execute(x);
255
6486
		oargs[i] = y;
256


6486
		   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
6486
		if (isfcn(y))
259
			FATAL("can't use function %s as argument in %s", y->nval, s);
260
6486
		if (isarr(y))
261
			args[i] = y;	/* arrays by ref */
262
		else
263
6486
			args[i] = copycell(y);
264
6486
		tempfree(y);
265
	}
266
6450
	for ( ; i < ndef; i++) {	/* add null args for ones not provided */
267
		args[i] = gettemp();
268
		*args[i] = newcopycell;
269
	}
270
6450
	fp++;	/* now ok to up frame */
271
6450
	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
6450
	fp->fcncell = fcn;
280
6450
	fp->args = args;
281
6450
	fp->nargs = ndef;	/* number defined with (excess are locals) */
282
6450
	fp->retval = gettemp();
283
284
6450
	   dprintf( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) );
285
6450
	y = execute((Node *)(fcn->sval));	/* execute body */
286
6450
	   dprintf( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) );
287
288
25872
	for (i = 0; i < ndef; i++) {
289
6486
		Cell *t = fp->args[i];
290
6486
		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
6486
		} else if (t != y) {	/* kludge to prevent freeing twice */
304
6486
			t->csub = CTEMP;
305
12972
			tempfree(t);
306
		} else if (t == y && t->csub == CCOPY) {
307
			t->csub = CTEMP;
308
			tempfree(t);
309
			freed = 1;
310
		}
311
	}
312
6450
	tempfree(fcn);
313

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

23984
	switch (n) {
355
	case EXIT:
356
153
		if (a[0] != NULL) {
357
9
			y = execute(a[0]);
358
9
			errorflag = (int) getfval(y);
359
9
			tempfree(y);
360
		}
361
		longjmp(env, 1);
362
	case RETURN:
363
6414
		if (a[0] != NULL) {
364
6414
			y = execute(a[0]);
365
6414
			if ((y->tval & (STR|NUM)) == (STR|NUM)) {
366
6
				setsval(fp->retval, getsval(y));
367
6
				fp->retval->fval = getfval(y);
368
6
				fp->retval->tval |= NUM;
369
6
			}
370
6408
			else if (y->tval & STR)
371
5964
				setsval(fp->retval, getsval(y));
372
444
			else if (y->tval & NUM)
373
444
				setfval(fp->retval, getfval(y));
374
			else		/* can't happen */
375
				FATAL("bad type variable %d", y->tval);
376
9396
			tempfree(y);
377
		}
378
6414
		return(jret);
379
	case NEXT:
380
4617
		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
11839
}
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
26368
	if (donefld == 0)
450
288
		fldbld();
451
13184
	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
15938
	char *buf;
460
7969
	int bufsz = recsize;
461
7969
	int nsub = strlen(*SUBSEP);
462
463
7969
	if ((buf = (char *) malloc(bufsz)) == NULL)
464
		FATAL("out of memory in array");
465
466
7969
	x = execute(a[0]);	/* Cell* for symbol table */
467
7969
	buf[0] = 0;
468
31876
	for (np = a[1]; np; np = np->nnext) {
469
7969
		y = execute(np);	/* subscript */
470
7969
		s = getsval(y);
471
7969
		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
7969
		strlcat(buf, s, bufsz);
474
7969
		if (np->nnext)
475
			strlcat(buf, *SUBSEP, bufsz);
476
8500
		tempfree(y);
477
	}
478
7969
	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
7969
	z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
487
7969
	z->ctype = OCELL;
488
7969
	z->csub = CVAR;
489
7969
	tempfree(x);
490
7969
	free(buf);
491
7969
	return(z);
492
7969
}
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
106258
	if (n == MATCHFCN) {
583
		mf = pmatch;
584
		mode = 1;
585
1212
	}
586
53129
	x = execute(a[1]);	/* a[1] = target text */
587
53129
	s = getsval(x);
588
53129
	if (a[0] == 0)		/* a[1] == 0: already-compiled reg expr */
589
53129
		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
53129
	tempfree(x);
598
53129
	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

92987
	} else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
609
11251
		return(True);
610
	else
611
40666
		return(False);
612
53129
}
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
86058
	x = execute(a[0]);
621
43029
	i = istrue(x);
622
43029
	tempfree(x);
623

43029
	switch (n) {
624
	case BOR:
625
19840
		if (i) return(True);
626
15448
		y = execute(a[1]);
627
15448
		i = istrue(y);
628
15448
		tempfree(y);
629
16580
		if (i) return(True);
630
14316
		else return(False);
631
	case AND:
632
26498
		if ( !i ) return(False);
633
23464
		y = execute(a[1]);
634
23464
		i = istrue(y);
635
23464
		tempfree(y);
636
25092
		if (i) return(True);
637
21836
		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
43029
}
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
9421312
	x = execute(a[0]);
654
4710656
	y = execute(a[1]);
655

8259361
	if (x->tval&NUM && y->tval&NUM) {
656
3548682
		j = x->fval - y->fval;
657
8408619
		i = j<0? -1: (j>0? 1: 0);
658
3548682
	} else {
659
1161974
		i = strcmp(getsval(x), getsval(y));
660
	}
661
6796706
	tempfree(x);
662
4724462
	tempfree(y);
663

4710656
	switch (n) {
664
5056738
	case LT:	if (i<0) return(True);
665
901886
			else return(False);
666
280874
	case LE:	if (i<=0) return(True);
667
6880
			else return(False);
668
2740458
	case NE:	if (i!=0) return(True);
669
151736
			else return(False);
670
153022
	case EQ:	if (i == 0) return(True);
671
90128
			else return(False);
672
12717
	case GE:	if (i>=0) return(True);
673
11309
			else return(False);
674
8469
	case GT:	if (i>0) return(True);
675
7095
			else return(False);
676
	default:	/* can't happen */
677
		FATAL("unknown relational operator %d", n);
678
	}
679
	return 0;	/*NOTREACHED*/
680
4710656
}
681
682
void tfree(Cell *a)	/* free a tempcell */
683
{
684
10034620
	if (freeable(a)) {
685

2615958
		   dprintf( ("freeing %s %s %o\n", NN(a->nval), NN(a->sval), a->tval) );
686
5231916
		xfree(a->sval);
687
	}
688
5017310
	if (a == tmps)
689
		FATAL("tempcell list is curdled");
690
5017310
	a->cnext = tmps;
691
5017310
	tmps = a;
692
5017310
}
693
694
Cell *gettemp(void)	/* get a tempcell */
695
{	int i;
696
	Cell *x;
697
698
10034620
	if (!tmps) {
699
316
		tmps = (Cell *) calloc(100, sizeof(Cell));
700
316
		if (!tmps)
701
			FATAL("out of space for temporaries");
702
63200
		for(i = 1; i < 100; i++)
703
31284
			tmps[i-1].cnext = &tmps[i];
704
316
		tmps[i-1].cnext = 0;
705
316
	}
706
5017310
	x = tmps;
707
5017310
	tmps = x->cnext;
708
5017310
	*x = tempcell;
709
5017310
	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
11784164
	x = execute(a[0]);
720
5892082
	val = getfval(x);	/* freebsd: defend against super large field numbers */
721
5892082
	if ((Awkfloat)INT_MAX < val)
722
		FATAL("trying to access out of range field %s", x->nval);
723
5892082
	m = (int) val;
724

11620393
	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
5892082
	tempfree(x);
728
5892082
	x = fieldadr(m);
729
5892082
	x->ctype = OCELL;	/* BUG?  why are these needed? */
730
5892082
	x->csub = CFLD;
731
5892082
	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
424062
	x = execute(a[0]);
742
212031
	y = execute(a[1]);
743
212031
	if (a[2] != 0)
744
205746
		z = execute(a[2]);
745
212031
	s = getsval(x);
746
212031
	k = strlen(s) + 1;
747
212031
	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
212029
	m = (int) getfval(y);
758
212029
	if (m <= 0)
759
		m = 1;
760
212029
	else if (m > k)
761
		m = k;
762
212060
	tempfree(y);
763
212029
	if (a[2] != 0) {
764
205744
		n = (int) getfval(z);
765
406295
		tempfree(z);
766
	} else
767
6285
		n = k - 1;
768
212029
	if (n < 0)
769
		n = 0;
770
212029
	else if (n > k - m)
771
269
		n = k - m;
772
212029
	   dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) );
773
212029
	y = gettemp();
774
212029
	temp = s[n+m-1];	/* with thanks to John Linderman */
775
212029
	s[n+m-1] = '\0';
776
212029
	setsval(y, s + m - 1);
777
212029
	s[n+m-1] = temp;
778
212029
	tempfree(x);
779
212029
	return(y);
780
212031
}
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
458
	x = execute(a[0]);
789
229
	s1 = getsval(x);
790
229
	y = execute(a[1]);
791
229
	s2 = getsval(y);
792
793
229
	z = gettemp();
794
992
	for (p1 = s1; *p1 != '\0'; p1++) {
795

4772
		for (q=p1, p2=s2; *p2 != '\0' && *q == *p2; q++, p2++)
796
			;
797
496
		if (*p2 == '\0') {
798
229
			v = (Awkfloat) (p1 - s1 + 1);	/* origin 1 */
799
229
			break;
800
		}
801
	}
802
229
	tempfree(x);
803
229
	tempfree(y);
804
229
	setfval(z, v);
805
229
	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
801918
	char *fmt;
813
400959
	char *p, *t;
814
	const char *os;
815
	Cell *x;
816
	int flag = 0, n;
817
	int fmtwd; /* format width */
818
400959
	int fmtsz = recsize;
819
400959
	char *buf = *pbuf;
820
400959
	int bufsize = *pbufsize;
821
822
	os = s;
823
400959
	p = buf;
824
400959
	if ((fmt = (char *) malloc(fmtsz)) == NULL)
825
		FATAL("out of memory in format()");
826
3619808
	while (*s) {
827
2638027
		adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format1");
828
2638027
		if (*s != '%') {
829
2057205
			*p++ = *s++;
830
2057205
			continue;
831
		}
832
580822
		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
580822
		fmtwd = atoi(s+1);
839
580822
		if (fmtwd < 0)
840
1155
			fmtwd = -fmtwd;
841
580822
		adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format2");
842
2401416
		for (t = fmt; (*t++ = *s) != '\0'; s++) {
843
1200708
			if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3"))
844
				FATAL("format item %.30s... ran format() out of memory", os);
845


2943174
			if (isalpha((uschar)*s) && *s != 'l' && *s != 'h' && *s != 'L')
846
				break;	/* the ansi panoply */
847
619886
			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
580822
		*t = '\0';
861
580822
		if (fmtwd < 0)
862
			fmtwd = -fmtwd;
863
580822
		adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format4");
864
865



580822
		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
122435
			if(*(s-1) == 'l') break;
872
122435
			*(t-1) = 'l';
873
122435
			*t = 'd';
874
122435
			*++t = '\0';
875
122435
			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
455838
			break;
882
		case 'c':
883
			flag = 'c';
884
1785
			break;
885
		default:
886
			WARNING("weird printf conversion %s", fmt);
887
			flag = '?';
888
			break;
889
		}
890
580822
		if (a == NULL)
891
			FATAL("not enough args in printf(%s)", os);
892
580822
		x = execute(a);
893
580822
		a = a->nnext;
894
		n = MAXNUMSIZE;
895
580822
		if (fmtwd > n)
896
			n = fmtwd;
897
580822
		adjbuf(&buf, &bufsize, 1+n+p-buf, recsize, &p, "format5");
898

580822
		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
122435
		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
455838
			t = getsval(x);
914
455838
			n = strlen(t);
915
455838
			if (fmtwd > n)
916
1155
				n = fmtwd;
917
455838
			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
455838
			snprintf(p, buf + bufsize - p, fmt, t);
920
455838
			break;
921
		case 'c':
922
1785
			if (isnum(x)) {
923
1785
				if ((int)getfval(x))
924
1785
					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
582004
		tempfree(x);
936
580822
		p += strlen(p);
937
580822
		s++;
938
	}
939
400959
	*p = '\0';
940
400959
	free(fmt);
941
801918
	for ( ; a; a = a->nnext)		/* evaluate any remaining args */
942
		execute(a);
943
400959
	*pbuf = buf;
944
400959
	*pbufsize = bufsize;
945
801918
	return p - buf;
946
400959
}
947
948
Cell *awksprintf(Node **a, int n)		/* sprintf(a[0]) */
949
{
950
	Cell *x;
951
	Node *y;
952
20492
	char *buf;
953
10246
	int bufsz=3*recsize;
954
955
10246
	if ((buf = (char *) malloc(bufsz)) == NULL)
956
		FATAL("out of memory in awksprintf");
957
10246
	y = a[0]->nnext;
958
10246
	x = execute(a[0]);
959
10246
	if (format(&buf, &bufsz, getsval(x), y) == -1)
960
		FATAL("sprintf string %.30s... too long.  can't happen.", buf);
961
10246
	tempfree(x);
962
10246
	x = gettemp();
963
10246
	x->sval = buf;
964
10246
	x->tval = STR;
965
10246
	return(x);
966
10246
}
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
781426
	char *buf;
975
	int len;
976
390713
	int bufsz=3*recsize;
977
978
390713
	if ((buf = (char *) malloc(bufsz)) == NULL)
979
		FATAL("out of memory in awkprintf");
980
390713
	y = a[0]->nnext;
981
390713
	x = execute(a[0]);
982
390713
	if ((len = format(&buf, &bufsz, getsval(x), y)) == -1)
983
		FATAL("printf string %.30s... too long.  can't happen.", buf);
984
390713
	tempfree(x);
985
390713
	if (a[1] == NULL) {
986
		/* fputs(buf, stdout); */
987
390713
		fwrite(buf, len, 1, stdout);
988

781426
		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
390713
	free(buf);
999
781426
	return(True);
1000
390713
}
1001
1002
Cell *arith(Node **a, int n)	/* a[0] + a[1], etc.  also -a[0] */
1003
{
1004
	Awkfloat i, j = 0;
1005
914302
	double v;
1006
	Cell *x, *y, *z;
1007
1008
457151
	x = execute(a[0]);
1009
457151
	i = getfval(x);
1010
475148
	tempfree(x);
1011
457151
	if (n != UMINUS) {
1012
455279
		y = execute(a[1]);
1013
455279
		j = getfval(y);
1014
470403
		tempfree(y);
1015
	}
1016
457151
	z = gettemp();
1017


457151
	switch (n) {
1018
	case ADD:
1019
33332
		i += j;
1020
33332
		break;
1021
	case MINUS:
1022
3722
		i -= j;
1023
3722
		break;
1024
	case MULT:
1025
5733
		i *= j;
1026
5733
		break;
1027
	case DIVIDE:
1028
		if (j == 0)
1029
			FATAL("division by zero");
1030
		i /= j;
1031
		break;
1032
	case MOD:
1033
412492
		if (j == 0)
1034
			FATAL("division by zero in mod");
1035
412492
		modf(i/j, &v);
1036
412492
		i = i - j * v;
1037
412492
		break;
1038
	case UMINUS:
1039
1872
		i = -i;
1040
1872
		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
457151
	setfval(z, i);
1051
457151
	return(z);
1052
457151
}
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
4904920
	x = execute(a[0]);
1074
2452460
	xf = getfval(x);
1075
2452460
	k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
1076
2452460
	if (n == PREINCR || n == PREDECR) {
1077
526041
		setfval(x, xf + k);
1078
526041
		return(x);
1079
	}
1080
1926419
	z = gettemp();
1081
1926419
	setfval(z, xf);
1082
1926419
	setfval(x, xf + k);
1083
1926419
	tempfree(x);
1084
1926419
	return(z);
1085
2452460
}
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
2801378
	double v;
1092
1093
1400689
	y = execute(a[1]);
1094
1400689
	x = execute(a[0]);
1095
1400689
	if (n == ASSIGN) {	/* ordinary assignment */
1096

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

29120
	switch (n) {
1115
	case ADDEQ:
1116
29120
		xf += yf;
1117
29120
		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
29476
	tempfree(y);
1146
29120
	setfval(x, xf);
1147
29120
	return(x);
1148
1400689
}
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
2601550
	x = execute(a[0]);
1158
1300775
	y = execute(a[1]);
1159
1300775
	getsval(x);
1160
1300775
	getsval(y);
1161
1300775
	n1 = strlen(x->sval);
1162
1300775
	n2 = strlen(y->sval);
1163
1300775
	len = n1 + n2 + 1;
1164
1300775
	s = (char *) malloc(len);
1165
1300775
	if (s == NULL)
1166
		FATAL("out of space concatenating %.15s... and %.15s...",
1167
			x->sval, y->sval);
1168
1300775
	strlcpy(s, x->sval, len);
1169
1300775
	strlcpy(s+n1, y->sval, len - n1);
1170
1307792
	tempfree(x);
1171
1309752
	tempfree(y);
1172
1300775
	z = gettemp();
1173
1300775
	z->sval = s;
1174
1300775
	z->tval = STR;
1175
1300775
	return(z);
1176
}
1177
1178
Cell *pastat(Node **a, int n)	/* a[0] { a[1] } */
1179
{
1180
	Cell *x;
1181
1182
4695796
	if (a[0] == 0)
1183
254586
		x = execute(a[1]);
1184
	else {
1185
2093312
		x = execute(a[0]);
1186
2093312
		if (istrue(x)) {
1187
1053361
			tempfree(x);
1188
1053361
			x = execute(a[1]);
1189
1053361
		}
1190
	}
1191
2347745
	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
1960
	char *t, temp, num[50], *fs = 0;
1223
	int n, tempstat, arg3type;
1224
1225
980
	y = execute(a[0]);	/* source string */
1226
980
	s = getsval(y);
1227
980
	arg3type = ptoi(a[3]);
1228
980
	if (a[2] == 0)		/* fs string */
1229
		fs = *FS;
1230
980
	else if (arg3type == STRING) {	/* split(str,arr,"string") */
1231
980
		x = execute(a[2]);
1232
980
		fs = getsval(x);
1233
980
	} else if (arg3type == REGEXPR)
1234
		fs = "(regexpr)";	/* split(str,arr,/regexpr/) */
1235
	else
1236
		FATAL("illegal type of split");
1237
980
	sep = *fs;
1238
980
	ap = execute(a[1]);	/* array name */
1239
980
	freesymtab(ap);
1240

980
	   dprintf( ("split: s=|%s|, a=%s, sep=|%s|\n", s, NN(ap->nval), fs) );
1241
980
	ap->tval &= ~STR;
1242
980
	ap->tval |= ARR;
1243
980
	ap->sval = (char *) makesymtab(NSYMTAB);
1244
1245
	n = 0;
1246

980
        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

1885
	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
980
	} else if (sep == ' ') {
1293
229
		for (n = 0; ; ) {
1294

3733
			while (*s == ' ' || *s == '\t' || *s == '\n')
1295
26
				s++;
1296
731
			if (*s == 0)
1297
				break;
1298
502
			n++;
1299
			t = s;
1300
502
			do
1301
8889
				s++;
1302

17506
			while (*s!=' ' && *s!='\t' && *s!='\n' && *s!='\0');
1303
502
			temp = *s;
1304
502
			*s = '\0';
1305
502
			snprintf(num, sizeof num, "%d", n);
1306
502
			if (is_number(t))
1307
15
				setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1308
			else
1309
487
				setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1310
502
			*s = temp;
1311
502
			if (*s != 0)
1312
273
				s++;
1313
		}
1314
751
	} 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
751
	} else if (*s != 0) {
1327
		for (;;) {
1328
795
			n++;
1329
			t = s;
1330

165522
			while (*s != sep && *s != '\n' && *s != '\0')
1331
32357
				s++;
1332
795
			temp = *s;
1333
795
			*s = '\0';
1334
795
			snprintf(num, sizeof num, "%d", n);
1335
795
			if (is_number(t))
1336
				setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1337
			else
1338
795
				setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1339
795
			*s = temp;
1340
795
			if (*s++ == 0)
1341
				break;
1342
		}
1343
	}
1344
980
	tempfree(ap);
1345
980
	tempfree(y);
1346
980
	if (a[2] != 0 && arg3type == STRING) {
1347
980
		tempfree(x);
1348
	}
1349
980
	x = gettemp();
1350
980
	x->tval = NUM;
1351
980
	x->fval = n;
1352
980
	return(x);
1353
980
}
1354
1355
Cell *condexpr(Node **a, int n)	/* a[0] ? a[1] : a[2] */
1356
{
1357
	Cell *x;
1358
1359
176
	x = execute(a[0]);
1360
88
	if (istrue(x)) {
1361
8
		tempfree(x);
1362
8
		x = execute(a[1]);
1363
8
	} else {
1364
80
		tempfree(x);
1365
80
		x = execute(a[2]);
1366
	}
1367
88
	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
668544
	x = execute(a[0]);
1375
334272
	if (istrue(x)) {
1376
224171
		tempfree(x);
1377
224171
		x = execute(a[1]);
1378
334272
	} else if (a[2] != 0) {
1379
57211
		tempfree(x);
1380
57211
		x = execute(a[2]);
1381
57211
	}
1382
334182
	return(x);
1383
}
1384
1385
Cell *whilestat(Node **a, int n)	/* while (a[0]) a[1] */
1386
{
1387
	Cell *x;
1388
1389
18
	for (;;) {
1390
786447
		x = execute(a[0]);
1391
786447
		if (!istrue(x))
1392
9
			return(x);
1393
786438
		tempfree(x);
1394
786438
		x = execute(a[1]);
1395
786438
		if (isbreak(x)) {
1396
			x = True;
1397
			return(x);
1398
		}
1399


3145752
		if (isnext(x) || isexit(x) || isret(x))
1400
			return(x);
1401
786438
		tempfree(x);
1402
	}
1403
9
}
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
7722
	x = execute(a[0]);
1428
3861
	tempfree(x);
1429
	for (;;) {
1430
1457625
		if (a[1]!=0) {
1431
1457625
			x = execute(a[1]);
1432
1460678
			if (!istrue(x)) return(x);
1433
1454572
			else tempfree(x);
1434
		}
1435
1454572
		x = execute(a[3]);
1436
1454572
		if (isbreak(x))		/* turn off break */
1437
808
			return True;
1438


5815056
		if (isnext(x) || isexit(x) || isret(x))
1439
			return(x);
1440
1454366
		tempfree(x);
1441
1453764
		x = execute(a[2]);
1442
2564091
		tempfree(x);
1443
	}
1444
3861
}
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
4
	vp = execute(a[0]);
1453
2
	arrayp = execute(a[1]);
1454
2
	if (!isarr(arrayp)) {
1455
		return True;
1456
	}
1457
2
	tp = (Array *) arrayp->sval;
1458
2
	tempfree(arrayp);
1459
504
	for (i = 0; i < tp->size; i++) {	/* this routine knows too much */
1460
962
		for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1461
231
			setsval(vp, cp->nval);
1462
231
			ncp = cp->cnext;
1463
231
			x = execute(a[2]);
1464
231
			if (isbreak(x)) {
1465
				tempfree(vp);
1466
				return True;
1467
			}
1468


924
			if (isnext(x) || isexit(x) || isret(x)) {
1469
				tempfree(vp);
1470
				return(x);
1471
			}
1472
231
			tempfree(x);
1473
		}
1474
	}
1475
2
	return True;
1476
2
}
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
2190662
	Awkfloat u;
1482
	int t;
1483
	Awkfloat tmp;
1484
	char *p, *buf;
1485
	Node *nextarg;
1486
	FILE *fp;
1487
1488
1095331
	t = ptoi(a[0]);
1489
1095331
	x = execute(a[1]);
1490
1095331
	nextarg = a[1]->nnext;
1491





1095331
	switch (t) {
1492
	case FLENGTH:
1493
15331
		if (isarr(x))
1494
			u = ((Array *) x->sval)->nelem;	/* GROT.  should be function*/
1495
		else
1496
15331
			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
1080000
		u = (Awkfloat) (random() & RAND_MAX) / ((u_int)RAND_MAX + 1);
1585
1080000
		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
1095331
	tempfree(x);
1630
1095331
	x = gettemp();
1631
1095331
	setfval(x, u);
1632
1095331
	if (nextarg != 0) {
1633
		WARNING("warning: function has too many arguments");
1634
		for ( ; nextarg; nextarg = nextarg->nnext)
1635
			execute(nextarg);
1636
	}
1637
1095331
	return(x);
1638
1095331
}
1639
1640
Cell *printstat(Node **a, int n)	/* print a[0] */
1641
{
1642
	Node *x;
1643
	Cell *y;
1644
	FILE *fp;
1645
1646
9391958
	if (a[1] == 0)	/* a[1] is redirection operator, a[2] is file */
1647
1454400
		fp = stdout;
1648
	else
1649
3241579
		fp = redirect(ptoi(a[1]), a[2]);
1650
18828638
	for (x = a[0]; x != NULL; x = x->nnext) {
1651
4718340
		y = execute(x);
1652
4718340
		fputs(getpssval(y), fp);
1653
5801705
		tempfree(y);
1654
4718340
		if (x->nnext == NULL)
1655
4695979
			fputs(*ORS, fp);
1656
		else
1657
22361
			fputs(*OFS, fp);
1658
	}
1659
4695979
	if (a[1] != 0)
1660
3241579
		fflush(fp);
1661

9391958
	if (ferror(fp))
1662
		FATAL("write error on %s", filename(fp));
1663
4695979
	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
6483158
	x = execute(b);
1681
3241579
	fname = getsval(x);
1682
3241579
	fp = openfile(a, fname);
1683
3241579
	if (fp == NULL)
1684
		FATAL("can't open file %s", fname);
1685
3241579
	tempfree(x);
1686
3241579
	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
1962
	nfiles = FOPEN_MAX;
1700
981
	files = calloc(nfiles, sizeof(*files));
1701
981
	if (files == NULL)
1702
		FATAL("can't allocate file memory for %u files", nfiles);
1703
981
        files[0].fp = stdin;
1704
981
	files[0].fname = "/dev/stdin";
1705
981
	files[0].mode = LT;
1706
981
        files[1].fp = stdout;
1707
981
	files[1].fname = "/dev/stdout";
1708
981
	files[1].mode = GT;
1709
981
        files[2].fp = stderr;
1710
981
	files[2].fname = "/dev/stderr";
1711
981
	files[2].mode = GT;
1712
981
}
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
6483158
	if (*s == '\0')
1721
		FATAL("null file name in print or getline");
1722
25956860
	for (i=0; i < nfiles; i++)
1723

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

3241516
			if (a == files[i].mode || (a==APPEND && files[i].mode==GT))
1725
3241516
				return files[i].fp;
1726
			if (a == FFLUSH)
1727
				return files[i].fp;
1728
		}
1729
63
	if (a == FFLUSH)	/* didn't find it, so don't create it! */
1730
		return NULL;
1731
1732
558
	for (i=0; i < nfiles; i++)
1733
279
		if (files[i].fp == 0)
1734
			break;
1735
63
	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
63
	fflush(stdout);	/* force a semblance of order */
1746
	m = a;
1747
63
	if (a == GT) {
1748
63
		fp = fopen(s, "w");
1749
63
	} 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
63
	if (fp != NULL) {
1761
63
		files[i].fname = tostring(s);
1762
63
		files[i].fp = fp;
1763
63
		files[i].mode = m;
1764
63
	}
1765
63
	return fp;
1766
3241579
}
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
42183
	for (i = 0; i < FOPEN_MAX; i++) {
1814
19620
		if (files[i].fp) {
1815

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

6012
			if (files[i].mode == '|' || files[i].mode == LE)
1818
				stat = pclose(files[i].fp);
1819
			else
1820
3006
				stat = fclose(files[i].fp);
1821
3006
			if (stat == EOF)
1822
				WARNING( "i/o error occurred while closing %s", files[i].fname );
1823
		}
1824
	}
1825
981
}
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
}