GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/ksh/syn.c Lines: 362 413 87.7 %
Date: 2017-11-07 Branches: 225 293 76.8 %

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
17525151
	reject = false;
63
64
8761132
	outtree = c_list(source->type == SSTRING);
65
26283396
	c = tpeek(0);
66
8761132
	if (c == 0 && !outtree)
67
1035387
		outtree = newtp(TEOF);
68
7725745
	else if (c != '\n' && c != 0)
69
		syntaxerr(NULL);
70
8761106
}
71
72
static struct op *
73
pipeline(int cf)
74
{
75
	struct op *t, *p, *tl = NULL;
76
77
53132419
	t = get_command(cf);
78
26564766
	if (t != NULL) {
79

58140297
		while (token(0) == '|') {
80
3193009
			if ((p = get_command(CONTIN)) == NULL)
81
				syntaxerr(NULL);
82
3193009
			if (tl == NULL)
83
2472965
				t = tl = block(TPIPE, t, p, NULL);
84
			else
85
720044
				tl = tl->right = block(TPIPE, tl->right, p, NULL);
86
		}
87
16187090
		reject = true;
88
16187090
	}
89
26564766
	return (t);
90
}
91
92
static struct op *
93
andor(void)
94
{
95
	struct op *t, *p;
96
	int c;
97
98
51623623
	t = pipeline(0);
99
25810368
	if (t != NULL) {
100

49273528
		while ((c = token(0)) == LOGAND || c == LOGOR) {
101
743863
			if ((p = pipeline(CONTIN)) == NULL)
102
				syntaxerr(NULL);
103
743863
			t = block(c == LOGAND? TAND: TOR, t, p, NULL);
104
		}
105
15432692
		reject = true;
106
15432692
	}
107
25810368
	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
26484798
	while (1) {
118
25810368
		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
77431104
		c = token(0);
123
		have_sep = 1;
124

44965220
		if (c == '\n' && (multi || inalias(source))) {
125
10014788
			if (!p) /* ignore blank lines */
126
				continue;
127
15795580
		} else if (!p)
128
			break;
129
9025052
		else if (c == '&' || c == COPROC)
130
1844
			p = block(c == '&' ? TASYNC : TCOPROC,
131
				  p, NULL, NULL);
132
9023208
		else if (c != ';')
133
6468984
			have_sep = 0;
134
15432692
		if (!t)
135
10042839
			t = p;
136
5389853
		else if (!tl)
137
2316020
			t = tl = block(TLIST, t, p, NULL);
138
		else
139
3073833
			tl = tl->right = block(TLIST, tl->right, p, NULL);
140
15432692
		if (!have_sep)
141
			break;
142
	}
143
13239512
	reject = true;
144
13239512
	return t;
145
}
146
147
static struct ioword *
148
synio(int cf)
149
{
150
	struct ioword *iop;
151
	int ishere;
152
153

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

42574008
	if ((token(cf)) != c)
175
		syntaxerr(NULL);
176
10643502
}
177
178
static struct op *
179
nested(int type, int smark, int emark)
180
{
181
	struct op *t;
182
2315894
	struct nesting_state old_nesting;
183
184
1157947
	nesting_push(&old_nesting, smark);
185
1157947
	t = c_list(true);
186
1157947
	musthave(emark, KEYWORD|ALIAS);
187
1157947
	nesting_pop(&old_nesting);
188
2315894
	return (block(type, t, NULL, NULL));
189
1157947
}
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
59689864
	XPtrV args, vars;
198
29844932
	struct nesting_state old_nesting;
199
200
29844932
	iops = areallocarray(NULL, NUFILE + 1,
201
29844932
	    sizeof(struct ioword *), ATEMP);
202
29844932
	XPinit(args, 16);
203
29844932
	XPinit(vars, 16);
204
205
	syniocf = KEYWORD|ALIAS;
206




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

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

97083194
				if (iopn == 0 && XPsize(vars) == 0 &&
236
39702428
				    XPsize(args) == 0 &&
237
16992224
				    assign_command(ident))
238
261050
					t->u.evalflags = DOVACHECK;
239

80093528
				if ((XPsize(args) == 0 || Flag(FKEYWORD)) &&
240
17187881
				    is_wdvarassign(yylval.cp))
241
7998850
					XPput(vars, yylval.cp);
242
				else
243
72120020
					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
84137
				afree(t, ATEMP);
251

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

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

22018812
	if (t->type == TCOM || t->type == TDBRACKET) {
398
33842214
		XPput(args, NULL);
399
16920327
		t->args = (char **) XPclose(args);
400
33840654
		XPput(vars, NULL);
401
16920327
		t->vars = (char **) XPclose(vars);
402
16920327
	} else {
403
2544042
		XPfree(args);
404
2544042
		XPfree(vars);
405
	}
406
407
19464369
	return t;
408
29842045
}
409
410
static struct op *
411
dogroup(void)
412
{
413
	int c;
414
	struct op *list;
415
416
718268
	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
179567
	if (c == DO)
423
179567
		c = DONE;
424
	else if (c == '{')
425
		c = '}';
426
	else
427
		syntaxerr(NULL);
428
179567
	list = c_list(true);
429
179567
	musthave(c, KEYWORD|ALIAS);
430
179567
	return list;
431
}
432
433
static struct op *
434
thenpart(void)
435
{
436
	struct op *t;
437
438
1737828
	musthave(THEN, KEYWORD|ALIAS);
439
868914
	t = newtp(0);
440
868914
	t->left = c_list(true);
441
868914
	if (t->left == NULL)
442
		syntaxerr(NULL);
443
868914
	t->right = elsepart();
444
868914
	return (t);
445
}
446
447
static struct op *
448
elsepart(void)
449
{
450
	struct op *t;
451
452

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

4526504
	while ((tpeek(CONTIN|KEYWORD|ESACONLY)) != c) { /* no ALIAS here */
486
862197
		struct op *tc = casepart(c);
487
862197
		if (tl == NULL)
488
269429
			t = tl = tc, tl->right = NULL;
489
		else
490
592768
			tl->right = tc, tl = tc;
491
	}
492
269429
	musthave(c, KEYWORD|ALIAS);
493
269429
	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
1724394
	XPinit(ptns, 16);
504
862197
	t = newtp(TPAT);
505
2586591
	c = token(CONTIN|KEYWORD); /* no ALIAS here */
506
862197
	if (c != '(')
507
862022
		reject = true;
508
	do {
509
2241418
		musthave(LWORD, 0);
510
4486392
		XPput(ptns, yylval.cp);
511

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

2586591
	if ((tpeek(CONTIN|KEYWORD|ALIAS)) != endtok)
520
858414
		musthave(BREAK, CONTIN|KEYWORD|ALIAS);
521
862197
	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
168540
	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
1663826
	for (p = sname; *p; p++)
540

1495286
		if (ctype(*p, C_QUOTE) || *p == '=')
541
			yyerror("%s: invalid function name\n", sname);
542
543
84270
	t = newtp(TFUNCT);
544
84270
	t->str = sname;
545
84270
	t->u.ksh_func = ksh_func;
546
84270
	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
84270
	if (ksh_func) {
554
158
		musthave('{', CONTIN|KEYWORD|ALIAS); /* } */
555
158
		reject = true;
556
158
	}
557
558
84270
	old_func_parse = genv->flags & EF_FUNC_PARSE;
559
84270
	genv->flags |= EF_FUNC_PARSE;
560
84270
	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
84270
	if (!old_func_parse)
579
83792
		genv->flags &= ~EF_FUNC_PARSE;
580
581
84270
	return t;
582
}
583
584
static char **
585
wordlist(void)
586
{
587
	int c;
588
	XPtrV args;
589
590
323422
	XPinit(args, 16);
591
	/* Posix does not do alias expansion here... */
592

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

2616044
	while ((c = token(0)) == LWORD)
598
1083026
		XPput(args, yylval.cp);
599
155732
	if (c != '\n' && c != ';')
600
		syntaxerr(NULL);
601
311484
	XPput(args, NULL);
602
155732
	return (char **) XPclose(args);
603
161711
}
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
20994102
	t = newtp(type);
615
10497051
	t->left = t1;
616
10497051
	t->right = t2;
617
10497051
	t->vars = wp;
618
10497051
	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
435540
	ktinit(&keywords, APERM, 32); /* must be 2^n (currently 20 keywords) */
665
11759580
	for (tt = tokentab; tt->name; tt++) {
666
5662020
		if (tt->reserved) {
667
4355400
			p = ktenter(&keywords, tt->name, hash(tt->name));
668
4355400
			p->flag |= DEFINED|ISSET;
669
4355400
			p->type = CKEYWD;
670
4355400
			p->val.i = tt->val;
671
4355400
		}
672
	}
673
217770
}
674
675
static void
676
syntaxerr(const char *what)
677
{
678
52
	char redir[6];	/* 2<<- is the longest redirection, I think */
679
	const char *s;
680
	struct tokeninfo const *tt;
681
	int c;
682
683
26
	if (!what)
684
26
		what = "unexpected";
685
26
	reject = true;
686
78
	c = token(0);
687
    Again:
688

26
	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
1404
		for (tt = tokentab; tt->name; tt++)
710
676
			if (tt->val == c)
711
			    break;
712
26
		if (tt->name)
713
			s = tt->name;
714
		else {
715
26
			if (c > 0 && c < 256) {
716
26
				redir[0] = c;
717
26
				redir[1] = '\0';
718
26
			} else
719
				shf_snprintf(redir, sizeof(redir),
720
					"?%d", c);
721
26
			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
4898474
	*save = nesting;
731
2449237
	nesting.start_token = tok;
732
2449237
	nesting.start_line = source->line;
733
2449237
}
734
735
static void
736
nesting_pop(struct nesting_state *saved)
737
{
738
4898474
	nesting = *saved;
739
2449237
}
740
741
static struct op *
742
newtp(int type)
743
{
744
	struct op *t;
745
746
63340436
	t = alloc(sizeof(*t), ATEMP);
747
31670218
	t->type = type;
748
31670218
	t->u.evalflags = 0;
749
31670218
	t->args = t->vars = NULL;
750
31670218
	t->ioact = NULL;
751
31670218
	t->left = t->right = NULL;
752
31670218
	t->str = NULL;
753
31670218
	return (t);
754
}
755
756
struct op *
757
compile(Source *s)
758
{
759
17528038
	nesting.start_token = 0;
760
8764019
	nesting.start_line = 0;
761
8764019
	herep = heres;
762
8764019
	source = s;
763
8764019
	yyparse();
764
8764019
	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

43123797
	if (Flag(FPOSIX) || !*s)
781
8507071
		return 0;
782
16970306
	return (strcmp(s, "alias") == 0) ||
783
8481159
	    (strcmp(s, "export") == 0) ||
784
25401425
	    (strcmp(s, "readonly") == 0) ||
785
8457565
	    (strcmp(s, "typeset") == 0);
786
16992224
}
787
788
/* Check if we are in the middle of reading an alias */
789
static int
790
inalias(struct source *s)
791
{
792

18281703
	for (; s && s->type == SALIAS; s = s->next)
793
625
		if (!(s->flags & SF_ALIASEND))
794
300
			return 1;
795
4569882
	return 0;
796
4570182
}
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
336132
	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
248014
	uqword = c == LWORD && *ident;
831
832
84033
	if (meta == TM_OR)
833
12215
		ret = c == LOGOR;
834
71818
	else if (meta == TM_AND)
835
12672
		ret = c == LOGAND;
836
59146
	else if (meta == TM_NOT)
837
27305
		ret = uqword && strcmp(yylval.cp, dbtest_tokens[(int) TM_NOT]) == 0;
838
46470
	else if (meta == TM_OPAREN)
839
12672
		ret = c == '(' /*)*/;
840
33798
	else if (meta == TM_CPAREN)
841
		ret = c == /*(*/ ')';
842
33798
	else if (meta == TM_UNOP || meta == TM_BINOP) {
843

23397
		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

36071
		} else if (uqword && (ret = (int) test_isop(te, meta, ident)))
849
12672
			save = yylval.cp;
850
	} else /* meta == TM_END */
851
31203
		ret = uqword && strcmp(yylval.cp, db_close) == 0;
852
84033
	if (ret) {
853
25348
		reject = false;
854
25348
		if (meta != TM_END) {
855
14947
			if (!save)
856
2275
				save = wdcopy(dbtest_tokens[(int) meta], ATEMP);
857
29894
			XPput(*te->pos.av, save);
858
14947
		}
859
	}
860
84033
	return ret;
861
}
862
863
static const char *
864
dbtestp_getopnd(Test_env *te, Test_op op, int do_eval)
865
{
866
93588
	int c = tpeek(ARRAYVAR);
867
868
23397
	if (c != LWORD)
869
		return NULL;
870
871
23397
	reject = false;
872
46794
	XPput(*te->pos.av, yylval.cp);
873
874
23397
	return null;
875
23397
}
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
25344
	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
}