GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/awk/run.c Lines: 491 1291 38.0 %
Date: 2016-12-06 Branches: 291 1010 28.8 %

Line Branch Exec Source
1
/*	$OpenBSD: run.c,v 1.40 2015/12/16 19:44:42 tb 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
679592
{
111
679592
	if (minlen > *psiz) {
112
		char *tbuf;
113
32
		int rminlen = quantum ? minlen % quantum : 0;
114
32
		int boff = pbptr ? *pbptr - *pbuf : 0;
115
		/* round up to next multiple of quantum */
116
32
		if (rminlen)
117
31
			minlen += quantum - rminlen;
118
32
		tbuf = (char *) realloc(*pbuf, minlen);
119
32
		dprintf( ("adjbuf %s: %d %d (pbuf=%p, tbuf=%p)\n", whatrtn, *psiz, minlen, *pbuf, tbuf) );
120
32
		if (tbuf == NULL) {
121
			if (whatrtn)
122
				FATAL("out of memory in %s", whatrtn);
123
			return 0;
124
		}
125
32
		*pbuf = tbuf;
126
32
		*psiz = minlen;
127
32
		if (pbptr)
128
32
			*pbptr = tbuf + boff;
129
	}
130
679592
	return 1;
131
}
132
133
void run(Node *a)	/* execution of parse tree starts here */
134
31
{
135
31
	stdinit();
136
31
	execute(a);
137
31
	closeall();
138
31
}
139
140
Cell *execute(Node *u)	/* execute a node of the parse tree */
141
844026
{
142
	Cell *(*proc)(Node **, int);
143
	Cell *x;
144
	Node *a;
145
146
844026
	if (u == NULL)
147
		return(True);
148
888216
	for (a = u; ; a = a->nnext) {
149
888216
		curnode = a;
150
888216
		if (isvalue(a)) {
151
469042
			x = (Cell *) (a->narg[0]);
152

469042
			if (isfld(x) && !donefld)
153
				fldbld();
154

469042
			else if (isrec(x) && !donerec)
155
				recbld();
156
469042
			return(x);
157
		}
158

419174
		if (notlegal(a->nobj))	/* probably a Cell* but too risky to print */
159
			FATAL("illegal statement");
160
419174
		proc = proctab[a->nobj-FIRSTTOKEN];
161
419174
		x = (*proc)(a->narg, a->nobj);
162

419133
		if (isfld(x) && !donefld)
163
			fldbld();
164

419133
		else if (isrec(x) && !donerec)
165
			recbld();
166
419133
		if (isexpr(a))
167
218977
			return(x);
168
200156
		if (isjump(x))
169
672
			return(x);
170
199484
		if (a->nnext == NULL)
171
155294
			return(x);
172
44190
		tempfree(x);
173
44190
	}
174
}
175
176
177
Cell *program(Node **a, int n)	/* execute an awk program */
178
31
{				/* a[0] = BEGIN, a[1] = body, a[2] = END */
179
	Cell *x;
180
181
31
	if (setjmp(env) != 0)
182
16
		goto ex;
183
31
	if (a[0]) {		/* BEGIN */
184
8
		x = execute(a[0]);
185
8
		if (isexit(x))
186
			return(True);
187
8
		if (isjump(x))
188
			FATAL("illegal break, continue, next or nextfile from BEGIN");
189
8
		tempfree(x);
190
	}
191

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

11
		if (isbreak(x) || isnext(x) || iscont(x))
204
			FATAL("illegal break, continue, next or nextfile from END");
205
11
		tempfree(x);
206
	}
207
31
  ex1:
208
31
	return(True);
209
}
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
	Cell *args[NARGS], *oargs[NARGS];	/* BUG: fixed size arrays */
231
	Cell *y, *z, *fcn;
232
	char *s;
233
234
	fcn = execute(a[0]);	/* the function itself */
235
	s = fcn->nval;
236
	if (!isfcn(fcn))
237
		FATAL("calling undefined function %s", s);
238
	if (frame == NULL) {
239
		fp = frame = (struct Frame *) calloc(nframe += 100, sizeof(struct Frame));
240
		if (frame == NULL)
241
			FATAL("out of space for stack frames calling %s", s);
242
	}
243
	for (ncall = 0, x = a[1]; x != NULL; x = x->nnext)	/* args in call */
244
		ncall++;
245
	ndef = (int) fcn->fval;			/* args in defn */
246
	   dprintf( ("calling %s, %d args (%d in defn), fp=%d\n", s, ncall, ndef, (int) (fp-frame)) );
247
	if (ncall > ndef)
248
		WARNING("function %s called with %d args, uses only %d",
249
			s, ncall, ndef);
250
	if (ncall + ndef > NARGS)
251
		FATAL("function %s has %d arguments, limit %d", s, ncall+ndef, NARGS);
252
	for (i = 0, x = a[1]; x != NULL; i++, x = x->nnext) {	/* get call args */
253
		   dprintf( ("evaluate args[%d], fp=%d:\n", i, (int) (fp-frame)) );
254
		y = execute(x);
255
		oargs[i] = y;
256
		   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
		if (isfcn(y))
259
			FATAL("can't use function %s as argument in %s", y->nval, s);
260
		if (isarr(y))
261
			args[i] = y;	/* arrays by ref */
262
		else
263
			args[i] = copycell(y);
264
		tempfree(y);
265
	}
266
	for ( ; i < ndef; i++) {	/* add null args for ones not provided */
267
		args[i] = gettemp();
268
		*args[i] = newcopycell;
269
	}
270
	fp++;	/* now ok to up frame */
271
	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
	fp->fcncell = fcn;
280
	fp->args = args;
281
	fp->nargs = ndef;	/* number defined with (excess are locals) */
282
	fp->retval = gettemp();
283
284
	   dprintf( ("start exec of %s, fp=%d\n", s, (int) (fp-frame)) );
285
	y = execute((Node *)(fcn->sval));	/* execute body */
286
	   dprintf( ("finished exec of %s, fp=%d\n", s, (int) (fp-frame)) );
287
288
	for (i = 0; i < ndef; i++) {
289
		Cell *t = fp->args[i];
290
		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
		} else if (t != y) {	/* kludge to prevent freeing twice */
304
			t->csub = CTEMP;
305
			tempfree(t);
306
		} else if (t == y && t->csub == CCOPY) {
307
			t->csub = CTEMP;
308
			tempfree(t);
309
			freed = 1;
310
		}
311
	}
312
	tempfree(fcn);
313
	if (isexit(y) || isnext(y))
314
		return y;
315
	if (freed == 0) {
316
		tempfree(y);	/* don't free twice! */
317
	}
318
	z = fp->retval;			/* return value */
319
	   dprintf( ("%s returns %g |%s| %o\n", s, getfval(z), getsval(z), z->tval) );
320
	fp--;
321
	return(z);
322
}
323
324
Cell *copycell(Cell *x)	/* make a copy of a cell in a temp */
325
{
326
	Cell *y;
327
328
	y = gettemp();
329
	y->csub = CCOPY;	/* prevents freeing until call is over */
330
	y->nval = x->nval;	/* BUG? */
331
	if (isstr(x))
332
		y->sval = tostring(x->sval);
333
	y->fval = x->fval;
334
	y->tval = x->tval & ~(CON|FLD|REC|DONTFREE);	/* copy is not constant or field */
335
							/* is DONTFREE right? */
336
	return y;
337
}
338
339
Cell *arg(Node **a, int n)	/* nth argument of a function */
340
{
341
342
	n = ptoi(a[0]);	/* argument number, counting from 0 */
343
	   dprintf( ("arg(%d), fp->nargs=%d\n", n, fp->nargs) );
344
	if (n+1 > fp->nargs)
345
		FATAL("argument #%d of function %s was not supplied",
346
			n+1, fp->fcncell->nval);
347
	return fp->args[n];
348
}
349
350
Cell *jump(Node **a, int n)	/* break, continue, next, nextfile, return */
351
223
{
352
	Cell *y;
353
354

223
	switch (n) {
355
	case EXIT:
356
16
		if (a[0] != NULL) {
357
			y = execute(a[0]);
358
			errorflag = (int) getfval(y);
359
			tempfree(y);
360
		}
361
16
		longjmp(env, 1);
362
	case RETURN:
363
		if (a[0] != NULL) {
364
			y = execute(a[0]);
365
			if ((y->tval & (STR|NUM)) == (STR|NUM)) {
366
				setsval(fp->retval, getsval(y));
367
				fp->retval->fval = getfval(y);
368
				fp->retval->tval |= NUM;
369
			}
370
			else if (y->tval & STR)
371
				setsval(fp->retval, getsval(y));
372
			else if (y->tval & NUM)
373
				setfval(fp->retval, getfval(y));
374
			else		/* can't happen */
375
				FATAL("bad type variable %d", y->tval);
376
			tempfree(y);
377
		}
378
		return(jret);
379
	case NEXT:
380
207
		return(jnext);
381
	case NEXTFILE:
382
		nextfile();
383
		return(jnextfile);
384
	case BREAK:
385
		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
}
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
	if (donefld == 0)
450
		fldbld();
451
	return (Cell *) a[0];
452
}
453
454
Cell *array(Node **a, int n)	/* a[0] is symtab, a[1] is list of subscripts */
455
2592
{
456
	Cell *x, *y, *z;
457
	char *s;
458
	Node *np;
459
	char *buf;
460
2592
	int bufsz = recsize;
461
2592
	int nsub = strlen(*SUBSEP);
462
463
2592
	if ((buf = (char *) malloc(bufsz)) == NULL)
464
		FATAL("out of memory in array");
465
466
2592
	x = execute(a[0]);	/* Cell* for symbol table */
467
2592
	buf[0] = 0;
468
5184
	for (np = a[1]; np; np = np->nnext) {
469
2592
		y = execute(np);	/* subscript */
470
2592
		s = getsval(y);
471
2592
		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
2592
		strlcat(buf, s, bufsz);
474
2592
		if (np->nnext)
475
			strlcat(buf, *SUBSEP, bufsz);
476
2592
		tempfree(y);
477
	}
478
2592
	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
2592
	z = setsymtab(buf, "", 0.0, STR|NUM, (Array *) x->sval);
487
2592
	z->ctype = OCELL;
488
2592
	z->csub = CVAR;
489
2592
	tempfree(x);
490
2592
	free(buf);
491
2592
	return(z);
492
}
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
1955
{
576
	Cell *x, *y;
577
	char *s, *t;
578
	int i;
579
	fa *pfa;
580
1955
	int (*mf)(fa *, const char *) = match, mode = 0;
581
582
1955
	if (n == MATCHFCN) {
583
		mf = pmatch;
584
		mode = 1;
585
	}
586
1955
	x = execute(a[1]);	/* a[1] = target text */
587
1955
	s = getsval(x);
588
1955
	if (a[0] == 0)		/* a[1] == 0: already-compiled reg expr */
589
1955
		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
1955
	tempfree(x);
598
1955
	if (n == MATCHFCN) {
599
		int start = patbeg - s + 1;
600
		if (patlen < 0)
601
			start = 0;
602
		setfval(rstartloc, (Awkfloat) start);
603
		setfval(rlengthloc, (Awkfloat) patlen);
604
		x = gettemp();
605
		x->tval = NUM;
606
		x->fval = start;
607
		return x;
608

1955
	} else if ((n == MATCH && i == 1) || (n == NOTMATCH && i == 0))
609
229
		return(True);
610
	else
611
1726
		return(False);
612
}
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
	x = execute(a[0]);
621
	i = istrue(x);
622
	tempfree(x);
623
	switch (n) {
624
	case BOR:
625
		if (i) return(True);
626
		y = execute(a[1]);
627
		i = istrue(y);
628
		tempfree(y);
629
		if (i) return(True);
630
		else return(False);
631
	case AND:
632
		if ( !i ) return(False);
633
		y = execute(a[1]);
634
		i = istrue(y);
635
		tempfree(y);
636
		if (i) return(True);
637
		else return(False);
638
	case NOT:
639
		if (i) return(False);
640
		else return(True);
641
	default:	/* can't happen */
642
		FATAL("unknown boolean operator %d", n);
643
	}
644
	return 0;	/*NOTREACHED*/
645
}
646
647
Cell *relop(Node **a, int n)	/* a[0 < a[1], etc. */
648
67136
{
649
	int i;
650
	Cell *x, *y;
651
	Awkfloat j;
652
653
67136
	x = execute(a[0]);
654
67136
	y = execute(a[1]);
655

133970
	if (x->tval&NUM && y->tval&NUM) {
656
66834
		j = x->fval - y->fval;
657
66834
		i = j<0? -1: (j>0? 1: 0);
658
	} else {
659
302
		i = strcmp(getsval(x), getsval(y));
660
	}
661
67136
	tempfree(x);
662
67136
	tempfree(y);
663

67136
	switch (n) {
664
23363
	case LT:	if (i<0) return(True);
665
517
			else return(False);
666
12058
	case LE:	if (i<=0) return(True);
667
14
			else return(False);
668
28642
	case NE:	if (i!=0) return(True);
669
2761
			else return(False);
670
1874
	case EQ:	if (i == 0) return(True);
671
1797
			else return(False);
672
1199
	case GE:	if (i>=0) return(True);
673
1197
			else return(False);
674
	case GT:	if (i>0) return(True);
675
			else return(False);
676
	default:	/* can't happen */
677
		FATAL("unknown relational operator %d", n);
678
	}
679
	return 0;	/*NOTREACHED*/
680
}
681
682
void tfree(Cell *a)	/* free a tempcell */
683
73649
{
684
73649
	if (freeable(a)) {
685

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

63840
	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
63840
	tempfree(x);
728
63840
	x = fieldadr(m);
729
63840
	x->ctype = OCELL;	/* BUG?  why are these needed? */
730
63840
	x->csub = CFLD;
731
63840
	return(x);
732
}
733
734
Cell *substr(Node **a, int nnn)		/* substr(a[0], a[1], a[2]) */
735
23371
{
736
	int k, m, n;
737
	char *s;
738
	int temp;
739
23371
	Cell *x, *y, *z = 0;
740
741
23371
	x = execute(a[0]);
742
23371
	y = execute(a[1]);
743
23371
	if (a[2] != 0)
744
22454
		z = execute(a[2]);
745
23371
	s = getsval(x);
746
23371
	k = strlen(s) + 1;
747
23371
	if (k <= 1) {
748
		tempfree(x);
749
		tempfree(y);
750
		if (a[2] != 0) {
751
			tempfree(z);
752
		}
753
		x = gettemp();
754
		setsval(x, "");
755
		return(x);
756
	}
757
23371
	m = (int) getfval(y);
758
23371
	if (m <= 0)
759
		m = 1;
760
23371
	else if (m > k)
761
		m = k;
762
23371
	tempfree(y);
763
23371
	if (a[2] != 0) {
764
22454
		n = (int) getfval(z);
765
22454
		tempfree(z);
766
	} else
767
917
		n = k - 1;
768
23371
	if (n < 0)
769
		n = 0;
770
23371
	else if (n > k - m)
771
246
		n = k - m;
772
23371
	   dprintf( ("substr: m=%d, n=%d, s=%s\n", m, n, s) );
773
23371
	y = gettemp();
774
23371
	temp = s[n+m-1];	/* with thanks to John Linderman */
775
23371
	s[n+m-1] = '\0';
776
23371
	setsval(y, s + m - 1);
777
23371
	s[n+m-1] = temp;
778
23371
	tempfree(x);
779
23371
	return(y);
780
}
781
782
Cell *sindex(Node **a, int nnn)		/* index(a[0], a[1]) */
783
229
{
784
	Cell *x, *y, *z;
785
	char *s1, *s2, *p1, *p2, *q;
786
229
	Awkfloat v = 0.0;
787
788
229
	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
496
	for (p1 = s1; *p1 != '\0'; p1++) {
795

496
		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
42370
{
812
	char *fmt;
813
	char *p, *t;
814
	const char *os;
815
	Cell *x;
816
42370
	int flag = 0, n;
817
	int fmtwd; /* format width */
818
42370
	int fmtsz = recsize;
819
42370
	char *buf = *pbuf;
820
42370
	int bufsize = *pbufsize;
821
822
42370
	os = s;
823
42370
	p = buf;
824
42370
	if ((fmt = (char *) malloc(fmtsz)) == NULL)
825
		FATAL("out of memory in format()");
826
324013
	while (*s) {
827
281643
		adjbuf(&buf, &bufsize, MAXNUMSIZE+1+p-buf, recsize, &p, "format1");
828
281643
		if (*s != '%') {
829
219558
			*p++ = *s++;
830
219558
			continue;
831
		}
832
62085
		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
62085
		fmtwd = atoi(s+1);
839
62085
		if (fmtwd < 0)
840
			fmtwd = -fmtwd;
841
62085
		adjbuf(&buf, &bufsize, fmtwd+1+p-buf, recsize, &p, "format2");
842
127100
		for (t = fmt; (*t++ = *s) != '\0'; s++) {
843
127100
			if (!adjbuf(&fmt, &fmtsz, MAXNUMSIZE+1+t-fmt, recsize, &t, "format3"))
844
				FATAL("format item %.30s... ran format() out of memory", os);
845


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

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

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

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


47225
	switch (n) {
1018
	case ADD:
1019
747
		i += j;
1020
747
		break;
1021
	case MINUS:
1022
229
		i -= j;
1023
229
		break;
1024
	case MULT:
1025
637
		i *= j;
1026
637
		break;
1027
	case DIVIDE:
1028
		if (j == 0)
1029
			FATAL("division by zero");
1030
		i /= j;
1031
		break;
1032
	case MOD:
1033
45612
		if (j == 0)
1034
			FATAL("division by zero in mod");
1035
45612
		modf(i/j, &v);
1036
45612
		i = i - j * v;
1037
45612
		break;
1038
	case UMINUS:
1039
		i = -i;
1040
		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
47225
	setfval(z, i);
1051
47225
	return(z);
1052
}
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
58943
{
1069
	Cell *x, *z;
1070
	int k;
1071
	Awkfloat xf;
1072
1073
58943
	x = execute(a[0]);
1074
58943
	xf = getfval(x);
1075
58943
	k = (n == PREINCR || n == POSTINCR) ? 1 : -1;
1076
58943
	if (n == PREINCR || n == PREDECR) {
1077
58352
		setfval(x, xf + k);
1078
58352
		return(x);
1079
	}
1080
591
	z = gettemp();
1081
591
	setfval(z, xf);
1082
591
	setfval(x, xf + k);
1083
591
	tempfree(x);
1084
591
	return(z);
1085
}
1086
1087
Cell *assign(Node **a, int n)	/* a[0] = a[1], a[0] += a[1], etc. */
1088
30168
{		/* this is subtle; don't muck with it. */
1089
	Cell *x, *y;
1090
	Awkfloat xf, yf;
1091
	double v;
1092
1093
30168
	y = execute(a[1]);
1094
30168
	x = execute(a[0]);
1095
30168
	if (n == ASSIGN) {	/* ordinary assignment */
1096

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

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

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

969
        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

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

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

4581
			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
740
	} 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
740
	} else if (*s != 0) {
1327
		for (;;) {
1328
785
			n++;
1329
785
			t = s;
1330

33093
			while (*s != sep && *s != '\n' && *s != '\0')
1331
31523
				s++;
1332
785
			temp = *s;
1333
785
			*s = '\0';
1334
785
			snprintf(num, sizeof num, "%d", n);
1335
785
			if (is_number(t))
1336
				setsymtab(num, t, atof(t), STR|NUM, (Array *) ap->sval);
1337
			else
1338
785
				setsymtab(num, t, 0.0, STR, (Array *) ap->sval);
1339
785
			*s = temp;
1340
785
			if (*s++ == 0)
1341
667
				break;
1342
		}
1343
	}
1344
969
	tempfree(ap);
1345
969
	tempfree(y);
1346
969
	if (a[2] != 0 && arg3type == STRING) {
1347
969
		tempfree(x);
1348
	}
1349
969
	x = gettemp();
1350
969
	x->tval = NUM;
1351
969
	x->fval = n;
1352
969
	return(x);
1353
}
1354
1355
Cell *condexpr(Node **a, int n)	/* a[0] ? a[1] : a[2] */
1356
{
1357
	Cell *x;
1358
1359
	x = execute(a[0]);
1360
	if (istrue(x)) {
1361
		tempfree(x);
1362
		x = execute(a[1]);
1363
	} else {
1364
		tempfree(x);
1365
		x = execute(a[2]);
1366
	}
1367
	return(x);
1368
}
1369
1370
Cell *ifstat(Node **a, int n)	/* if (a[0]) a[1]; else a[2] */
1371
26758
{
1372
	Cell *x;
1373
1374
26758
	x = execute(a[0]);
1375
26758
	if (istrue(x)) {
1376
22731
		tempfree(x);
1377
22731
		x = execute(a[1]);
1378
4027
	} else if (a[2] != 0) {
1379
2362
		tempfree(x);
1380
2362
		x = execute(a[2]);
1381
	}
1382
26749
	return(x);
1383
}
1384
1385
Cell *whilestat(Node **a, int n)	/* while (a[0]) a[1] */
1386
{
1387
	Cell *x;
1388
1389
	for (;;) {
1390
		x = execute(a[0]);
1391
		if (!istrue(x))
1392
			return(x);
1393
		tempfree(x);
1394
		x = execute(a[1]);
1395
		if (isbreak(x)) {
1396
			x = True;
1397
			return(x);
1398
		}
1399
		if (isnext(x) || isexit(x) || isret(x))
1400
			return(x);
1401
		tempfree(x);
1402
	}
1403
}
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
533
{
1425
	Cell *x;
1426
1427
533
	x = execute(a[0]);
1428
533
	tempfree(x);
1429
	for (;;) {
1430
38423
		if (a[1]!=0) {
1431
38423
			x = execute(a[1]);
1432
38423
			if (!istrue(x)) return(x);
1433
37890
			else tempfree(x);
1434
		}
1435
37890
		x = execute(a[3]);
1436
37890
		if (isbreak(x))		/* turn off break */
1437
			return True;
1438

37890
		if (isnext(x) || isexit(x) || isret(x))
1439
			return(x);
1440
37890
		tempfree(x);
1441
37890
		x = execute(a[2]);
1442
37890
		tempfree(x);
1443
	}
1444
}
1445
1446
Cell *instat(Node **a, int n)	/* for (a[0] in a[1]) a[2] */
1447
2
{
1448
	Cell *x, *vp, *arrayp, *cp, *ncp;
1449
	Array *tp;
1450
	int i;
1451
1452
2
	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
252
	for (i = 0; i < tp->size; i++) {	/* this routine knows too much */
1460
479
		for (cp = tp->tab[i]; cp != NULL; cp = ncp) {
1461
229
			setsval(vp, cp->nval);
1462
229
			ncp = cp->cnext;
1463
229
			x = execute(a[2]);
1464
229
			if (isbreak(x)) {
1465
				tempfree(vp);
1466
				return True;
1467
			}
1468

229
			if (isnext(x) || isexit(x) || isret(x)) {
1469
				tempfree(vp);
1470
				return(x);
1471
			}
1472
229
			tempfree(x);
1473
		}
1474
	}
1475
2
	return True;
1476
}
1477
1478
Cell *bltin(Node **a, int n)	/* builtin functions. a[0] is type, a[1] is arg list */
1479
621
{
1480
	Cell *x, *y;
1481
	Awkfloat u;
1482
	int t;
1483
	Awkfloat tmp;
1484
	char *p, *buf;
1485
	Node *nextarg;
1486
	FILE *fp;
1487
1488
621
	t = ptoi(a[0]);
1489
621
	x = execute(a[1]);
1490
621
	nextarg = a[1]->nnext;
1491





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

22667
	if (ferror(fp))
1662
		FATAL("write error on %s", filename(fp));
1663
22667
	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
	x = execute(b);
1681
	fname = getsval(x);
1682
	fp = openfile(a, fname);
1683
	if (fp == NULL)
1684
		FATAL("can't open file %s", fname);
1685
	tempfree(x);
1686
	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
31
{
1699
31
	nfiles = FOPEN_MAX;
1700
31
	files = calloc(nfiles, sizeof(*files));
1701
31
	if (files == NULL)
1702
		FATAL("can't allocate file memory for %u files", nfiles);
1703
31
        files[0].fp = stdin;
1704
31
	files[0].fname = "/dev/stdin";
1705
31
	files[0].mode = LT;
1706
31
        files[1].fp = stdout;
1707
31
	files[1].fname = "/dev/stdout";
1708
31
	files[1].mode = GT;
1709
31
        files[2].fp = stderr;
1710
31
	files[2].fname = "/dev/stderr";
1711
31
	files[2].mode = GT;
1712
31
}
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
	if (*s == '\0')
1721
		FATAL("null file name in print or getline");
1722
	for (i=0; i < nfiles; i++)
1723
		if (files[i].fname && strcmp(s, files[i].fname) == 0) {
1724
			if (a == files[i].mode || (a==APPEND && files[i].mode==GT))
1725
				return files[i].fp;
1726
			if (a == FFLUSH)
1727
				return files[i].fp;
1728
		}
1729
	if (a == FFLUSH)	/* didn't find it, so don't create it! */
1730
		return NULL;
1731
1732
	for (i=0; i < nfiles; i++)
1733
		if (files[i].fp == 0)
1734
			break;
1735
	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
	fflush(stdout);	/* force a semblance of order */
1746
	m = a;
1747
	if (a == GT) {
1748
		fp = fopen(s, "w");
1749
	} 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
	if (fp != NULL) {
1761
		files[i].fname = tostring(s);
1762
		files[i].fp = fp;
1763
		files[i].mode = m;
1764
	}
1765
	return fp;
1766
}
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
31
{
1811
	int i, stat;
1812
1813
651
	for (i = 0; i < FOPEN_MAX; i++) {
1814
620
		if (files[i].fp) {
1815

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