GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: bin/ksh/syn.c Lines: 372 425 87.5 %
Date: 2016-12-06 Branches: 237 318 74.5 %

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
34985
{
60
	int c;
61
62
34985
	reject = false;
63
64
34985
	outtree = c_list(source->type == SSTRING);
65
34983
	c = tpeek(0);
66

46704
	if (c == 0 && !outtree)
67
11721
		outtree = newtp(TEOF);
68
23262
	else if (c != '\n' && c != 0)
69
2
		syntaxerr(NULL);
70
34981
}
71
72
static struct op *
73
pipeline(int cf)
74
96198
{
75
96198
	struct op *t, *p, *tl = NULL;
76
77
96198
	t = get_command(cf);
78
96196
	if (t != NULL) {
79

57202
		while (token(0) == '|') {
80
3006
			if ((p = get_command(CONTIN)) == NULL)
81
				syntaxerr(NULL);
82
3006
			if (tl == NULL)
83
2942
				t = tl = block(TPIPE, t, p, NULL);
84
			else
85
64
				tl = tl->right = block(TPIPE, tl->right, p, NULL);
86
		}
87
54196
		reject = true;
88
	}
89
96196
	return (t);
90
}
91
92
static struct op *
93
andor(void)
94
93504
{
95
	struct op *t, *p;
96
	int c;
97
98
93504
	t = pipeline(0);
99
93502
	if (t != NULL) {
100

54189
		while ((c = token(0)) == LOGAND || c == LOGOR) {
101
2687
			if ((p = pipeline(CONTIN)) == NULL)
102
				syntaxerr(NULL);
103
2687
			t = block(c == LOGAND? TAND: TOR, t, p, NULL);
104
		}
105
51502
		reject = true;
106
	}
107
93502
	return (t);
108
}
109
110
static struct op *
111
c_list(int multi)
112
51900
{
113
51900
	struct op *t = NULL, *p, *tl = NULL;
114
	int c;
115
	int have_sep;
116
117
	while (1) {
118
93504
		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
93502
		c = token(0);
123
93502
		have_sep = 1;
124

93502
		if (c == '\n' && (multi || inalias(source))) {
125
32503
			if (!p) /* ignore blank lines */
126
11485
				continue;
127
60999
		} else if (!p)
128
30515
			break;
129
30484
		else if (c == '&' || c == COPROC)
130
38
			p = block(c == '&' ? TASYNC : TCOPROC,
131
				  p, NULL, NULL);
132
30446
		else if (c != ';')
133
21383
			have_sep = 0;
134
51502
		if (!t)
135
35205
			t = p;
136
16297
		else if (!tl)
137
6916
			t = tl = block(TLIST, t, p, NULL);
138
		else
139
9381
			tl = tl->right = block(TLIST, tl->right, p, NULL);
140
51502
		if (!have_sep)
141
21383
			break;
142
	}
143
51898
	reject = true;
144
51898
	return t;
145
}
146
147
static struct ioword *
148
synio(int cf)
149
67727
{
150
	struct ioword *iop;
151
	int ishere;
152
153

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

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



99558
	switch (c = token(cf|KEYWORD|ALIAS|VARASN)) {
207
	default:
208
42000
		reject = true;
209
42000
		afree(iops, ATEMP);
210
42000
		XPfree(args);
211
42000
		XPfree(vars);
212
42000
		return NULL; /* empty line */
213
214
	case LWORD:
215
	case REDIR:
216
48629
		reject = true;
217
48629
		syniocf &= ~(KEYWORD|ALIAS);
218
48629
		t = newtp(TCOM);
219
48629
		t->lineno = source->line;
220
		while (1) {
221

182387
			cf = (t->u.evalflags ? ARRAYVAR : 0) |
222
			    (XPsize(args) == 0 ? ALIAS|VARASN : CMDWORD);
223

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


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

138524
				if ((XPsize(args) == 0 || Flag(FKEYWORD)) &&
240
				    is_wdvarassign(yylval.cp))
241
14049
					XPput(vars, yylval.cp);
242
				else
243
110426
					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
352
				afree(t, ATEMP);
251

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

350
				if (iopn != 0 || XPsize(args) != 1 ||
257
				    XPsize(vars) != 0)
258
					syntaxerr(NULL);
259
350
				reject = false;
260
				/*(*/
261
350
				musthave(')', 0);
262
350
				t = function_body(XPptrv(args)[0], false);
263
350
				goto Leave;
264
265
			default:
266
				goto Leave;
267
			}
268
		}
269
	  Leave:
270
		break;
271
272
1596
	  Subshell:
273
	case '(':
274
1596
		t = nested(TPAREN, '(', ')');
275
1596
		break;
276
277
	case '{': /*}*/
278
2201
		t = nested(TBRACE, '{', '}');
279
2201
		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
4
		t = newtp(TCOM);
289
4
		t->lineno = source->line;
290
4
		reject = false;
291
4
		XPput(args, wdcopy(let_cmd, ATEMP));
292
4
		musthave(LWORD,LETEXPR);
293
4
		XPput(args, yylval.cp);
294
4
		break;
295
	  }
296
297
	case DBRACKET: /* [[ .. ]] */
298
		/* Leave KEYWORD in syniocf (allow if [[ -n 1 ]] then ...) */
299
2
		t = newtp(TDBRACKET);
300
2
		reject = false;
301
		{
302
			Test_env te;
303
304
2
			te.flags = TEF_DBRACKET;
305
2
			te.pos.av = &args;
306
2
			te.isa = dbtestp_isa;
307
2
			te.getopnd = dbtestp_getopnd;
308
2
			te.eval = dbtestp_eval;
309
2
			te.error = dbtestp_error;
310
311
2
			test_parse(&te);
312
		}
313
2
		break;
314
315
	case FOR:
316
	case SELECT:
317
1006
		t = newtp((c == FOR) ? TFOR : TSELECT);
318
1006
		musthave(LWORD, ARRAYVAR);
319
1006
		if (!is_wdvarname(yylval.cp, true))
320
			yyerror("%s: bad identifier\n",
321
			    c == FOR ? "for" : "select");
322
1006
		t->str = str_save(ident, ATEMP);
323
1006
		nesting_push(&old_nesting, c);
324
1006
		t->vars = wordlist();
325
1006
		t->left = dogroup();
326
1006
		nesting_pop(&old_nesting);
327
1006
		break;
328
329
	case WHILE:
330
	case UNTIL:
331
68
		nesting_push(&old_nesting, c);
332
68
		t = newtp((c == WHILE) ? TWHILE : TUNTIL);
333
68
		t->left = c_list(true);
334
68
		t->right = dogroup();
335
68
		nesting_pop(&old_nesting);
336
68
		break;
337
338
	case CASE:
339
863
		t = newtp(TCASE);
340
863
		musthave(LWORD, 0);
341
863
		t->str = yylval.cp;
342
863
		nesting_push(&old_nesting, c);
343
863
		t->left = caselist();
344
863
		nesting_pop(&old_nesting);
345
863
		break;
346
347
	case IF:
348
3180
		nesting_push(&old_nesting, c);
349
3180
		t = newtp(TIF);
350
3180
		t->left = c_list(true);
351
3180
		t->right = thenpart();
352
3180
		musthave(FI, KEYWORD|ALIAS);
353
3180
		nesting_pop(&old_nesting);
354
3180
		break;
355
356
	case BANG:
357
5
		syniocf &= ~(KEYWORD|ALIAS);
358
5
		t = pipeline(0);
359
5
		if (t == NULL)
360
			syntaxerr(NULL);
361
5
		t = block(TBANG, NULL, t, NULL);
362
5
		break;
363
364
	case TIME:
365
2
		syniocf &= ~(KEYWORD|ALIAS);
366
2
		t = pipeline(0);
367
2
		if (t) {
368
2
			t->str = alloc(2, ATEMP);
369
2
			t->str[0] = '\0'; /* TF_* flags */
370
2
			t->str[1] = '\0';
371
		}
372
2
		t = block(TTIME, t, NULL, NULL);
373
2
		break;
374
375
	case FUNCTION:
376
4
		musthave(LWORD, 0);
377
4
		t = function_body(yylval.cp, true);
378
		break;
379
	}
380
381
58444
	while ((iop = synio(syniocf)) != NULL) {
382
888
		if (iopn >= NUFILE)
383
			yyerror("too many redirections\n");
384
888
		iops[iopn++] = iop;
385
	}
386
387
57556
	if (iopn == 0) {
388
49410
		afree(iops, ATEMP);
389
49410
		t->ioact = NULL;
390
	} else {
391
8146
		iops[iopn++] = NULL;
392
8146
		iops = areallocarray(iops, iopn,
393
		    sizeof(struct ioword *), ATEMP);
394
8146
		t->ioact = iops;
395
	}
396
397
57556
	if (t->type == TCOM || t->type == TDBRACKET) {
398
48281
		XPput(args, NULL);
399
48281
		t->args = (char **) XPclose(args);
400
48281
		XPput(vars, NULL);
401
48281
		t->vars = (char **) XPclose(vars);
402
	} else {
403
9275
		XPfree(args);
404
9275
		XPfree(vars);
405
	}
406
407
57556
	return t;
408
}
409
410
static struct op *
411
dogroup(void)
412
1074
{
413
	int c;
414
	struct op *list;
415
416
1074
	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
1074
	if (c == DO)
423
1074
		c = DONE;
424
	else if (c == '{')
425
		c = '}';
426
	else
427
		syntaxerr(NULL);
428
1074
	list = c_list(true);
429
1074
	musthave(c, KEYWORD|ALIAS);
430
1074
	return list;
431
}
432
433
static struct op *
434
thenpart(void)
435
3248
{
436
	struct op *t;
437
438
3248
	musthave(THEN, KEYWORD|ALIAS);
439
3248
	t = newtp(0);
440
3248
	t->left = c_list(true);
441
3248
	if (t->left == NULL)
442
		syntaxerr(NULL);
443
3248
	t->right = elsepart();
444
3248
	return (t);
445
}
446
447
static struct op *
448
elsepart(void)
449
3248
{
450
	struct op *t;
451
452

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

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

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

3375
	if ((tpeek(CONTIN|KEYWORD|ALIAS)) != endtok)
520
3342
		musthave(BREAK, CONTIN|KEYWORD|ALIAS);
521
3375
	return (t);
522
}
523
524
static struct op *
525
function_body(char *name,
526
    int ksh_func)		/* function foo { ... } vs foo() { .. } */
527
354
{
528
	char *sname, *p;
529
	struct op *t;
530
	int old_func_parse;
531
532
354
	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
2901
	for (p = sname; *p; p++)
540

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

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

5734
	while ((c = token(0)) == LWORD)
598
4755
		XPput(args, yylval.cp);
599
979
	if (c != '\n' && c != ';')
600
		syntaxerr(NULL);
601
979
	XPput(args, NULL);
602
979
	return (char **) XPclose(args);
603
}
604
605
/*
606
 * supporting functions
607
 */
608
609
static struct op *
610
block(int type, struct op *t1, struct op *t2, char **wp)
611
25832
{
612
	struct op *t;
613
614
25832
	t = newtp(type);
615
25832
	t->left = t1;
616
25832
	t->right = t2;
617
25832
	t->vars = wp;
618
25832
	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
3525
{
661
	struct tokeninfo const *tt;
662
	struct tbl *p;
663
664
3525
	ktinit(&keywords, APERM, 32); /* must be 2^n (currently 20 keywords) */
665
95175
	for (tt = tokentab; tt->name; tt++) {
666
91650
		if (tt->reserved) {
667
70500
			p = ktenter(&keywords, tt->name, hash(tt->name));
668
70500
			p->flag |= DEFINED|ISSET;
669
70500
			p->type = CKEYWD;
670
70500
			p->val.i = tt->val;
671
		}
672
	}
673
3525
}
674
675
static void
676
syntaxerr(const char *what)
677
2
{
678
	char redir[6];	/* 2<<- is the longest redirection, I think */
679
	const char *s;
680
	struct tokeninfo const *tt;
681
	int c;
682
683
2
	if (!what)
684
2
		what = "unexpected";
685
2
	reject = true;
686
2
	c = token(0);
687
2
    Again:
688

2
	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
54
		for (tt = tokentab; tt->name; tt++)
710
52
			if (tt->val == c)
711
			    break;
712
2
		if (tt->name)
713
			s = tt->name;
714
		else {
715
2
			if (c > 0 && c < 256) {
716
2
				redir[0] = c;
717
2
				redir[1] = '\0';
718
			} else
719
				shf_snprintf(redir, sizeof(redir),
720
					"?%d", c);
721
2
			s = redir;
722
		}
723
	}
724
2
	yyerror("syntax error: `%s' %s\n", s, what);
725
}
726
727
static void
728
nesting_push(struct nesting_state *save, int tok)
729
8914
{
730
8914
	*save = nesting;
731
8914
	nesting.start_token = tok;
732
8914
	nesting.start_line = source->line;
733
8914
}
734
735
static void
736
nesting_pop(struct nesting_state *saved)
737
8914
{
738
8914
	nesting = *saved;
739
8914
}
740
741
static struct op *
742
newtp(int type)
743
98350
{
744
	struct op *t;
745
746
98350
	t = alloc(sizeof(*t), ATEMP);
747
98350
	t->type = type;
748
98350
	t->u.evalflags = 0;
749
98350
	t->args = t->vars = NULL;
750
98350
	t->ioact = NULL;
751
98350
	t->left = t->right = NULL;
752
98350
	t->str = NULL;
753
98350
	return (t);
754
}
755
756
struct op *
757
compile(Source *s)
758
34985
{
759
34985
	nesting.start_token = 0;
760
34985
	nesting.start_line = 0;
761
34985
	herep = heres;
762
34985
	source = s;
763
34985
	yyparse();
764
34981
	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
48621
{
780

48621
	if (Flag(FPOSIX) || !*s)
781
26062
		return 0;
782


22559
	return (strcmp(s, "alias") == 0) ||
783
	    (strcmp(s, "export") == 0) ||
784
	    (strcmp(s, "readonly") == 0) ||
785
	    (strcmp(s, "typeset") == 0);
786
}
787
788
/* Check if we are in the middle of reading an alias */
789
static int
790
inalias(struct source *s)
791
17816
{
792

17842
	for (; s && s->type == SALIAS; s = s->next)
793
50
		if (!(s->flags & SF_ALIASEND))
794
24
			return 1;
795
17792
	return 0;
796
}
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
12
{
824

12
	int c = tpeek(ARRAYVAR | (meta == TM_BINOP ? 0 : CONTIN));
825
12
	int uqword = 0;
826
12
	char *save = NULL;
827
12
	int ret = 0;
828
829
	/* unquoted word? */
830

12
	uqword = c == LWORD && *ident;
831
832
12
	if (meta == TM_OR)
833
2
		ret = c == LOGOR;
834
10
	else if (meta == TM_AND)
835
2
		ret = c == LOGAND;
836
8
	else if (meta == TM_NOT)
837

2
		ret = uqword && strcmp(yylval.cp, dbtest_tokens[(int) TM_NOT]) == 0;
838
6
	else if (meta == TM_OPAREN)
839
2
		ret = c == '(' /*)*/;
840
4
	else if (meta == TM_CPAREN)
841
		ret = c == /*(*/ ')';
842
4
	else if (meta == TM_UNOP || meta == TM_BINOP) {
843

2
		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

2
		} else if (uqword && (ret = (int) test_isop(te, meta, ident)))
849
2
			save = yylval.cp;
850
	} else /* meta == TM_END */
851

2
		ret = uqword && strcmp(yylval.cp, db_close) == 0;
852
12
	if (ret) {
853
4
		reject = false;
854
4
		if (meta != TM_END) {
855
2
			if (!save)
856
				save = wdcopy(dbtest_tokens[(int) meta], ATEMP);
857
2
			XPput(*te->pos.av, save);
858
		}
859
	}
860
12
	return ret;
861
}
862
863
static const char *
864
dbtestp_getopnd(Test_env *te, Test_op op, int do_eval)
865
2
{
866
2
	int c = tpeek(ARRAYVAR);
867
868
2
	if (c != LWORD)
869
		return NULL;
870
871
2
	reject = false;
872
2
	XPput(*te->pos.av, yylval.cp);
873
874
2
	return null;
875
}
876
877
static int
878
dbtestp_eval(Test_env *te, Test_op op, const char *opnd1, const char *opnd2,
879
    int do_eval)
880
2
{
881
2
	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
}