GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/ksh/syn.c Lines: 362 415 87.2 %
Date: 2017-11-13 Branches: 219 291 75.3 %

Line Branch Exec Source
1
/*	$OpenBSD: syn.c,v 1.38 2015/12/30 09:07:00 tedu Exp $	*/
2
3
/*
4
 * shell parser (C version)
5
 */
6
7
#include <string.h>
8
9
#include "sh.h"
10
#include "c_test.h"
11
12
struct nesting_state {
13
	int	start_token;	/* token than began nesting (eg, FOR) */
14
	int	start_line;	/* line nesting began on */
15
};
16
17
static void	yyparse(void);
18
static struct op *pipeline(int);
19
static struct op *andor(void);
20
static struct op *c_list(int);
21
static struct ioword *synio(int);
22
static void	musthave(int, int);
23
static struct op *nested(int, int, int);
24
static struct op *get_command(int);
25
static struct op *dogroup(void);
26
static struct op *thenpart(void);
27
static struct op *elsepart(void);
28
static struct op *caselist(void);
29
static struct op *casepart(int);
30
static struct op *function_body(char *, int);
31
static char **	wordlist(void);
32
static struct op *block(int, struct op *, struct op *, char **);
33
static struct op *newtp(int);
34
static void	syntaxerr(const char *) __attribute__((__noreturn__));
35
static void	nesting_push(struct nesting_state *, int);
36
static void	nesting_pop(struct nesting_state *);
37
static int	assign_command(char *);
38
static int	inalias(struct source *);
39
static int	dbtestp_isa(Test_env *, Test_meta);
40
static const char *dbtestp_getopnd(Test_env *, Test_op, int);
41
static int	dbtestp_eval(Test_env *, Test_op, const char *, const char *,
42
		    int);
43
static void	dbtestp_error(Test_env *, int, const char *);
44
45
static	struct	op	*outtree; /* yyparse output */
46
47
static struct nesting_state nesting;	/* \n changed to ; */
48
49
static	int	reject;		/* token(cf) gets symbol again */
50
static	int	symbol;		/* yylex value */
51
52
#define	token(cf) \
53
	((reject) ? (reject = false, symbol) : (symbol = yylex(cf)))
54
#define	tpeek(cf) \
55
	((reject) ? (symbol) : (reject = true, symbol = yylex(cf)))
56
57
static void
58
yyparse(void)
59
{
60
	int c;
61
62
5044063
	reject = false;
63
64
2521701
	outtree = c_list(source->type == SSTRING);
65
7565103
	c = tpeek(0);
66
2521701
	if (c == 0 && !outtree)
67
189156
		outtree = newtp(TEOF);
68
2332545
	else if (c != '\n' && c != 0)
69
		syntaxerr(NULL);
70
2521695
}
71
72
static struct op *
73
pipeline(int cf)
74
{
75
	struct op *t, *p, *tl = NULL;
76
77
7654903
	t = get_command(cf);
78
3827121
	if (t != NULL) {
79

18154136
		while (token(0) == '|') {
80
1644250
			if ((p = get_command(CONTIN)) == NULL)
81
				syntaxerr(NULL);
82
1644250
			if (tl == NULL)
83
1236559
				t = tl = block(TPIPE, t, p, NULL);
84
			else
85
407691
				tl = tl->right = block(TPIPE, tl->right, p, NULL);
86
		}
87
2894284
		reject = true;
88
2894284
	}
89
3827121
	return (t);
90
}
91
92
static struct op *
93
andor(void)
94
{
95
	struct op *t, *p;
96
	int c;
97
98
7518447
	t = pipeline(0);
99
3758893
	if (t != NULL) {
100

11569132
		while ((c = token(0)) == LOGAND || c == LOGOR) {
101
66227
			if ((p = pipeline(CONTIN)) == NULL)
102
				syntaxerr(NULL);
103
66227
			t = block(c == LOGAND? TAND: TOR, t, p, NULL);
104
		}
105
2826056
		reject = true;
106
2826056
	}
107
3758893
	return (t);
108
}
109
110
static struct op *
111
c_list(int multi)
112
{
113
	struct op *t = NULL, *p, *tl = NULL;
114
	int c;
115
	int have_sep;
116
117
6337696
	while (1) {
118
3758893
		p = andor();
119
		/* Token has always been read/rejected at this point, so
120
		 * we don't worry about what flags to pass token()
121
		 */
122
11276679
		c = token(0);
123
		have_sep = 1;
124

6044569
		if (c == '\n' && (multi || inalias(source))) {
125
538704
			if (!p) /* ignore blank lines */
126
125209
				continue;
127
3220189
		} else if (!p)
128
			break;
129
2412561
		else if (c == '&' || c == COPROC)
130
490
			p = block(c == '&' ? TASYNC : TCOPROC,
131
				  p, NULL, NULL);
132
2412071
		else if (c != ';')
133
1895062
			have_sep = 0;
134
2826056
		if (!t)
135
2070024
			t = p;
136
756032
		else if (!tl)
137
380064
			t = tl = block(TLIST, t, p, NULL);
138
		else
139
375968
			tl = tl->right = block(TLIST, tl->right, p, NULL);
140
2826056
		if (!have_sep)
141
			break;
142
	}
143
2702690
	reject = true;
144
2702690
	return t;
145
}
146
147
static struct ioword *
148
synio(int cf)
149
{
150
	struct ioword *iop;
151
	int ishere;
152
153

19418300
	if (tpeek(cf) != REDIR)
154
4564696
		return NULL;
155
289879
	reject = false;
156
289879
	iop = yylval.iop;
157
289879
	ishere = (iop->flag&IOTYPE) == IOHERE;
158
289879
	musthave(LWORD, ishere ? HEREDELIM : 0);
159
289879
	if (ishere) {
160
2278
		iop->delim = yylval.cp;
161
2278
		if (*ident != 0) /* unquoted */
162
2178
			iop->flag |= IOEVAL;
163
2278
		if (herep >= &heres[HERES])
164
			yyerror("too many <<'s\n");
165
2278
		*herep++ = iop;
166
2278
	} else
167
287601
		iop->name = yylval.cp;
168
289879
	return iop;
169
4854575
}
170
171
static void
172
musthave(int c, int cf)
173
{
174

1914568
	if ((token(cf)) != c)
175
		syntaxerr(NULL);
176
478642
}
177
178
static struct op *
179
nested(int type, int smark, int emark)
180
{
181
	struct op *t;
182
61746
	struct nesting_state old_nesting;
183
184
30873
	nesting_push(&old_nesting, smark);
185
30873
	t = c_list(true);
186
30873
	musthave(emark, KEYWORD|ALIAS);
187
30873
	nesting_pop(&old_nesting);
188
61746
	return (block(type, t, NULL, NULL));
189
30873
}
190
191
static struct op *
192
get_command(int cf)
193
{
194
	struct op *t;
195
	int c, iopn = 0, syniocf;
196
	struct ioword *iop, **iops;
197
10996388
	XPtrV args, vars;
198
5498194
	struct nesting_state old_nesting;
199
200
5498194
	iops = areallocarray(NULL, NUFILE + 1,
201
5498194
	    sizeof(struct ioword *), ATEMP);
202
5498194
	XPinit(args, 16);
203
5498194
	XPinit(vars, 16);
204
205
	syniocf = KEYWORD|ALIAS;
206




16493927
	switch (c = token(cf|KEYWORD|ALIAS|VARASN)) {
207
	default:
208
932837
		reject = true;
209
932837
		afree(iops, ATEMP);
210
932837
		XPfree(args);
211
932837
		XPfree(vars);
212
932837
		return NULL; /* empty line */
213
214
	case LWORD:
215
	case REDIR:
216
4468205
		reject = true;
217
		syniocf &= ~(KEYWORD|ALIAS);
218
4468205
		t = newtp(TCOM);
219
4468205
		t->lineno = source->line;
220
17097340
		while (1) {
221
34194680
			cf = (t->u.evalflags ? ARRAYVAR : 0) |
222
17097340
			    (XPsize(args) == 0 ? ALIAS|VARASN : CMDWORD);
223

51298911
			switch (tpeek(cf)) {
224
			case REDIR:
225
289042
				if (iopn >= NUFILE)
226
					yyerror("too many redirections\n");
227
289042
				iops[iopn++] = synio(cf);
228
289042
				break;
229
230
			case LWORD:
231
12340093
				reject = false;
232
				/* the iopn == 0 and XPsize(vars) == 0 are
233
				 * dubious but at&t ksh acts this way
234
				 */
235

29146914
				if (iopn == 0 && XPsize(vars) == 0 &&
236
12174856
				    XPsize(args) == 0 &&
237
4468187
				    assign_command(ident))
238
113693
					t->u.evalflags = DOVACHECK;
239

24680186
				if ((XPsize(args) == 0 || Flag(FKEYWORD)) &&
240
4551500
				    is_wdvarassign(yylval.cp))
241
413138
					XPput(vars, yylval.cp);
242
				else
243
24279791
					XPput(args, yylval.cp);
244
				break;
245
246
			case '(':
247
				/* Check for "> foo (echo hi)", which at&t ksh
248
				 * allows (not POSIX, but not disallowed)
249
				 */
250
26108
				afree(t, ATEMP);
251

26114
				if (XPsize(args) == 0 && XPsize(vars) == 0) {
252
6
					reject = false;
253
					goto Subshell;
254
				}
255
				/* Must be a function */
256

78306
				if (iopn != 0 || XPsize(args) != 1 ||
257
26102
				    XPsize(vars) != 0)
258
					syntaxerr(NULL);
259
26102
				reject = false;
260
				/*(*/
261
26102
				musthave(')', 0);
262
26102
				t = function_body(XPptrv(args)[0], false);
263
26102
				goto Leave;
264
265
			default:
266
				goto Leave;
267
			}
268
		}
269
	  Leave:
270
6
		break;
271
272
	  Subshell:
273
	case '(':
274
4565
		t = nested(TPAREN, '(', ')');
275
4565
		break;
276
277
	case '{': /*}*/
278
26308
		t = nested(TBRACE, '{', '}');
279
26308
		break;
280
281
	case MDPAREN:
282
	  {
283
		static const char let_cmd[] = {
284
			CHAR, 'l', CHAR, 'e',
285
			CHAR, 't', EOS
286
		};
287
		/* Leave KEYWORD in syniocf (allow if (( 1 )) then ...) */
288
12
		t = newtp(TCOM);
289
12
		t->lineno = source->line;
290
12
		reject = false;
291
24
		XPput(args, wdcopy(let_cmd, ATEMP));
292
12
		musthave(LWORD,LETEXPR);
293
24
		XPput(args, yylval.cp);
294
12
		break;
295
	  }
296
297
	case DBRACKET: /* [[ .. ]] */
298
		/* Leave KEYWORD in syniocf (allow if [[ -n 1 ]] then ...) */
299
330
		t = newtp(TDBRACKET);
300
330
		reject = false;
301
		{
302
330
			Test_env te;
303
304
330
			te.flags = TEF_DBRACKET;
305
330
			te.pos.av = &args;
306
330
			te.isa = dbtestp_isa;
307
330
			te.getopnd = dbtestp_getopnd;
308
330
			te.eval = dbtestp_eval;
309
330
			te.error = dbtestp_error;
310
311
330
			test_parse(&te);
312
330
		}
313
330
		break;
314
315
	case FOR:
316
	case SELECT:
317
5818
		t = newtp((c == FOR) ? TFOR : TSELECT);
318
5818
		musthave(LWORD, ARRAYVAR);
319
5818
		if (!is_wdvarname(yylval.cp, true))
320
			yyerror("%s: bad identifier\n",
321
			    c == FOR ? "for" : "select");
322
5818
		t->str = str_save(ident, ATEMP);
323
5818
		nesting_push(&old_nesting, c);
324
5818
		t->vars = wordlist();
325
5818
		t->left = dogroup();
326
5818
		nesting_pop(&old_nesting);
327
5818
		break;
328
329
	case WHILE:
330
	case UNTIL:
331
4089
		nesting_push(&old_nesting, c);
332
4089
		t = newtp((c == WHILE) ? TWHILE : TUNTIL);
333
4089
		t->left = c_list(true);
334
4089
		t->right = dogroup();
335
4089
		nesting_pop(&old_nesting);
336
4089
		break;
337
338
	case CASE:
339
981
		t = newtp(TCASE);
340
981
		musthave(LWORD, 0);
341
981
		t->str = yylval.cp;
342
981
		nesting_push(&old_nesting, c);
343
981
		t->left = caselist();
344
981
		nesting_pop(&old_nesting);
345
981
		break;
346
347
	case IF:
348
52339
		nesting_push(&old_nesting, c);
349
52339
		t = newtp(TIF);
350
52339
		t->left = c_list(true);
351
52339
		t->right = thenpart();
352
52339
		musthave(FI, KEYWORD|ALIAS);
353
52339
		nesting_pop(&old_nesting);
354
52339
		break;
355
356
	case BANG:
357
		syniocf &= ~(KEYWORD|ALIAS);
358
643
		t = pipeline(0);
359
643
		if (t == NULL)
360
			syntaxerr(NULL);
361
643
		t = block(TBANG, NULL, t, NULL);
362
643
		break;
363
364
	case TIME:
365
		syniocf &= ~(KEYWORD|ALIAS);
366
1358
		t = pipeline(0);
367
1358
		if (t) {
368
1358
			t->str = alloc(2, ATEMP);
369
1358
			t->str[0] = '\0'; /* TF_* flags */
370
1358
			t->str[1] = '\0';
371
1358
		}
372
1358
		t = block(TTIME, t, NULL, NULL);
373
1358
		break;
374
375
	case FUNCTION:
376
60
		musthave(LWORD, 0);
377
60
		t = function_body(yylval.cp, true);
378
60
		break;
379
	}
380
381
9131066
	while ((iop = synio(syniocf)) != NULL) {
382
837
		if (iopn >= NUFILE)
383
			yyerror("too many redirections\n");
384
837
		iops[iopn++] = iop;
385
	}
386
387
4564696
	if (iopn == 0) {
388
4351972
		afree(iops, ATEMP);
389
		t->ioact = NULL;
390
4351972
	} else {
391
212724
		iops[iopn++] = NULL;
392
425448
		iops = areallocarray(iops, iopn,
393
212724
		    sizeof(struct ioword *), ATEMP);
394
		t->ioact = iops;
395
	}
396
397

4687289
	if (t->type == TCOM || t->type == TDBRACKET) {
398
8885158
		XPput(args, NULL);
399
4442433
		t->args = (char **) XPclose(args);
400
8884866
		XPput(vars, NULL);
401
4442433
		t->vars = (char **) XPclose(vars);
402
4442433
	} else {
403
122263
		XPfree(args);
404
122263
		XPfree(vars);
405
	}
406
407
4564696
	return t;
408
5497533
}
409
410
static struct op *
411
dogroup(void)
412
{
413
	int c;
414
	struct op *list;
415
416
39628
	c = token(CONTIN|KEYWORD|ALIAS);
417
	/* A {...} can be used instead of do...done for for/select loops
418
	 * but not for while/until loops - we don't need to check if it
419
	 * is a while loop because it would have been parsed as part of
420
	 * the conditional command list...
421
	 */
422
9907
	if (c == DO)
423
9907
		c = DONE;
424
	else if (c == '{')
425
		c = '}';
426
	else
427
		syntaxerr(NULL);
428
9907
	list = c_list(true);
429
9907
	musthave(c, KEYWORD|ALIAS);
430
9907
	return list;
431
}
432
433
static struct op *
434
thenpart(void)
435
{
436
	struct op *t;
437
438
104898
	musthave(THEN, KEYWORD|ALIAS);
439
52449
	t = newtp(0);
440
52449
	t->left = c_list(true);
441
52449
	if (t->left == NULL)
442
		syntaxerr(NULL);
443
52449
	t->right = elsepart();
444
52449
	return (t);
445
}
446
447
static struct op *
448
elsepart(void)
449
{
450
	struct op *t;
451
452

209796
	switch (token(KEYWORD|ALIAS|VARASN)) {
453
	case ELSE:
454
28381
		if ((t = c_list(true)) == NULL)
455
			syntaxerr(NULL);
456
28381
		return (t);
457
458
	case ELIF:
459
110
		t = newtp(TELIF);
460
110
		t->left = c_list(true);
461
110
		t->right = thenpart();
462
110
		return (t);
463
464
	default:
465
23958
		reject = true;
466
	}
467
23958
	return NULL;
468
52449
}
469
470
static struct op *
471
caselist(void)
472
{
473
	struct op *t, *tl;
474
	int c;
475
476
3924
	c = token(CONTIN|KEYWORD|ALIAS);
477
	/* A {...} can be used instead of in...esac for case statements */
478
981
	if (c == IN)
479
981
		c = ESAC;
480
	else if (c == '{')
481
		c = '}';
482
	else
483
		syntaxerr(NULL);
484
	t = tl = NULL;
485

15288
	while ((tpeek(CONTIN|KEYWORD|ESACONLY)) != c) { /* no ALIAS here */
486
2841
		struct op *tc = casepart(c);
487
2841
		if (tl == NULL)
488
981
			t = tl = tc, tl->right = NULL;
489
		else
490
1860
			tl->right = tc, tl = tc;
491
	}
492
981
	musthave(c, KEYWORD|ALIAS);
493
981
	return (t);
494
}
495
496
static struct op *
497
casepart(int endtok)
498
{
499
	struct op *t;
500
	int c;
501
	XPtrV ptns;
502
503
5682
	XPinit(ptns, 16);
504
2841
	t = newtp(TPAT);
505
8523
	c = token(CONTIN|KEYWORD); /* no ALIAS here */
506
2841
	if (c != '(')
507
2799
		reject = true;
508
2841
	do {
509
3619
		musthave(LWORD, 0);
510
7238
		XPput(ptns, yylval.cp);
511

10857
	} while ((c = token(0)) == '|');
512
2841
	reject = true;
513
5682
	XPput(ptns, NULL);
514
2841
	t->vars = (char **) XPclose(ptns);
515
2841
	musthave(')', 0);
516
517
2841
	t->left = c_list(true);
518
	/* Note: Posix requires the ;; */
519

8523
	if ((tpeek(CONTIN|KEYWORD|ALIAS)) != endtok)
520
2721
		musthave(BREAK, CONTIN|KEYWORD|ALIAS);
521
2841
	return (t);
522
}
523
524
static struct op *
525
function_body(char *name,
526
    int ksh_func)		/* function foo { ... } vs foo() { .. } */
527
{
528
	char *sname, *p;
529
	struct op *t;
530
	int old_func_parse;
531
532
52324
	sname = wdstrip(name);
533
	/* Check for valid characters in name.  posix and ksh93 say only
534
	 * allow [a-zA-Z_0-9] but this allows more as old pdksh's have
535
	 * allowed more (the following were never allowed:
536
	 *	nul space nl tab $ ' " \ ` ( ) & | ; = < >
537
	 *  C_QUOTE covers all but = and adds # [ ? *)
538
	 */
539
398182
	for (p = sname; *p; p++)
540

345858
		if (ctype(*p, C_QUOTE) || *p == '=')
541
			yyerror("%s: invalid function name\n", sname);
542
543
26162
	t = newtp(TFUNCT);
544
26162
	t->str = sname;
545
26162
	t->u.ksh_func = ksh_func;
546
26162
	t->lineno = source->line;
547
548
	/* Note that POSIX allows only compound statements after foo(), sh and
549
	 * at&t ksh allow any command, go with the later since it shouldn't
550
	 * break anything.  However, for function foo, at&t ksh only accepts
551
	 * an open-brace.
552
	 */
553
26162
	if (ksh_func) {
554
60
		musthave('{', CONTIN|KEYWORD|ALIAS); /* } */
555
60
		reject = true;
556
60
	}
557
558
26162
	old_func_parse = genv->flags & EF_FUNC_PARSE;
559
26162
	genv->flags |= EF_FUNC_PARSE;
560
26162
	if ((t->left = get_command(CONTIN)) == NULL) {
561
		/*
562
		 * Probably something like foo() followed by eof or ;.
563
		 * This is accepted by sh and ksh88.
564
		 * To make "typeset -f foo" work reliably (so its output can
565
		 * be used as input), we pretend there is a colon here.
566
		 */
567
		t->left = newtp(TCOM);
568
		t->left->args = areallocarray(NULL, 2, sizeof(char *), ATEMP);
569
		t->left->args[0] = alloc(3, ATEMP);
570
		t->left->args[0][0] = CHAR;
571
		t->left->args[0][1] = ':';
572
		t->left->args[0][2] = EOS;
573
		t->left->args[1] = NULL;
574
		t->left->vars = alloc(sizeof(char *), ATEMP);
575
		t->left->vars[0] = NULL;
576
		t->left->lineno = 1;
577
	}
578
26162
	if (!old_func_parse)
579
26156
		genv->flags &= ~EF_FUNC_PARSE;
580
581
26162
	return t;
582
}
583
584
static char **
585
wordlist(void)
586
{
587
	int c;
588
	XPtrV args;
589
590
11636
	XPinit(args, 16);
591
	/* Posix does not do alias expansion here... */
592

17454
	if ((c = token(CONTIN|KEYWORD|ALIAS)) != IN) {
593
108
		if (c != ';') /* non-POSIX, but at&t ksh accepts a ; here */
594
			reject = true;
595
108
		return NULL;
596
	}
597

107580
	while ((c = token(0)) == LWORD)
598
42533
		XPput(args, yylval.cp);
599
5710
	if (c != '\n' && c != ';')
600
		syntaxerr(NULL);
601
11427
	XPput(args, NULL);
602
5710
	return (char **) XPclose(args);
603
5818
}
604
605
/*
606
 * supporting functions
607
 */
608
609
static struct op *
610
block(int type, struct op *t1, struct op *t2, char **wp)
611
{
612
	struct op *t;
613
614
4999746
	t = newtp(type);
615
2499873
	t->left = t1;
616
2499873
	t->right = t2;
617
2499873
	t->vars = wp;
618
2499873
	return (t);
619
}
620
621
const	struct tokeninfo {
622
	const char *name;
623
	short	val;
624
	short	reserved;
625
} tokentab[] = {
626
	/* Reserved words */
627
	{ "if",		IF,	true },
628
	{ "then",	THEN,	true },
629
	{ "else",	ELSE,	true },
630
	{ "elif",	ELIF,	true },
631
	{ "fi",		FI,	true },
632
	{ "case",	CASE,	true },
633
	{ "esac",	ESAC,	true },
634
	{ "for",	FOR,	true },
635
	{ "select",	SELECT,	true },
636
	{ "while",	WHILE,	true },
637
	{ "until",	UNTIL,	true },
638
	{ "do",		DO,	true },
639
	{ "done",	DONE,	true },
640
	{ "in",		IN,	true },
641
	{ "function",	FUNCTION, true },
642
	{ "time",	TIME,	true },
643
	{ "{",		'{',	true },
644
	{ "}",		'}',	true },
645
	{ "!",		BANG,	true },
646
	{ "[[",		DBRACKET, true },
647
	/* Lexical tokens (0[EOF], LWORD and REDIR handled specially) */
648
	{ "&&",		LOGAND,	false },
649
	{ "||",		LOGOR,	false },
650
	{ ";;",		BREAK,	false },
651
	{ "((",		MDPAREN, false },
652
	{ "|&",		COPROC,	false },
653
	/* and some special cases... */
654
	{ "newline",	'\n',	false },
655
	{ 0 }
656
};
657
658
void
659
initkeywords(void)
660
{
661
	struct tokeninfo const *tt;
662
	struct tbl *p;
663
664
209526
	ktinit(&keywords, APERM, 32); /* must be 2^n (currently 20 keywords) */
665
5657202
	for (tt = tokentab; tt->name; tt++) {
666
2723838
		if (tt->reserved) {
667
2095260
			p = ktenter(&keywords, tt->name, hash(tt->name));
668
2095260
			p->flag |= DEFINED|ISSET;
669
2095260
			p->type = CKEYWD;
670
2095260
			p->val.i = tt->val;
671
2095260
		}
672
	}
673
104763
}
674
675
static void
676
syntaxerr(const char *what)
677
{
678
12
	char redir[6];	/* 2<<- is the longest redirection, I think */
679
	const char *s;
680
	struct tokeninfo const *tt;
681
	int c;
682
683
6
	if (!what)
684
6
		what = "unexpected";
685
6
	reject = true;
686
18
	c = token(0);
687
    Again:
688

6
	switch (c) {
689
	case 0:
690
		if (nesting.start_token) {
691
			c = nesting.start_token;
692
			source->errline = nesting.start_line;
693
			what = "unmatched";
694
			goto Again;
695
		}
696
		/* don't quote the EOF */
697
		yyerror("syntax error: unexpected EOF\n");
698
		/* NOTREACHED */
699
700
	case LWORD:
701
		s = snptreef(NULL, 32, "%S", yylval.cp);
702
		break;
703
704
	case REDIR:
705
		s = snptreef(redir, sizeof(redir), "%R", yylval.iop);
706
		break;
707
708
	default:
709
324
		for (tt = tokentab; tt->name; tt++)
710
156
			if (tt->val == c)
711
			    break;
712
6
		if (tt->name)
713
			s = tt->name;
714
		else {
715
6
			if (c > 0 && c < 256) {
716
6
				redir[0] = c;
717
6
				redir[1] = '\0';
718
6
			} else
719
				shf_snprintf(redir, sizeof(redir),
720
					"?%d", c);
721
6
			s = redir;
722
		}
723
	}
724
	yyerror("syntax error: `%s' %s\n", s, what);
725
}
726
727
static void
728
nesting_push(struct nesting_state *save, int tok)
729
{
730
188200
	*save = nesting;
731
94100
	nesting.start_token = tok;
732
94100
	nesting.start_line = source->line;
733
94100
}
734
735
static void
736
nesting_pop(struct nesting_state *saved)
737
{
738
188200
	nesting = *saved;
739
94100
}
740
741
static struct op *
742
newtp(int type)
743
{
744
	struct op *t;
745
746
14604730
	t = alloc(sizeof(*t), ATEMP);
747
7302365
	t->type = type;
748
7302365
	t->u.evalflags = 0;
749
7302365
	t->args = t->vars = NULL;
750
7302365
	t->ioact = NULL;
751
7302365
	t->left = t->right = NULL;
752
7302365
	t->str = NULL;
753
7302365
	return (t);
754
}
755
756
struct op *
757
compile(Source *s)
758
{
759
5044724
	nesting.start_token = 0;
760
2522362
	nesting.start_line = 0;
761
2522362
	herep = heres;
762
2522362
	source = s;
763
2522362
	yyparse();
764
2522362
	return outtree;
765
}
766
767
/* This kludge exists to take care of sh/at&t ksh oddity in which
768
 * the arguments of alias/export/readonly/typeset have no field
769
 * splitting, file globbing, or (normal) tilde expansion done.
770
 * at&t ksh seems to do something similar to this since
771
 *	$ touch a=a; typeset a=[ab]; echo "$a"
772
 *	a=[ab]
773
 *	$ x=typeset; $x a=[ab]; echo "$a"
774
 *	a=a
775
 *	$
776
 */
777
static int
778
assign_command(char *s)
779
{
780

13404549
	if (Flag(FPOSIX) || !*s)
781
313334
		return 0;
782
8309706
	return (strcmp(s, "alias") == 0) ||
783
4154679
	    (strcmp(s, "export") == 0) ||
784
12447983
	    (strcmp(s, "readonly") == 0) ||
785
4146523
	    (strcmp(s, "typeset") == 0);
786
4468187
}
787
788
/* Check if we are in the middle of reading an alias */
789
static int
790
inalias(struct source *s)
791
{
792

3494322
	for (; s && s->type == SALIAS; s = s->next)
793
150
		if (!(s->flags & SF_ALIASEND))
794
72
			return 1;
795
873450
	return 0;
796
873522
}
797
798
799
/* Order important - indexed by Test_meta values
800
 * Note that ||, &&, ( and ) can't appear in as unquoted strings
801
 * in normal shell input, so these can be interpreted unambiguously
802
 * in the evaluation pass.
803
 */
804
static const char dbtest_or[] = { CHAR, '|', CHAR, '|', EOS };
805
static const char dbtest_and[] = { CHAR, '&', CHAR, '&', EOS };
806
static const char dbtest_not[] = { CHAR, '!', EOS };
807
static const char dbtest_oparen[] = { CHAR, '(', EOS };
808
static const char dbtest_cparen[] = { CHAR, ')', EOS };
809
const char *const dbtest_tokens[] = {
810
	dbtest_or, dbtest_and, dbtest_not,
811
	dbtest_oparen, dbtest_cparen
812
};
813
const char db_close[] = { CHAR, ']', CHAR, ']', EOS };
814
const char db_lthan[] = { CHAR, '<', EOS };
815
const char db_gthan[] = { CHAR, '>', EOS };
816
817
/* Test if the current token is a whatever.  Accepts the current token if
818
 * it is.  Returns 0 if it is not, non-zero if it is (in the case of
819
 * TM_UNOP and TM_BINOP, the returned value is a Test_op).
820
 */
821
static int
822
dbtestp_isa(Test_env *te, Test_meta meta)
823
{
824
9072
	int c = tpeek(ARRAYVAR | (meta == TM_BINOP ? 0 : CONTIN));
825
	int uqword = 0;
826
	char *save = NULL;
827
	int ret = 0;
828
829
	/* unquoted word? */
830
2268
	uqword = c == LWORD && *ident;
831
832
2268
	if (meta == TM_OR)
833
330
		ret = c == LOGOR;
834
1938
	else if (meta == TM_AND)
835
330
		ret = c == LOGAND;
836
1608
	else if (meta == TM_NOT)
837
702
		ret = uqword && strcmp(yylval.cp, dbtest_tokens[(int) TM_NOT]) == 0;
838
1278
	else if (meta == TM_OPAREN)
839
330
		ret = c == '(' /*)*/;
840
948
	else if (meta == TM_CPAREN)
841
		ret = c == /*(*/ ')';
842
948
	else if (meta == TM_UNOP || meta == TM_BINOP) {
843

618
		if (meta == TM_BINOP && c == REDIR &&
844
		    (yylval.iop->flag == IOREAD || yylval.iop->flag == IOWRITE)) {
845
			ret = 1;
846
			save = wdcopy(yylval.iop->flag == IOREAD ?
847
			    db_lthan : db_gthan, ATEMP);
848

948
		} else if (uqword && (ret = (int) test_isop(te, meta, ident)))
849
330
			save = yylval.cp;
850
	} else /* meta == TM_END */
851
990
		ret = uqword && strcmp(yylval.cp, db_close) == 0;
852
2268
	if (ret) {
853
660
		reject = false;
854
660
		if (meta != TM_END) {
855
330
			if (!save)
856
				save = wdcopy(dbtest_tokens[(int) meta], ATEMP);
857
660
			XPput(*te->pos.av, save);
858
330
		}
859
	}
860
2268
	return ret;
861
}
862
863
static const char *
864
dbtestp_getopnd(Test_env *te, Test_op op, int do_eval)
865
{
866
2472
	int c = tpeek(ARRAYVAR);
867
868
618
	if (c != LWORD)
869
		return NULL;
870
871
618
	reject = false;
872
1236
	XPput(*te->pos.av, yylval.cp);
873
874
618
	return null;
875
618
}
876
877
static int
878
dbtestp_eval(Test_env *te, Test_op op, const char *opnd1, const char *opnd2,
879
    int do_eval)
880
{
881
660
	return 1;
882
}
883
884
static void
885
dbtestp_error(Test_env *te, int offset, const char *msg)
886
{
887
	te->flags |= TEF_ERROR;
888
889
	if (offset < 0) {
890
		reject = true;
891
		/* Kludgy to say the least... */
892
		symbol = LWORD;
893
		yylval.cp = *(XPptrv(*te->pos.av) + XPsize(*te->pos.av) +
894
		    offset);
895
	}
896
	syntaxerr(msg);
897
}