xref: /original-bsd/bin/sh/parser.c (revision d272e02a)
1 /*-
2  * Copyright (c) 1991 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kenneth Almquist.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char sccsid[] = "@(#)parser.c	5.2 (Berkeley) 03/13/91";
13 #endif /* not lint */
14 
15 #include "shell.h"
16 #include "parser.h"
17 #include "nodes.h"
18 #include "expand.h"	/* defines rmescapes() */
19 #include "redir.h"	/* defines copyfd() */
20 #include "syntax.h"
21 #include "options.h"
22 #include "input.h"
23 #include "output.h"
24 #include "var.h"
25 #include "error.h"
26 #include "memalloc.h"
27 #include "mystring.h"
28 
29 
30 /*
31  * Shell command parser.
32  */
33 
34 #define EOFMARKLEN 79
35 
36 /* values returned by readtoken */
37 #include "token.def"
38 
39 
40 
41 struct heredoc {
42 	struct heredoc *next;	/* next here document in list */
43 	union node *here;		/* redirection node */
44 	char *eofmark;		/* string indicating end of input */
45 	int striptabs;		/* if set, strip leading tabs */
46 };
47 
48 
49 
50 struct heredoc *heredoclist;	/* list of here documents to read */
51 int parsebackquote;		/* nonzero if we are inside backquotes */
52 int doprompt;			/* if set, prompt the user */
53 int needprompt;			/* true if interactive and at start of line */
54 int lasttoken;			/* last token read */
55 MKINIT int tokpushback;		/* last token pushed back */
56 char *wordtext;			/* text of last word returned by readtoken */
57 struct nodelist *backquotelist;
58 union node *redirnode;
59 struct heredoc *heredoc;
60 int quoteflag;			/* set if (part of) last token was quoted */
61 int startlinno;			/* line # where last token started */
62 
63 
64 #define GDB_HACK 1 /* avoid local declarations which gdb can't handle */
65 #ifdef GDB_HACK
66 static const char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'};
67 static const char types[] = "}-+?=";
68 #endif
69 
70 
71 #ifdef __STDC__
72 STATIC union node *list(int);
73 STATIC union node *andor(void);
74 STATIC union node *pipeline(void);
75 STATIC union node *command(void);
76 STATIC union node *simplecmd(void);
77 STATIC void parsefname(void);
78 STATIC void parseheredoc(void);
79 STATIC void checkkwd(void);
80 STATIC int readtoken(void);
81 STATIC int readtoken1(int, char const *, char *, int);
82 STATIC void attyline(void);
83 STATIC int noexpand(char *);
84 STATIC void synexpect(int);
85 STATIC void synerror(char *);
86 #else
87 STATIC union node *list();
88 STATIC union node *andor();
89 STATIC union node *pipeline();
90 STATIC union node *command();
91 STATIC union node *simplecmd();
92 STATIC void parsefname();
93 STATIC void parseheredoc();
94 STATIC void checkkwd();
95 STATIC int readtoken();
96 STATIC int readtoken1();
97 STATIC void attyline();
98 STATIC int noexpand();
99 STATIC void synexpect();
100 STATIC void synerror();
101 #endif
102 
103 #if ATTY
104 #ifdef __STDC__
105 STATIC void putprompt(char *);
106 #else
107 STATIC void putprompt();
108 #endif
109 #else /* not ATTY */
110 #define putprompt(s)	out2str(s)
111 #endif
112 
113 
114 
115 
116 /*
117  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
118  * valid parse tree indicating a blank line.)
119  */
120 
121 union node *
122 parsecmd(interact) {
123 	int t;
124 
125 	doprompt = interact;
126 	if (doprompt)
127 		putprompt(ps1val());
128 	needprompt = 0;
129 	if ((t = readtoken()) == TEOF)
130 		return NEOF;
131 	if (t == TNL)
132 		return NULL;
133 	tokpushback++;
134 	return list(1);
135 }
136 
137 
138 STATIC union node *
139 list(nlflag) {
140 	union node *n1, *n2, *n3;
141 
142 	checkkwd();
143 	if (nlflag == 0 && tokendlist[lasttoken])
144 		return NULL;
145 	n1 = andor();
146 	for (;;) {
147 		switch (readtoken()) {
148 		case TBACKGND:
149 			if (n1->type == NCMD || n1->type == NPIPE) {
150 				n1->ncmd.backgnd = 1;
151 			} else if (n1->type == NREDIR) {
152 				n1->type = NBACKGND;
153 			} else {
154 				n3 = (union node *)stalloc(sizeof (struct nredir));
155 				n3->type = NBACKGND;
156 				n3->nredir.n = n1;
157 				n3->nredir.redirect = NULL;
158 				n1 = n3;
159 			}
160 			goto tsemi;
161 		case TNL:
162 			tokpushback++;
163 			/* fall through */
164 tsemi:	    case TSEMI:
165 			if (readtoken() == TNL) {
166 				parseheredoc();
167 				if (nlflag)
168 					return n1;
169 			} else {
170 				tokpushback++;
171 			}
172 			checkkwd();
173 			if (tokendlist[lasttoken])
174 				return n1;
175 			n2 = andor();
176 			n3 = (union node *)stalloc(sizeof (struct nbinary));
177 			n3->type = NSEMI;
178 			n3->nbinary.ch1 = n1;
179 			n3->nbinary.ch2 = n2;
180 			n1 = n3;
181 			break;
182 		case TEOF:
183 			if (heredoclist)
184 				parseheredoc();
185 			else
186 				pungetc();		/* push back EOF on input */
187 			return n1;
188 		default:
189 			if (nlflag)
190 				synexpect(-1);
191 			tokpushback++;
192 			return n1;
193 		}
194 	}
195 }
196 
197 
198 
199 STATIC union node *
200 andor() {
201 	union node *n1, *n2, *n3;
202 	int t;
203 
204 	n1 = pipeline();
205 	for (;;) {
206 		if ((t = readtoken()) == TAND) {
207 			t = NAND;
208 		} else if (t == TOR) {
209 			t = NOR;
210 		} else {
211 			tokpushback++;
212 			return n1;
213 		}
214 		n2 = pipeline();
215 		n3 = (union node *)stalloc(sizeof (struct nbinary));
216 		n3->type = t;
217 		n3->nbinary.ch1 = n1;
218 		n3->nbinary.ch2 = n2;
219 		n1 = n3;
220 	}
221 }
222 
223 
224 
225 STATIC union node *
226 pipeline() {
227 	union node *n1, *pipenode;
228 	struct nodelist *lp, *prev;
229 
230 	n1 = command();
231 	if (readtoken() == TPIPE) {
232 		pipenode = (union node *)stalloc(sizeof (struct npipe));
233 		pipenode->type = NPIPE;
234 		pipenode->npipe.backgnd = 0;
235 		lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
236 		pipenode->npipe.cmdlist = lp;
237 		lp->n = n1;
238 		do {
239 			prev = lp;
240 			lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
241 			lp->n = command();
242 			prev->next = lp;
243 		} while (readtoken() == TPIPE);
244 		lp->next = NULL;
245 		n1 = pipenode;
246 	}
247 	tokpushback++;
248 	return n1;
249 }
250 
251 
252 
253 STATIC union node *
254 command() {
255 	union node *n1, *n2;
256 	union node *ap, **app;
257 	union node *cp, **cpp;
258 	union node *redir, **rpp;
259 	int t;
260 
261 	checkkwd();
262 	switch (readtoken()) {
263 	case TIF:
264 		n1 = (union node *)stalloc(sizeof (struct nif));
265 		n1->type = NIF;
266 		n1->nif.test = list(0);
267 		if (readtoken() != TTHEN)
268 			synexpect(TTHEN);
269 		n1->nif.ifpart = list(0);
270 		n2 = n1;
271 		while (readtoken() == TELIF) {
272 			n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
273 			n2 = n2->nif.elsepart;
274 			n2->type = NIF;
275 			n2->nif.test = list(0);
276 			if (readtoken() != TTHEN)
277 				synexpect(TTHEN);
278 			n2->nif.ifpart = list(0);
279 		}
280 		if (lasttoken == TELSE)
281 			n2->nif.elsepart = list(0);
282 		else {
283 			n2->nif.elsepart = NULL;
284 			tokpushback++;
285 		}
286 		if (readtoken() != TFI)
287 			synexpect(TFI);
288 		checkkwd();
289 		break;
290 	case TWHILE:
291 	case TUNTIL:
292 		n1 = (union node *)stalloc(sizeof (struct nbinary));
293 		n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
294 		n1->nbinary.ch1 = list(0);
295 		if (readtoken() != TDO)
296 			synexpect(TDO);
297 		n1->nbinary.ch2 = list(0);
298 		if (readtoken() != TDONE)
299 			synexpect(TDONE);
300 		checkkwd();
301 		break;
302 	case TFOR:
303 		if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
304 			synerror("Bad for loop variable");
305 		n1 = (union node *)stalloc(sizeof (struct nfor));
306 		n1->type = NFOR;
307 		n1->nfor.var = wordtext;
308 		if (readtoken() == TWORD && ! quoteflag && equal(wordtext, "in")) {
309 			app = ≈
310 			while (readtoken() == TWORD) {
311 				n2 = (union node *)stalloc(sizeof (struct narg));
312 				n2->type = NARG;
313 				n2->narg.text = wordtext;
314 				n2->narg.backquote = backquotelist;
315 				*app = n2;
316 				app = &n2->narg.next;
317 			}
318 			*app = NULL;
319 			n1->nfor.args = ap;
320 		} else {
321 #ifndef GDB_HACK
322 			static const char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
323 								   '@', '=', '\0'};
324 #endif
325 			n2 = (union node *)stalloc(sizeof (struct narg));
326 			n2->type = NARG;
327 			n2->narg.text = (char *)argvars;
328 			n2->narg.backquote = NULL;
329 			n2->narg.next = NULL;
330 			n1->nfor.args = n2;
331 		}
332 		if (lasttoken != TNL && lasttoken != TSEMI)
333 			synexpect(-1);
334 		checkkwd();
335 		if ((t = readtoken()) == TDO)
336 			t = TDONE;
337 		else if (t == TBEGIN)
338 			t = TEND;
339 		else
340 			synexpect(-1);
341 		n1->nfor.body = list(0);
342 		if (readtoken() != t)
343 			synexpect(t);
344 		checkkwd();
345 		break;
346 	case TCASE:
347 		n1 = (union node *)stalloc(sizeof (struct ncase));
348 		n1->type = NCASE;
349 		if (readtoken() != TWORD)
350 			synexpect(TWORD);
351 		n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
352 		n2->type = NARG;
353 		n2->narg.text = wordtext;
354 		n2->narg.backquote = backquotelist;
355 		n2->narg.next = NULL;
356 		while (readtoken() == TNL);
357 		if (lasttoken != TWORD || ! equal(wordtext, "in"))
358 			synerror("expecting \"in\"");
359 		cpp = &n1->ncase.cases;
360 		while (checkkwd(), readtoken() == TWORD) {
361 			*cpp = cp = (union node *)stalloc(sizeof (struct nclist));
362 			cp->type = NCLIST;
363 			app = &cp->nclist.pattern;
364 			for (;;) {
365 				*app = ap = (union node *)stalloc(sizeof (struct narg));
366 				ap->type = NARG;
367 				ap->narg.text = wordtext;
368 				ap->narg.backquote = backquotelist;
369 				if (readtoken() != TPIPE)
370 					break;
371 				app = &ap->narg.next;
372 				if (readtoken() != TWORD)
373 					synexpect(TWORD);
374 			}
375 			ap->narg.next = NULL;
376 			if (lasttoken != TRP)
377 				synexpect(TRP);
378 			cp->nclist.body = list(0);
379 			if ((t = readtoken()) == TESAC)
380 				tokpushback++;
381 			else if (t != TENDCASE)
382 				synexpect(TENDCASE);
383 			cpp = &cp->nclist.next;
384 		}
385 		*cpp = NULL;
386 		if (lasttoken != TESAC)
387 			synexpect(TESAC);
388 		checkkwd();
389 		break;
390 	case TLP:
391 		n1 = (union node *)stalloc(sizeof (struct nredir));
392 		n1->type = NSUBSHELL;
393 		n1->nredir.n = list(0);
394 		n1->nredir.redirect = NULL;
395 		if (readtoken() != TRP)
396 			synexpect(TRP);
397 		checkkwd();
398 		break;
399 	case TBEGIN:
400 		n1 = list(0);
401 		if (readtoken() != TEND)
402 			synexpect(TEND);
403 		checkkwd();
404 		break;
405 	case TWORD:
406 	case TREDIR:
407 		tokpushback++;
408 		return simplecmd();
409 	default:
410 		synexpect(-1);
411 	}
412 
413 	/* Now check for redirection which may follow command */
414 	rpp = &redir;
415 	while (readtoken() == TREDIR) {
416 		*rpp = n2 = redirnode;
417 		rpp = &n2->nfile.next;
418 		parsefname();
419 	}
420 	tokpushback++;
421 	*rpp = NULL;
422 	if (redir) {
423 		if (n1->type != NSUBSHELL) {
424 			n2 = (union node *)stalloc(sizeof (struct nredir));
425 			n2->type = NREDIR;
426 			n2->nredir.n = n1;
427 			n1 = n2;
428 		}
429 		n1->nredir.redirect = redir;
430 	}
431 	return n1;
432 }
433 
434 
435 STATIC union node *
436 simplecmd() {
437 	union node *args, **app;
438 	union node *redir, **rpp;
439 	union node *n;
440 
441 	args = NULL;
442 	app = &args;
443 	rpp = &redir;
444 	for (;;) {
445 		if (readtoken() == TWORD) {
446 			n = (union node *)stalloc(sizeof (struct narg));
447 			n->type = NARG;
448 			n->narg.text = wordtext;
449 			n->narg.backquote = backquotelist;
450 			*app = n;
451 			app = &n->narg.next;
452 		} else if (lasttoken == TREDIR) {
453 			*rpp = n = redirnode;
454 			rpp = &n->nfile.next;
455 			parsefname();	/* read name of redirection file */
456 		} else if (lasttoken == TLP && app == &args->narg.next
457 					    && rpp == &redir) {
458 			/* We have a function */
459 			if (readtoken() != TRP)
460 				synexpect(TRP);
461 #ifdef notdef
462 			if (! goodname(n->narg.text))
463 				synerror("Bad function name");
464 #endif
465 			n->type = NDEFUN;
466 			n->narg.next = command();
467 			return n;
468 		} else {
469 			tokpushback++;
470 			break;
471 		}
472 	}
473 	*app = NULL;
474 	*rpp = NULL;
475 	n = (union node *)stalloc(sizeof (struct ncmd));
476 	n->type = NCMD;
477 	n->ncmd.backgnd = 0;
478 	n->ncmd.args = args;
479 	n->ncmd.redirect = redir;
480 	return n;
481 }
482 
483 
484 STATIC void
485 parsefname() {
486 	union node *n = redirnode;
487 
488 	if (readtoken() != TWORD)
489 		synexpect(-1);
490 	if (n->type == NHERE) {
491 		struct heredoc *here = heredoc;
492 		struct heredoc *p;
493 		int i;
494 
495 		if (quoteflag == 0)
496 			n->type = NXHERE;
497 		TRACE(("Here document %d\n", n->type));
498 		if (here->striptabs) {
499 			while (*wordtext == '\t')
500 				wordtext++;
501 		}
502 		if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
503 			synerror("Illegal eof marker for << redirection");
504 		rmescapes(wordtext);
505 		here->eofmark = wordtext;
506 		here->next = NULL;
507 		if (heredoclist == NULL)
508 			heredoclist = here;
509 		else {
510 			for (p = heredoclist ; p->next ; p = p->next);
511 			p->next = here;
512 		}
513 	} else if (n->type == NTOFD || n->type == NFROMFD) {
514 		if (is_digit(wordtext[0]))
515 			n->ndup.dupfd = digit_val(wordtext[0]);
516 		else if (wordtext[0] == '-')
517 			n->ndup.dupfd = -1;
518 		else
519 			goto bad;
520 		if (wordtext[1] != '\0') {
521 bad:
522 			synerror("Bad fd number");
523 		}
524 	} else {
525 		n->nfile.fname = (union node *)stalloc(sizeof (struct narg));
526 		n = n->nfile.fname;
527 		n->type = NARG;
528 		n->narg.next = NULL;
529 		n->narg.text = wordtext;
530 		n->narg.backquote = backquotelist;
531 	}
532 }
533 
534 
535 /*
536  * Input any here documents.
537  */
538 
539 STATIC void
540 parseheredoc() {
541 	struct heredoc *here;
542 	union node *n;
543 
544 	while (heredoclist) {
545 		here = heredoclist;
546 		heredoclist = here->next;
547 		if (needprompt) {
548 			putprompt(ps2val());
549 			needprompt = 0;
550 		}
551 		readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
552 				here->eofmark, here->striptabs);
553 		n = (union node *)stalloc(sizeof (struct narg));
554 		n->narg.type = NARG;
555 		n->narg.next = NULL;
556 		n->narg.text = wordtext;
557 		n->narg.backquote = backquotelist;
558 		here->here->nhere.doc = n;
559 	}
560 }
561 
562 
563 
564 /*
565  * This routine is called to tell readtoken that we are at the beginning
566  * of a command, so newlines should be ignored and keywords should be
567  * checked for.  We munge things here rather than setting a flag for
568  * readtoken.
569  */
570 
571 STATIC void
572 checkkwd() {
573 	register char *const *pp;
574 	int t;
575 
576 	while ((t = readtoken()) == TNL)
577 		parseheredoc();
578 	if (t == TWORD && quoteflag == 0) {
579 		for (pp = parsekwd ; *pp ; pp++) {
580 			if (**pp == *wordtext && equal(*pp, wordtext)) {
581 				lasttoken = pp - parsekwd + KWDOFFSET;
582 				break;
583 			}
584 		}
585 	}
586 	tokpushback++;
587 }
588 
589 
590 
591 STATIC int xxreadtoken();
592 
593 STATIC int
594 readtoken() {
595 	int t;
596 
597 	if (tokpushback) {
598 		return xxreadtoken();
599 	} else {
600 		t = xxreadtoken();
601 		TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
602 		return t;
603 	}
604 }
605 
606 
607 /*
608  * Read the next input token.
609  * If the token is a word, we set backquotelist to the list of cmds in
610  *	backquotes.  We set quoteflag to true if any part of the word was
611  *	quoted.
612  * If the token is TREDIR, then we set redirnode to a structure containing
613  *	the redirection.
614  * In all cases, the variable startlinno is set to the number of the line
615  *	on which the token starts.
616  *
617  * [Change comment:  here documents and internal procedures]
618  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
619  *  word parsing code into a separate routine.  In this case, readtoken
620  *  doesn't need to have any internal procedures, but parseword does.
621  *  We could also make parseoperator in essence the main routine, and
622  *  have parseword (readtoken1?) handle both words and redirection.]
623  */
624 
625 #define RETURN(token)	return lasttoken = token
626 
627 STATIC int
628 xxreadtoken() {
629 	register c;
630 
631 	if (tokpushback) {
632 		tokpushback = 0;
633 		return lasttoken;
634 	}
635 	if (needprompt) {
636 		putprompt(ps2val());
637 		needprompt = 0;
638 	}
639 	startlinno = plinno;
640 	for (;;) {	/* until token or start of word found */
641 		c = pgetc_macro();
642 		if (c == ' ' || c == '\t')
643 			continue;		/* quick check for white space first */
644 		switch (c) {
645 		case ' ': case '\t':
646 			continue;
647 		case '#':
648 			while ((c = pgetc()) != '\n' && c != PEOF);
649 			pungetc();
650 			continue;
651 		case '\\':
652 			if (pgetc() == '\n') {
653 				startlinno = ++plinno;
654 				if (doprompt)
655 					putprompt(ps2val());
656 				continue;
657 			}
658 			pungetc();
659 			goto breakloop;
660 		case '\n':
661 			plinno++;
662 			needprompt = doprompt;
663 			RETURN(TNL);
664 		case PEOF:
665 			RETURN(TEOF);
666 		case '&':
667 			if (pgetc() == '&')
668 				RETURN(TAND);
669 			pungetc();
670 			RETURN(TBACKGND);
671 		case '|':
672 			if (pgetc() == '|')
673 				RETURN(TOR);
674 			pungetc();
675 			RETURN(TPIPE);
676 		case ';':
677 			if (pgetc() == ';')
678 				RETURN(TENDCASE);
679 			pungetc();
680 			RETURN(TSEMI);
681 		case '(':
682 			RETURN(TLP);
683 		case ')':
684 			RETURN(TRP);
685 		default:
686 			goto breakloop;
687 		}
688 	}
689 breakloop:
690 	return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
691 #undef RETURN
692 }
693 
694 
695 
696 /*
697  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
698  * is not NULL, read a here document.  In the latter case, eofmark is the
699  * word which marks the end of the document and striptabs is true if
700  * leading tabs should be stripped from the document.  The argument firstc
701  * is the first character of the input token or document.
702  *
703  * Because C does not have internal subroutines, I have simulated them
704  * using goto's to implement the subroutine linkage.  The following macros
705  * will run code that appears at the end of readtoken1.
706  */
707 
708 #define CHECKEND()	{goto checkend; checkend_return:;}
709 #define PARSEREDIR()	{goto parseredir; parseredir_return:;}
710 #define PARSESUB()	{goto parsesub; parsesub_return:;}
711 #define PARSEBACKQOLD()	{oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
712 #define PARSEBACKQNEW()	{oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
713 
714 STATIC int
715 readtoken1(firstc, syntax, eofmark, striptabs)
716 	int firstc;
717 	char const *syntax;
718 	char *eofmark;
719 	int striptabs;
720 	{
721 	register c = firstc;
722 	register char *out;
723 	int len;
724 	char line[EOFMARKLEN + 1];
725 	struct nodelist *bqlist;
726 	int quotef;
727 	int dblquote;
728 	int varnest;
729 	int oldstyle;
730 
731 	startlinno = plinno;
732 	dblquote = 0;
733 	if (syntax == DQSYNTAX)
734 		dblquote = 1;
735 	quotef = 0;
736 	bqlist = NULL;
737 	varnest = 0;
738 	STARTSTACKSTR(out);
739 	loop: {	/* for each line, until end of word */
740 #if ATTY
741 		if (c == '\034' && doprompt
742 		 && attyset() && ! equal(termval(), "emacs")) {
743 			attyline();
744 			if (syntax == BASESYNTAX)
745 				return readtoken();
746 			c = pgetc();
747 			goto loop;
748 		}
749 #endif
750 		CHECKEND();	/* set c to PEOF if at end of here document */
751 		for (;;) {	/* until end of line or end of word */
752 			CHECKSTRSPACE(3, out);	/* permit 3 calls to USTPUTC */
753 			switch(syntax[c]) {
754 			case CNL:	/* '\n' */
755 				if (syntax == BASESYNTAX)
756 					goto endword;	/* exit outer loop */
757 				USTPUTC(c, out);
758 				plinno++;
759 				if (doprompt) {
760 					putprompt(ps2val());
761 				}
762 				c = pgetc();
763 				goto loop;		/* continue outer loop */
764 			case CWORD:
765 				USTPUTC(c, out);
766 				break;
767 			case CCTL:
768 				if (eofmark == NULL || dblquote)
769 					USTPUTC(CTLESC, out);
770 				USTPUTC(c, out);
771 				break;
772 			case CBACK:	/* backslash */
773 				c = pgetc();
774 				if (c == PEOF) {
775 					USTPUTC('\\', out);
776 					pungetc();
777 				} else if (c == '\n') {
778 					if (doprompt)
779 						putprompt(ps2val());
780 				} else {
781 					if (dblquote && c != '\\' && c != '`' && c != '$'
782 							 && (c != '"' || eofmark != NULL))
783 						USTPUTC('\\', out);
784 					if (SQSYNTAX[c] == CCTL)
785 						USTPUTC(CTLESC, out);
786 					USTPUTC(c, out);
787 					quotef++;
788 				}
789 				break;
790 			case CSQUOTE:
791 				syntax = SQSYNTAX;
792 				break;
793 			case CDQUOTE:
794 				syntax = DQSYNTAX;
795 				dblquote = 1;
796 				break;
797 			case CENDQUOTE:
798 				if (eofmark) {
799 					USTPUTC(c, out);
800 				} else {
801 					syntax = BASESYNTAX;
802 					quotef++;
803 					dblquote = 0;
804 				}
805 				break;
806 			case CVAR:	/* '$' */
807 				PARSESUB();		/* parse substitution */
808 				break;
809 			case CENDVAR:	/* '}' */
810 				if (varnest > 0) {
811 					varnest--;
812 					USTPUTC(CTLENDVAR, out);
813 				} else {
814 					USTPUTC(c, out);
815 				}
816 				break;
817 			case CBQUOTE:	/* '`' */
818 				if (parsebackquote && syntax == BASESYNTAX) {
819 					if (out == stackblock())
820 						return lasttoken = TENDBQUOTE;
821 					else
822 						goto endword;	/* exit outer loop */
823 				}
824 				PARSEBACKQOLD();
825 				break;
826 			case CEOF:
827 				goto endword;		/* exit outer loop */
828 			default:
829 				if (varnest == 0)
830 					goto endword;	/* exit outer loop */
831 				USTPUTC(c, out);
832 			}
833 			c = pgetc_macro();
834 		}
835 	}
836 endword:
837 	if (syntax != BASESYNTAX && eofmark == NULL)
838 		synerror("Unterminated quoted string");
839 	if (varnest != 0) {
840 		startlinno = plinno;
841 		synerror("Missing '}'");
842 	}
843 	USTPUTC('\0', out);
844 	len = out - stackblock();
845 	out = stackblock();
846 	if (eofmark == NULL) {
847 		if ((c == '>' || c == '<')
848 		 && quotef == 0
849 		 && len <= 2
850 		 && (*out == '\0' || is_digit(*out))) {
851 			PARSEREDIR();
852 			return lasttoken = TREDIR;
853 		} else {
854 			pungetc();
855 		}
856 	}
857 	quoteflag = quotef;
858 	backquotelist = bqlist;
859 	grabstackblock(len);
860 	wordtext = out;
861 	return lasttoken = TWORD;
862 /* end of readtoken routine */
863 
864 
865 
866 /*
867  * Check to see whether we are at the end of the here document.  When this
868  * is called, c is set to the first character of the next input line.  If
869  * we are at the end of the here document, this routine sets the c to PEOF.
870  */
871 
872 checkend: {
873 	if (eofmark) {
874 		if (striptabs) {
875 			while (c == '\t')
876 				c = pgetc();
877 		}
878 		if (c == *eofmark) {
879 			if (pfgets(line, sizeof line) != NULL) {
880 				register char *p, *q;
881 
882 				p = line;
883 				for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
884 				if (*p == '\n' && *q == '\0') {
885 					c = PEOF;
886 					plinno++;
887 					needprompt = doprompt;
888 				} else {
889 					ppushback(line, strlen(line));
890 				}
891 			}
892 		}
893 	}
894 	goto checkend_return;
895 }
896 
897 
898 /*
899  * Parse a redirection operator.  The variable "out" points to a string
900  * specifying the fd to be redirected.  The variable "c" contains the
901  * first character of the redirection operator.
902  */
903 
904 parseredir: {
905 	char fd = *out;
906 	union node *np;
907 
908 	np = (union node *)stalloc(sizeof (struct nfile));
909 	if (c == '>') {
910 		np->nfile.fd = 1;
911 		c = pgetc();
912 		if (c == '>')
913 			np->type = NAPPEND;
914 		else if (c == '&')
915 			np->type = NTOFD;
916 		else {
917 			np->type = NTO;
918 			pungetc();
919 		}
920 	} else {	/* c == '<' */
921 		np->nfile.fd = 0;
922 		c = pgetc();
923 		if (c == '<') {
924 			if (sizeof (struct nfile) != sizeof (struct nhere)) {
925 				np = (union node *)stalloc(sizeof (struct nhere));
926 				np->nfile.fd = 0;
927 			}
928 			np->type = NHERE;
929 			heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
930 			heredoc->here = np;
931 			if ((c = pgetc()) == '-') {
932 				heredoc->striptabs = 1;
933 			} else {
934 				heredoc->striptabs = 0;
935 				pungetc();
936 			}
937 		} else if (c == '&')
938 			np->type = NFROMFD;
939 		else {
940 			np->type = NFROM;
941 			pungetc();
942 		}
943 	}
944 	if (fd != '\0')
945 		np->nfile.fd = digit_val(fd);
946 	redirnode = np;
947 	goto parseredir_return;
948 }
949 
950 
951 /*
952  * Parse a substitution.  At this point, we have read the dollar sign
953  * and nothing else.
954  */
955 
956 parsesub: {
957 	int subtype;
958 	int typeloc;
959 	int flags;
960 	char *p;
961 #ifndef GDB_HACK
962 	static const char types[] = "}-+?=";
963 #endif
964 
965 	c = pgetc();
966 	if (c != '(' && c != '{' && !is_name(c) && !is_special(c)) {
967 		USTPUTC('$', out);
968 		pungetc();
969 	} else if (c == '(') {	/* $(command) */
970 		PARSEBACKQNEW();
971 	} else {
972 		USTPUTC(CTLVAR, out);
973 		typeloc = out - stackblock();
974 		USTPUTC(VSNORMAL, out);
975 		subtype = VSNORMAL;
976 		if (c == '{') {
977 			c = pgetc();
978 			subtype = 0;
979 		}
980 		if (is_name(c)) {
981 			do {
982 				STPUTC(c, out);
983 				c = pgetc();
984 			} while (is_in_name(c));
985 		} else {
986 			if (! is_special(c))
987 badsub:				synerror("Bad substitution");
988 			USTPUTC(c, out);
989 			c = pgetc();
990 		}
991 		STPUTC('=', out);
992 		flags = 0;
993 		if (subtype == 0) {
994 			if (c == ':') {
995 				flags = VSNUL;
996 				c = pgetc();
997 			}
998 			p = strchr(types, c);
999 			if (p == NULL)
1000 				goto badsub;
1001 			subtype = p - types + VSNORMAL;
1002 		} else {
1003 			pungetc();
1004 		}
1005 		if (dblquote)
1006 			flags |= VSQUOTE;
1007 		*(stackblock() + typeloc) = subtype | flags;
1008 		if (subtype != VSNORMAL)
1009 			varnest++;
1010 	}
1011 	goto parsesub_return;
1012 }
1013 
1014 
1015 /*
1016  * Called to parse command substitutions.  Newstyle is set if the command
1017  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
1018  * list of commands (passed by reference), and savelen is the number of
1019  * characters on the top of the stack which must be preserved.
1020  */
1021 
1022 parsebackq: {
1023 	struct nodelist **nlpp;
1024 	int savepbq;
1025 	union node *n;
1026 	char *volatile str;
1027 	struct jmploc jmploc;
1028 	struct jmploc *volatile savehandler;
1029 	int savelen;
1030 	int t;
1031 
1032 	savepbq = parsebackquote;
1033 	if (setjmp(jmploc.loc)) {
1034 		if (str)
1035 			ckfree(str);
1036 		parsebackquote = 0;
1037 		handler = savehandler;
1038 		longjmp(handler, 1);
1039 	}
1040 	INTOFF;
1041 	str = NULL;
1042 	savelen = out - stackblock();
1043 	if (savelen > 0) {
1044 		str = ckmalloc(savelen);
1045 		bcopy(stackblock(), str, savelen);
1046 	}
1047 	savehandler = handler;
1048 	handler = &jmploc;
1049 	INTON;
1050 	nlpp = &bqlist;
1051 	while (*nlpp)
1052 		nlpp = &(*nlpp)->next;
1053 	*nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
1054 	(*nlpp)->next = NULL;
1055 	parsebackquote = oldstyle;
1056 	n = list(0);
1057 	t = oldstyle? TENDBQUOTE : TRP;
1058 	if (readtoken() != t)
1059 		synexpect(t);
1060 	(*nlpp)->n = n;
1061 	while (stackblocksize() <= savelen)
1062 		growstackblock();
1063 	STARTSTACKSTR(out);
1064 	if (str) {
1065 		bcopy(str, out, savelen);
1066 		STADJUST(savelen, out);
1067 		INTOFF;
1068 		ckfree(str);
1069 		str = NULL;
1070 		INTON;
1071 	}
1072 	parsebackquote = savepbq;
1073 	handler = savehandler;
1074 	USTPUTC(CTLBACKQ + dblquote, out);
1075 	if (oldstyle)
1076 		goto parsebackq_oldreturn;
1077 	else
1078 		goto parsebackq_newreturn;
1079 }
1080 
1081 } /* end of readtoken */
1082 
1083 
1084 
1085 #ifdef mkinit
1086 RESET {
1087 	tokpushback = 0;
1088 }
1089 #endif
1090 
1091 
1092 #if ATTY
1093 /*
1094  * Called to process a command generated by atty.  We execute the line,
1095  * and catch any errors that occur so they don't propagate outside of
1096  * this routine.
1097  */
1098 
1099 STATIC void
1100 attyline() {
1101 	char line[256];
1102 	struct stackmark smark;
1103 	struct jmploc jmploc;
1104 	struct jmploc *volatile savehandler;
1105 
1106 	if (pfgets(line, sizeof line) == NULL)
1107 		return;				/* "can't happen" */
1108 	if (setjmp(jmploc.loc)) {
1109 		if (exception == EXERROR)
1110 			out2str("\033]D\n");
1111 		handler = savehandler;
1112 		longjmp(handler, 1);
1113 	}
1114 	savehandler = handler;
1115 	handler = &jmploc;
1116 	setstackmark(&smark);
1117 	evalstring(line);
1118 	popstackmark(&smark);
1119 	handler = savehandler;
1120 	doprompt = 1;
1121 }
1122 
1123 
1124 /*
1125  * Output a prompt for atty.  We output the prompt as part of the
1126  * appropriate escape sequence.
1127  */
1128 
1129 STATIC void
1130 putprompt(s)
1131 	char *s;
1132 	{
1133 	register char *p;
1134 
1135 	if (attyset() && ! equal(termval(), "emacs")) {
1136 		if (strchr(s, '\7'))
1137 			out2c('\7');
1138 		out2str("\033]P1;");
1139 		for (p = s ; *p ; p++) {
1140 			if ((unsigned)(*p - ' ') <= '~' - ' ')
1141 				out2c(*p);
1142 		}
1143 		out2c('\n');
1144 	} else {
1145 		out2str(s);
1146 	}
1147 }
1148 #endif
1149 
1150 
1151 
1152 /*
1153  * Returns true if the text contains nothing to expand (no dollar signs
1154  * or backquotes).
1155  */
1156 
1157 STATIC int
1158 noexpand(text)
1159 	char *text;
1160 	{
1161 	register char *p;
1162 	register char c;
1163 
1164 	p = text;
1165 	while ((c = *p++) != '\0') {
1166 		if (c == CTLESC)
1167 			p++;
1168 		else if (BASESYNTAX[c] == CCTL)
1169 			return 0;
1170 	}
1171 	return 1;
1172 }
1173 
1174 
1175 /*
1176  * Return true if the argument is a legal variable name (a letter or
1177  * underscore followed by zero or more letters, underscores, and digits).
1178  */
1179 
1180 int
1181 goodname(name)
1182 	char *name;
1183 	{
1184 	register char *p;
1185 
1186 	p = name;
1187 	if (! is_name(*p))
1188 		return 0;
1189 	while (*++p) {
1190 		if (! is_in_name(*p))
1191 			return 0;
1192 	}
1193 	return 1;
1194 }
1195 
1196 
1197 /*
1198  * Called when an unexpected token is read during the parse.  The argument
1199  * is the token that is expected, or -1 if more than one type of token can
1200  * occur at this point.
1201  */
1202 
1203 STATIC void
1204 synexpect(token) {
1205 	char msg[64];
1206 
1207 	if (token >= 0) {
1208 		fmtstr(msg, 64, "%s unexpected (expecting %s)",
1209 			tokname[lasttoken], tokname[token]);
1210 	} else {
1211 		fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]);
1212 	}
1213 	synerror(msg);
1214 }
1215 
1216 
1217 STATIC void
1218 synerror(msg)
1219 	char *msg;
1220 	{
1221 	if (commandname)
1222 		outfmt(&errout, "%s: %d: ", commandname, startlinno);
1223 	outfmt(&errout, "Syntax error: %s\n", msg);
1224 	error((char *)NULL);
1225 }
1226