parser.c revision 208655
1167974Sdelphij/*-
2167974Sdelphij * Copyright (c) 1991, 1993
3167974Sdelphij *	The Regents of the University of California.  All rights reserved.
478556Sobrien *
5351008Sdelphij * This code is derived from software contributed to Berkeley by
6351008Sdelphij * Kenneth Almquist.
778556Sobrien *
8167974Sdelphij * Redistribution and use in source and binary forms, with or without
9167974Sdelphij * modification, are permitted provided that the following conditions
10167974Sdelphij * are met:
11167974Sdelphij * 1. Redistributions of source code must retain the above copyright
12167974Sdelphij *    notice, this list of conditions and the following disclaimer.
13167974Sdelphij * 2. Redistributions in binary form must reproduce the above copyright
14167974Sdelphij *    notice, this list of conditions and the following disclaimer in the
15167974Sdelphij *    documentation and/or other materials provided with the distribution.
1678556Sobrien * 4. Neither the name of the University nor the names of its contributors
1778556Sobrien *    may be used to endorse or promote products derived from this software
1878556Sobrien *    without specific prior written permission.
1978556Sobrien *
2078556Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2178556Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2278556Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2378556Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2478556Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2578556Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2678556Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2778556Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2878556Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2978556Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3078556Sobrien * SUCH DAMAGE.
3178556Sobrien */
3278556Sobrien
3378556Sobrien#ifndef lint
3478556Sobrien#if 0
3578556Sobrienstatic char sccsid[] = "@(#)parser.c	8.7 (Berkeley) 5/16/95";
3678556Sobrien#endif
3778556Sobrien#endif /* not lint */
3878556Sobrien#include <sys/cdefs.h>
3978556Sobrien__FBSDID("$FreeBSD: head/bin/sh/parser.c 208655 2010-05-30 14:11:27Z jilles $");
4078556Sobrien
4178556Sobrien#include <stdlib.h>
4278556Sobrien#include <unistd.h>
4378556Sobrien
4478556Sobrien#include "shell.h"
4578556Sobrien#include "parser.h"
4678556Sobrien#include "nodes.h"
4778556Sobrien#include "expand.h"	/* defines rmescapes() */
4878556Sobrien#include "syntax.h"
4978556Sobrien#include "options.h"
5078556Sobrien#include "input.h"
5178556Sobrien#include "output.h"
5278556Sobrien#include "var.h"
5378556Sobrien#include "error.h"
5478556Sobrien#include "memalloc.h"
5578556Sobrien#include "mystring.h"
5678556Sobrien#include "alias.h"
5778556Sobrien#include "show.h"
5878556Sobrien#include "eval.h"
5978556Sobrien#ifndef NO_HISTORY
6078556Sobrien#include "myhistedit.h"
6178556Sobrien#endif
6278556Sobrien
6378556Sobrien/*
6478556Sobrien * Shell command parser.
6578556Sobrien */
6678556Sobrien
6778556Sobrien#define	EOFMARKLEN	79
6878556Sobrien#define	PROMPTLEN	128
6978556Sobrien
7078556Sobrien/* values returned by readtoken */
7178556Sobrien#include "token.h"
7278556Sobrien
7378556Sobrien
7478556Sobrien
7578556Sobrienstruct heredoc {
7678556Sobrien	struct heredoc *next;	/* next here document in list */
7778556Sobrien	union node *here;		/* redirection node */
7878556Sobrien	char *eofmark;		/* string indicating end of input */
7978556Sobrien	int striptabs;		/* if set, strip leading tabs */
8078556Sobrien};
8178556Sobrien
8278556Sobrienstruct parser_temp {
8378556Sobrien	struct parser_temp *next;
8478556Sobrien	void *data;
8578556Sobrien};
8678556Sobrien
8778556Sobrien
8878556SobrienSTATIC struct heredoc *heredoclist;	/* list of here documents to read */
8978556SobrienSTATIC int doprompt;		/* if set, prompt the user */
9078556SobrienSTATIC int needprompt;		/* true if interactive and at start of line */
9178556SobrienSTATIC int lasttoken;		/* last token read */
9278556SobrienMKINIT int tokpushback;		/* last token pushed back */
9378556SobrienSTATIC char *wordtext;		/* text of last word returned by readtoken */
9478556SobrienMKINIT int checkkwd;            /* 1 == check for kwds, 2 == also eat newlines */
9578556SobrienSTATIC struct nodelist *backquotelist;
9678556SobrienSTATIC union node *redirnode;
9778556SobrienSTATIC struct heredoc *heredoc;
9878556SobrienSTATIC int quoteflag;		/* set if (part of) last token was quoted */
9978556SobrienSTATIC int startlinno;		/* line # where last token started */
10078556SobrienSTATIC int funclinno;		/* line # where the current function started */
10178556SobrienSTATIC struct parser_temp *parser_temp;
10278556Sobrien
10378556Sobrien/* XXX When 'noaliases' is set to one, no alias expansion takes place. */
10478556Sobrienstatic int noaliases = 0;
10578556Sobrien
10678556Sobrien
10778556SobrienSTATIC union node *list(int);
10878556SobrienSTATIC union node *andor(void);
10978556SobrienSTATIC union node *pipeline(void);
11078556SobrienSTATIC union node *command(void);
11178556SobrienSTATIC union node *simplecmd(union node **, union node *);
11278556SobrienSTATIC union node *makename(void);
11378556SobrienSTATIC void parsefname(void);
11478556SobrienSTATIC void parseheredoc(void);
11578556SobrienSTATIC int peektoken(void);
11678556SobrienSTATIC int readtoken(void);
11778556SobrienSTATIC int xxreadtoken(void);
11878556SobrienSTATIC int readtoken1(int, char const *, char *, int);
11978556SobrienSTATIC int noexpand(char *);
12078556SobrienSTATIC void synexpect(int);
12178556SobrienSTATIC void synerror(const char *);
12278556SobrienSTATIC void setprompt(int);
12378556Sobrien
12478556Sobrien
12578556SobrienSTATIC void *
12678556Sobrienparser_temp_alloc(size_t len)
12778556Sobrien{
12878556Sobrien	struct parser_temp *t;
12978556Sobrien
13078556Sobrien	INTOFF;
13178556Sobrien	t = ckmalloc(sizeof(*t));
13278556Sobrien	t->data = NULL;
13378556Sobrien	t->next = parser_temp;
13478556Sobrien	parser_temp = t;
13578556Sobrien	t->data = ckmalloc(len);
13678556Sobrien	INTON;
13778556Sobrien	return t->data;
13878556Sobrien}
13978556Sobrien
14078556Sobrien
14178556SobrienSTATIC void *
14278556Sobrienparser_temp_realloc(void *ptr, size_t len)
14378556Sobrien{
14478556Sobrien	struct parser_temp *t;
14578556Sobrien
14678556Sobrien	INTOFF;
14778556Sobrien	t = parser_temp;
14878556Sobrien	if (ptr != t->data)
14978556Sobrien		error("bug: parser_temp_realloc misused");
15090067Ssobomax	t->data = ckrealloc(t->data, len);
15178556Sobrien	INTON;
15278556Sobrien	return t->data;
15378556Sobrien}
15478556Sobrien
15578556Sobrien
15678556SobrienSTATIC void
15778556Sobrienparser_temp_free_upto(void *ptr)
15878556Sobrien{
15978556Sobrien	struct parser_temp *t;
16078556Sobrien	int done = 0;
16178556Sobrien
16278556Sobrien	INTOFF;
16378556Sobrien	while (parser_temp != NULL && !done) {
16478556Sobrien		t = parser_temp;
16578556Sobrien		parser_temp = t->next;
16678556Sobrien		done = t->data == ptr;
16778556Sobrien		ckfree(t->data);
16878556Sobrien		ckfree(t);
16978556Sobrien	}
17078556Sobrien	INTON;
17178556Sobrien	if (!done)
17278556Sobrien		error("bug: parser_temp_free_upto misused");
17378556Sobrien}
17478556Sobrien
17578556Sobrien
17678556SobrienSTATIC void
17778556Sobrienparser_temp_free_all(void)
17878556Sobrien{
17978556Sobrien	struct parser_temp *t;
18078556Sobrien
18190067Ssobomax	INTOFF;
18290067Ssobomax	while (parser_temp != NULL) {
18390067Ssobomax		t = parser_temp;
18490067Ssobomax		parser_temp = t->next;
18590067Ssobomax		ckfree(t->data);
18690067Ssobomax		ckfree(t);
18790067Ssobomax	}
18890067Ssobomax	INTON;
18990067Ssobomax}
19090067Ssobomax
19190067Ssobomax
19290067Ssobomax/*
19390067Ssobomax * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
19490067Ssobomax * valid parse tree indicating a blank line.)
19590067Ssobomax */
19690067Ssobomax
19790067Ssobomaxunion node *
19890067Ssobomaxparsecmd(int interact)
19990067Ssobomax{
20090067Ssobomax	int t;
20190067Ssobomax
20290067Ssobomax	/* This assumes the parser is not re-entered,
20390067Ssobomax	 * which could happen if we add command substitution on PS1/PS2.
20490067Ssobomax	 */
20590067Ssobomax	parser_temp_free_all();
20690067Ssobomax
20790067Ssobomax	tokpushback = 0;
20890067Ssobomax	doprompt = interact;
20990067Ssobomax	if (doprompt)
21090067Ssobomax		setprompt(1);
21190067Ssobomax	else
21290067Ssobomax		setprompt(0);
21390067Ssobomax	needprompt = 0;
21490067Ssobomax	t = readtoken();
21590067Ssobomax	if (t == TEOF)
21690067Ssobomax		return NEOF;
21790067Ssobomax	if (t == TNL)
21890067Ssobomax		return NULL;
21990067Ssobomax	tokpushback++;
22090067Ssobomax	return list(1);
22190067Ssobomax}
22290067Ssobomax
22390067Ssobomax
22490067SsobomaxSTATIC union node *
22590067Ssobomaxlist(int nlflag)
22690067Ssobomax{
22790067Ssobomax	union node *n1, *n2, *n3;
22890067Ssobomax	int tok;
22990067Ssobomax
23090067Ssobomax	checkkwd = 2;
23190067Ssobomax	if (nlflag == 0 && tokendlist[peektoken()])
23290067Ssobomax		return NULL;
23390067Ssobomax	n1 = NULL;
23490067Ssobomax	for (;;) {
23590067Ssobomax		n2 = andor();
23690067Ssobomax		tok = readtoken();
23790067Ssobomax		if (tok == TBACKGND) {
23890067Ssobomax			if (n2->type == NCMD || n2->type == NPIPE) {
23990067Ssobomax				n2->ncmd.backgnd = 1;
24090067Ssobomax			} else if (n2->type == NREDIR) {
24190067Ssobomax				n2->type = NBACKGND;
24290067Ssobomax			} else {
24390067Ssobomax				n3 = (union node *)stalloc(sizeof (struct nredir));
24490067Ssobomax				n3->type = NBACKGND;
24590067Ssobomax				n3->nredir.n = n2;
24690067Ssobomax				n3->nredir.redirect = NULL;
24790067Ssobomax				n2 = n3;
24890067Ssobomax			}
24990067Ssobomax		}
25090067Ssobomax		if (n1 == NULL) {
25190067Ssobomax			n1 = n2;
25290067Ssobomax		}
25390067Ssobomax		else {
25490067Ssobomax			n3 = (union node *)stalloc(sizeof (struct nbinary));
25590067Ssobomax			n3->type = NSEMI;
25690067Ssobomax			n3->nbinary.ch1 = n1;
25790067Ssobomax			n3->nbinary.ch2 = n2;
25890067Ssobomax			n1 = n3;
25990067Ssobomax		}
26090067Ssobomax		switch (tok) {
26190067Ssobomax		case TBACKGND:
26290067Ssobomax		case TSEMI:
26390067Ssobomax			tok = readtoken();
26490067Ssobomax			/* FALLTHROUGH */
26590067Ssobomax		case TNL:
26690067Ssobomax			if (tok == TNL) {
267146293Sobrien				parseheredoc();
268146293Sobrien				if (nlflag)
269146293Sobrien					return n1;
270146293Sobrien			} else {
271146293Sobrien				tokpushback++;
272146293Sobrien			}
273146293Sobrien			checkkwd = 2;
274146293Sobrien			if (tokendlist[peektoken()])
275146293Sobrien				return n1;
276146293Sobrien			break;
277167974Sdelphij		case TEOF:
278146293Sobrien			if (heredoclist)
279146293Sobrien				parseheredoc();
280146293Sobrien			else
281146293Sobrien				pungetc();		/* push back EOF on input */
282146293Sobrien			return n1;
283146293Sobrien		default:
284146293Sobrien			if (nlflag)
285146293Sobrien				synexpect(-1);
286146293Sobrien			tokpushback++;
287146293Sobrien			return n1;
288146293Sobrien		}
289167974Sdelphij	}
290167974Sdelphij}
291167974Sdelphij
292167974Sdelphij
293167974Sdelphij
294167974SdelphijSTATIC union node *
295167974Sdelphijandor(void)
296167974Sdelphij{
297167974Sdelphij	union node *n1, *n2, *n3;
298167974Sdelphij	int t;
299167974Sdelphij
300167974Sdelphij	n1 = pipeline();
301167974Sdelphij	for (;;) {
302167974Sdelphij		if ((t = readtoken()) == TAND) {
303167974Sdelphij			t = NAND;
304167974Sdelphij		} else if (t == TOR) {
305167974Sdelphij			t = NOR;
306167974Sdelphij		} else {
307167974Sdelphij			tokpushback++;
308167974Sdelphij			return n1;
309167974Sdelphij		}
310167974Sdelphij		n2 = pipeline();
311167974Sdelphij		n3 = (union node *)stalloc(sizeof (struct nbinary));
312167974Sdelphij		n3->type = t;
313167974Sdelphij		n3->nbinary.ch1 = n1;
314167974Sdelphij		n3->nbinary.ch2 = n2;
315177420Sdelphij		n1 = n3;
316177420Sdelphij	}
317177420Sdelphij}
318177420Sdelphij
319177420Sdelphij
320215041Sobrien
321215041SobrienSTATIC union node *
322215041Sobrienpipeline(void)
323215041Sobrien{
324215041Sobrien	union node *n1, *n2, *pipenode;
325215041Sobrien	struct nodelist *lp, *prev;
326215041Sobrien	int negate;
327215041Sobrien
328349719Sdelphij	negate = 0;
329349719Sdelphij	checkkwd = 2;
330349719Sdelphij	TRACE(("pipeline: entered\n"));
331349719Sdelphij	while (readtoken() == TNOT)
332349719Sdelphij		negate = !negate;
333349719Sdelphij	tokpushback++;
334349719Sdelphij	n1 = command();
335349719Sdelphij	if (readtoken() == TPIPE) {
336349719Sdelphij		pipenode = (union node *)stalloc(sizeof (struct npipe));
337349719Sdelphij		pipenode->type = NPIPE;
338349719Sdelphij		pipenode->npipe.backgnd = 0;
339349719Sdelphij		lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
340349719Sdelphij		pipenode->npipe.cmdlist = lp;
341351008Sdelphij		lp->n = n1;
342351008Sdelphij		do {
343351008Sdelphij			prev = lp;
344351008Sdelphij			lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
345351008Sdelphij			lp->n = command();
346351008Sdelphij			prev->next = lp;
347351008Sdelphij		} while (readtoken() == TPIPE);
348351008Sdelphij		lp->next = NULL;
349351008Sdelphij		n1 = pipenode;
350351008Sdelphij	}
351351008Sdelphij	tokpushback++;
352351008Sdelphij	if (negate) {
353351008Sdelphij		n2 = (union node *)stalloc(sizeof (struct nnot));
354351008Sdelphij		n2->type = NNOT;
355351008Sdelphij		n2->nnot.com = n1;
356351008Sdelphij		return n2;
357	} else
358		return n1;
359}
360
361
362
363STATIC union node *
364command(void)
365{
366	union node *n1, *n2;
367	union node *ap, **app;
368	union node *cp, **cpp;
369	union node *redir, **rpp;
370	int t, negate = 0;
371
372	checkkwd = 2;
373	redir = NULL;
374	n1 = NULL;
375	rpp = &redir;
376
377	/* Check for redirection which may precede command */
378	while (readtoken() == TREDIR) {
379		*rpp = n2 = redirnode;
380		rpp = &n2->nfile.next;
381		parsefname();
382	}
383	tokpushback++;
384
385	while (readtoken() == TNOT) {
386		TRACE(("command: TNOT recognized\n"));
387		negate = !negate;
388	}
389	tokpushback++;
390
391	switch (readtoken()) {
392	case TIF:
393		n1 = (union node *)stalloc(sizeof (struct nif));
394		n1->type = NIF;
395		if ((n1->nif.test = list(0)) == NULL)
396			synexpect(-1);
397		if (readtoken() != TTHEN)
398			synexpect(TTHEN);
399		n1->nif.ifpart = list(0);
400		n2 = n1;
401		while (readtoken() == TELIF) {
402			n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
403			n2 = n2->nif.elsepart;
404			n2->type = NIF;
405			if ((n2->nif.test = list(0)) == NULL)
406				synexpect(-1);
407			if (readtoken() != TTHEN)
408				synexpect(TTHEN);
409			n2->nif.ifpart = list(0);
410		}
411		if (lasttoken == TELSE)
412			n2->nif.elsepart = list(0);
413		else {
414			n2->nif.elsepart = NULL;
415			tokpushback++;
416		}
417		if (readtoken() != TFI)
418			synexpect(TFI);
419		checkkwd = 1;
420		break;
421	case TWHILE:
422	case TUNTIL: {
423		int got;
424		n1 = (union node *)stalloc(sizeof (struct nbinary));
425		n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
426		if ((n1->nbinary.ch1 = list(0)) == NULL)
427			synexpect(-1);
428		if ((got=readtoken()) != TDO) {
429TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
430			synexpect(TDO);
431		}
432		n1->nbinary.ch2 = list(0);
433		if (readtoken() != TDONE)
434			synexpect(TDONE);
435		checkkwd = 1;
436		break;
437	}
438	case TFOR:
439		if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
440			synerror("Bad for loop variable");
441		n1 = (union node *)stalloc(sizeof (struct nfor));
442		n1->type = NFOR;
443		n1->nfor.var = wordtext;
444		while (readtoken() == TNL)
445			;
446		if (lasttoken == TWORD && ! quoteflag && equal(wordtext, "in")) {
447			app = &ap;
448			while (readtoken() == TWORD) {
449				n2 = (union node *)stalloc(sizeof (struct narg));
450				n2->type = NARG;
451				n2->narg.text = wordtext;
452				n2->narg.backquote = backquotelist;
453				*app = n2;
454				app = &n2->narg.next;
455			}
456			*app = NULL;
457			n1->nfor.args = ap;
458			if (lasttoken != TNL && lasttoken != TSEMI)
459				synexpect(-1);
460		} else {
461			static char argvars[5] = {
462				CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
463			};
464			n2 = (union node *)stalloc(sizeof (struct narg));
465			n2->type = NARG;
466			n2->narg.text = argvars;
467			n2->narg.backquote = NULL;
468			n2->narg.next = NULL;
469			n1->nfor.args = n2;
470			/*
471			 * Newline or semicolon here is optional (but note
472			 * that the original Bourne shell only allowed NL).
473			 */
474			if (lasttoken != TNL && lasttoken != TSEMI)
475				tokpushback++;
476		}
477		checkkwd = 2;
478		if ((t = readtoken()) == TDO)
479			t = TDONE;
480		else if (t == TBEGIN)
481			t = TEND;
482		else
483			synexpect(-1);
484		n1->nfor.body = list(0);
485		if (readtoken() != t)
486			synexpect(t);
487		checkkwd = 1;
488		break;
489	case TCASE:
490		n1 = (union node *)stalloc(sizeof (struct ncase));
491		n1->type = NCASE;
492		if (readtoken() != TWORD)
493			synexpect(TWORD);
494		n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
495		n2->type = NARG;
496		n2->narg.text = wordtext;
497		n2->narg.backquote = backquotelist;
498		n2->narg.next = NULL;
499		while (readtoken() == TNL);
500		if (lasttoken != TWORD || ! equal(wordtext, "in"))
501			synerror("expecting \"in\"");
502		cpp = &n1->ncase.cases;
503		noaliases = 1;	/* turn off alias expansion */
504		checkkwd = 2, readtoken();
505		while (lasttoken != TESAC) {
506			*cpp = cp = (union node *)stalloc(sizeof (struct nclist));
507			cp->type = NCLIST;
508			app = &cp->nclist.pattern;
509			if (lasttoken == TLP)
510				readtoken();
511			for (;;) {
512				*app = ap = (union node *)stalloc(sizeof (struct narg));
513				ap->type = NARG;
514				ap->narg.text = wordtext;
515				ap->narg.backquote = backquotelist;
516				if (checkkwd = 2, readtoken() != TPIPE)
517					break;
518				app = &ap->narg.next;
519				readtoken();
520			}
521			ap->narg.next = NULL;
522			if (lasttoken != TRP)
523				noaliases = 0, synexpect(TRP);
524			cp->nclist.body = list(0);
525
526			checkkwd = 2;
527			if ((t = readtoken()) != TESAC) {
528				if (t != TENDCASE)
529					noaliases = 0, synexpect(TENDCASE);
530				else
531					checkkwd = 2, readtoken();
532			}
533			cpp = &cp->nclist.next;
534		}
535		noaliases = 0;	/* reset alias expansion */
536		*cpp = NULL;
537		checkkwd = 1;
538		break;
539	case TLP:
540		n1 = (union node *)stalloc(sizeof (struct nredir));
541		n1->type = NSUBSHELL;
542		n1->nredir.n = list(0);
543		n1->nredir.redirect = NULL;
544		if (readtoken() != TRP)
545			synexpect(TRP);
546		checkkwd = 1;
547		break;
548	case TBEGIN:
549		n1 = list(0);
550		if (readtoken() != TEND)
551			synexpect(TEND);
552		checkkwd = 1;
553		break;
554	/* Handle an empty command like other simple commands.  */
555	case TSEMI:
556	case TAND:
557	case TOR:
558		/*
559		 * An empty command before a ; doesn't make much sense, and
560		 * should certainly be disallowed in the case of `if ;'.
561		 */
562		if (!redir)
563			synexpect(-1);
564	case TNL:
565	case TEOF:
566	case TWORD:
567	case TRP:
568		tokpushback++;
569		n1 = simplecmd(rpp, redir);
570		goto checkneg;
571	default:
572		synexpect(-1);
573	}
574
575	/* Now check for redirection which may follow command */
576	while (readtoken() == TREDIR) {
577		*rpp = n2 = redirnode;
578		rpp = &n2->nfile.next;
579		parsefname();
580	}
581	tokpushback++;
582	*rpp = NULL;
583	if (redir) {
584		if (n1->type != NSUBSHELL) {
585			n2 = (union node *)stalloc(sizeof (struct nredir));
586			n2->type = NREDIR;
587			n2->nredir.n = n1;
588			n1 = n2;
589		}
590		n1->nredir.redirect = redir;
591	}
592
593checkneg:
594	if (negate) {
595		n2 = (union node *)stalloc(sizeof (struct nnot));
596		n2->type = NNOT;
597		n2->nnot.com = n1;
598		return n2;
599	}
600	else
601		return n1;
602}
603
604
605STATIC union node *
606simplecmd(union node **rpp, union node *redir)
607{
608	union node *args, **app;
609	union node **orig_rpp = rpp;
610	union node *n = NULL, *n2;
611	int negate = 0;
612
613	/* If we don't have any redirections already, then we must reset */
614	/* rpp to be the address of the local redir variable.  */
615	if (redir == 0)
616		rpp = &redir;
617
618	args = NULL;
619	app = &args;
620	/*
621	 * We save the incoming value, because we need this for shell
622	 * functions.  There can not be a redirect or an argument between
623	 * the function name and the open parenthesis.
624	 */
625	orig_rpp = rpp;
626
627	while (readtoken() == TNOT) {
628		TRACE(("command: TNOT recognized\n"));
629		negate = !negate;
630	}
631	tokpushback++;
632
633	for (;;) {
634		if (readtoken() == TWORD) {
635			n = (union node *)stalloc(sizeof (struct narg));
636			n->type = NARG;
637			n->narg.text = wordtext;
638			n->narg.backquote = backquotelist;
639			*app = n;
640			app = &n->narg.next;
641		} else if (lasttoken == TREDIR) {
642			*rpp = n = redirnode;
643			rpp = &n->nfile.next;
644			parsefname();	/* read name of redirection file */
645		} else if (lasttoken == TLP && app == &args->narg.next
646					    && rpp == orig_rpp) {
647			/* We have a function */
648			if (readtoken() != TRP)
649				synexpect(TRP);
650			funclinno = plinno;
651#ifdef notdef
652			if (! goodname(n->narg.text))
653				synerror("Bad function name");
654#endif
655			n->type = NDEFUN;
656			n->narg.next = command();
657			funclinno = 0;
658			goto checkneg;
659		} else {
660			tokpushback++;
661			break;
662		}
663	}
664	*app = NULL;
665	*rpp = NULL;
666	n = (union node *)stalloc(sizeof (struct ncmd));
667	n->type = NCMD;
668	n->ncmd.backgnd = 0;
669	n->ncmd.args = args;
670	n->ncmd.redirect = redir;
671
672checkneg:
673	if (negate) {
674		n2 = (union node *)stalloc(sizeof (struct nnot));
675		n2->type = NNOT;
676		n2->nnot.com = n;
677		return n2;
678	}
679	else
680		return n;
681}
682
683STATIC union node *
684makename(void)
685{
686	union node *n;
687
688	n = (union node *)stalloc(sizeof (struct narg));
689	n->type = NARG;
690	n->narg.next = NULL;
691	n->narg.text = wordtext;
692	n->narg.backquote = backquotelist;
693	return n;
694}
695
696void fixredir(union node *n, const char *text, int err)
697{
698	TRACE(("Fix redir %s %d\n", text, err));
699	if (!err)
700		n->ndup.vname = NULL;
701
702	if (is_digit(text[0]) && text[1] == '\0')
703		n->ndup.dupfd = digit_val(text[0]);
704	else if (text[0] == '-' && text[1] == '\0')
705		n->ndup.dupfd = -1;
706	else {
707
708		if (err)
709			synerror("Bad fd number");
710		else
711			n->ndup.vname = makename();
712	}
713}
714
715
716STATIC void
717parsefname(void)
718{
719	union node *n = redirnode;
720
721	if (readtoken() != TWORD)
722		synexpect(-1);
723	if (n->type == NHERE) {
724		struct heredoc *here = heredoc;
725		struct heredoc *p;
726		int i;
727
728		if (quoteflag == 0)
729			n->type = NXHERE;
730		TRACE(("Here document %d\n", n->type));
731		if (here->striptabs) {
732			while (*wordtext == '\t')
733				wordtext++;
734		}
735		if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
736			synerror("Illegal eof marker for << redirection");
737		rmescapes(wordtext);
738		here->eofmark = wordtext;
739		here->next = NULL;
740		if (heredoclist == NULL)
741			heredoclist = here;
742		else {
743			for (p = heredoclist ; p->next ; p = p->next);
744			p->next = here;
745		}
746	} else if (n->type == NTOFD || n->type == NFROMFD) {
747		fixredir(n, wordtext, 0);
748	} else {
749		n->nfile.fname = makename();
750	}
751}
752
753
754/*
755 * Input any here documents.
756 */
757
758STATIC void
759parseheredoc(void)
760{
761	struct heredoc *here;
762	union node *n;
763
764	while (heredoclist) {
765		here = heredoclist;
766		heredoclist = here->next;
767		if (needprompt) {
768			setprompt(2);
769			needprompt = 0;
770		}
771		readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
772				here->eofmark, here->striptabs);
773		n = (union node *)stalloc(sizeof (struct narg));
774		n->narg.type = NARG;
775		n->narg.next = NULL;
776		n->narg.text = wordtext;
777		n->narg.backquote = backquotelist;
778		here->here->nhere.doc = n;
779	}
780}
781
782STATIC int
783peektoken(void)
784{
785	int t;
786
787	t = readtoken();
788	tokpushback++;
789	return (t);
790}
791
792STATIC int
793readtoken(void)
794{
795	int t;
796	int savecheckkwd = checkkwd;
797	struct alias *ap;
798#ifdef DEBUG
799	int alreadyseen = tokpushback;
800#endif
801
802	top:
803	t = xxreadtoken();
804
805	if (checkkwd) {
806		/*
807		 * eat newlines
808		 */
809		if (checkkwd == 2) {
810			checkkwd = 0;
811			while (t == TNL) {
812				parseheredoc();
813				t = xxreadtoken();
814			}
815		} else
816			checkkwd = 0;
817		/*
818		 * check for keywords and aliases
819		 */
820		if (t == TWORD && !quoteflag)
821		{
822			const char * const *pp;
823
824			for (pp = parsekwd; *pp; pp++) {
825				if (**pp == *wordtext && equal(*pp, wordtext))
826				{
827					lasttoken = t = pp - parsekwd + KWDOFFSET;
828					TRACE(("keyword %s recognized\n", tokname[t]));
829					goto out;
830				}
831			}
832			if (noaliases == 0 &&
833			    (ap = lookupalias(wordtext, 1)) != NULL) {
834				pushstring(ap->val, strlen(ap->val), ap);
835				checkkwd = savecheckkwd;
836				goto top;
837			}
838		}
839out:
840		checkkwd = (t == TNOT) ? savecheckkwd : 0;
841	}
842#ifdef DEBUG
843	if (!alreadyseen)
844	    TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
845	else
846	    TRACE(("reread token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
847#endif
848	return (t);
849}
850
851
852/*
853 * Read the next input token.
854 * If the token is a word, we set backquotelist to the list of cmds in
855 *	backquotes.  We set quoteflag to true if any part of the word was
856 *	quoted.
857 * If the token is TREDIR, then we set redirnode to a structure containing
858 *	the redirection.
859 * In all cases, the variable startlinno is set to the number of the line
860 *	on which the token starts.
861 *
862 * [Change comment:  here documents and internal procedures]
863 * [Readtoken shouldn't have any arguments.  Perhaps we should make the
864 *  word parsing code into a separate routine.  In this case, readtoken
865 *  doesn't need to have any internal procedures, but parseword does.
866 *  We could also make parseoperator in essence the main routine, and
867 *  have parseword (readtoken1?) handle both words and redirection.]
868 */
869
870#define RETURN(token)	return lasttoken = token
871
872STATIC int
873xxreadtoken(void)
874{
875	int c;
876
877	if (tokpushback) {
878		tokpushback = 0;
879		return lasttoken;
880	}
881	if (needprompt) {
882		setprompt(2);
883		needprompt = 0;
884	}
885	startlinno = plinno;
886	for (;;) {	/* until token or start of word found */
887		c = pgetc_macro();
888		if (c == ' ' || c == '\t')
889			continue;		/* quick check for white space first */
890		switch (c) {
891		case ' ': case '\t':
892			continue;
893		case '#':
894			while ((c = pgetc()) != '\n' && c != PEOF);
895			pungetc();
896			continue;
897		case '\\':
898			if (pgetc() == '\n') {
899				startlinno = ++plinno;
900				if (doprompt)
901					setprompt(2);
902				else
903					setprompt(0);
904				continue;
905			}
906			pungetc();
907			goto breakloop;
908		case '\n':
909			plinno++;
910			needprompt = doprompt;
911			RETURN(TNL);
912		case PEOF:
913			RETURN(TEOF);
914		case '&':
915			if (pgetc() == '&')
916				RETURN(TAND);
917			pungetc();
918			RETURN(TBACKGND);
919		case '|':
920			if (pgetc() == '|')
921				RETURN(TOR);
922			pungetc();
923			RETURN(TPIPE);
924		case ';':
925			if (pgetc() == ';')
926				RETURN(TENDCASE);
927			pungetc();
928			RETURN(TSEMI);
929		case '(':
930			RETURN(TLP);
931		case ')':
932			RETURN(TRP);
933		default:
934			goto breakloop;
935		}
936	}
937breakloop:
938	return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
939#undef RETURN
940}
941
942
943#define MAXNEST_STATIC 8
944struct tokenstate
945{
946	const char *syntax; /* *SYNTAX */
947	int parenlevel; /* levels of parentheses in arithmetic */
948	enum tokenstate_category
949	{
950		TSTATE_TOP,
951		TSTATE_VAR_OLD, /* ${var+-=?}, inherits dquotes */
952		TSTATE_VAR_NEW, /* other ${var...}, own dquote state */
953		TSTATE_ARITH
954	} category;
955};
956
957
958/*
959 * Called to parse command substitutions.
960 */
961
962STATIC char *
963parsebackq(char *out, struct nodelist **pbqlist,
964		int oldstyle, int dblquote, int quoted)
965{
966	struct nodelist **nlpp;
967	union node *n;
968	char *volatile str;
969	struct jmploc jmploc;
970	struct jmploc *const savehandler = handler;
971	int savelen;
972	int saveprompt;
973	const int bq_startlinno = plinno;
974	char *volatile ostr = NULL;
975	struct parsefile *const savetopfile = getcurrentfile();
976	struct heredoc *const saveheredoclist = heredoclist;
977	struct heredoc *here;
978
979	str = NULL;
980	if (setjmp(jmploc.loc)) {
981		popfilesupto(savetopfile);
982		if (str)
983			ckfree(str);
984		if (ostr)
985			ckfree(ostr);
986		heredoclist = saveheredoclist;
987		handler = savehandler;
988		if (exception == EXERROR) {
989			startlinno = bq_startlinno;
990			synerror("Error in command substitution");
991		}
992		longjmp(handler->loc, 1);
993	}
994	INTOFF;
995	savelen = out - stackblock();
996	if (savelen > 0) {
997		str = ckmalloc(savelen);
998		memcpy(str, stackblock(), savelen);
999	}
1000	handler = &jmploc;
1001	heredoclist = NULL;
1002	INTON;
1003        if (oldstyle) {
1004                /* We must read until the closing backquote, giving special
1005                   treatment to some slashes, and then push the string and
1006                   reread it as input, interpreting it normally.  */
1007                char *oout;
1008                int c;
1009                int olen;
1010
1011
1012                STARTSTACKSTR(oout);
1013		for (;;) {
1014			if (needprompt) {
1015				setprompt(2);
1016				needprompt = 0;
1017			}
1018			switch (c = pgetc()) {
1019			case '`':
1020				goto done;
1021
1022			case '\\':
1023                                if ((c = pgetc()) == '\n') {
1024					plinno++;
1025					if (doprompt)
1026						setprompt(2);
1027					else
1028						setprompt(0);
1029					/*
1030					 * If eating a newline, avoid putting
1031					 * the newline into the new character
1032					 * stream (via the STPUTC after the
1033					 * switch).
1034					 */
1035					continue;
1036				}
1037                                if (c != '\\' && c != '`' && c != '$'
1038                                    && (!dblquote || c != '"'))
1039                                        STPUTC('\\', oout);
1040				break;
1041
1042			case '\n':
1043				plinno++;
1044				needprompt = doprompt;
1045				break;
1046
1047			case PEOF:
1048			        startlinno = plinno;
1049				synerror("EOF in backquote substitution");
1050 				break;
1051
1052			default:
1053				break;
1054			}
1055			STPUTC(c, oout);
1056                }
1057done:
1058                STPUTC('\0', oout);
1059                olen = oout - stackblock();
1060		INTOFF;
1061		ostr = ckmalloc(olen);
1062		memcpy(ostr, stackblock(), olen);
1063		setinputstring(ostr, 1);
1064		INTON;
1065        }
1066	nlpp = pbqlist;
1067	while (*nlpp)
1068		nlpp = &(*nlpp)->next;
1069	*nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
1070	(*nlpp)->next = NULL;
1071
1072	if (oldstyle) {
1073		saveprompt = doprompt;
1074		doprompt = 0;
1075	}
1076
1077	n = list(0);
1078
1079	if (oldstyle)
1080		doprompt = saveprompt;
1081	else {
1082		if (readtoken() != TRP)
1083			synexpect(TRP);
1084	}
1085
1086	(*nlpp)->n = n;
1087        if (oldstyle) {
1088		/*
1089		 * Start reading from old file again, ignoring any pushed back
1090		 * tokens left from the backquote parsing
1091		 */
1092                popfile();
1093		tokpushback = 0;
1094	}
1095	while (stackblocksize() <= savelen)
1096		growstackblock();
1097	STARTSTACKSTR(out);
1098	INTOFF;
1099	if (str) {
1100		memcpy(out, str, savelen);
1101		STADJUST(savelen, out);
1102		ckfree(str);
1103		str = NULL;
1104	}
1105	if (ostr) {
1106		ckfree(ostr);
1107		ostr = NULL;
1108	}
1109	here = saveheredoclist;
1110	if (here != NULL) {
1111		while (here->next != NULL)
1112			here = here->next;
1113		here->next = heredoclist;
1114		heredoclist = saveheredoclist;
1115	}
1116	handler = savehandler;
1117	INTON;
1118	if (quoted)
1119		USTPUTC(CTLBACKQ | CTLQUOTE, out);
1120	else
1121		USTPUTC(CTLBACKQ, out);
1122	return out;
1123}
1124
1125
1126/*
1127 * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
1128 * is not NULL, read a here document.  In the latter case, eofmark is the
1129 * word which marks the end of the document and striptabs is true if
1130 * leading tabs should be stripped from the document.  The argument firstc
1131 * is the first character of the input token or document.
1132 *
1133 * Because C does not have internal subroutines, I have simulated them
1134 * using goto's to implement the subroutine linkage.  The following macros
1135 * will run code that appears at the end of readtoken1.
1136 */
1137
1138#define CHECKEND()	{goto checkend; checkend_return:;}
1139#define PARSEREDIR()	{goto parseredir; parseredir_return:;}
1140#define PARSESUB()	{goto parsesub; parsesub_return:;}
1141#define	PARSEARITH()	{goto parsearith; parsearith_return:;}
1142
1143STATIC int
1144readtoken1(int firstc, char const *initialsyntax, char *eofmark, int striptabs)
1145{
1146	int c = firstc;
1147	char *out;
1148	int len;
1149	char line[EOFMARKLEN + 1];
1150	struct nodelist *bqlist;
1151	int quotef;
1152	int newvarnest;
1153	int level;
1154	int synentry;
1155	struct tokenstate state_static[MAXNEST_STATIC];
1156	int maxnest = MAXNEST_STATIC;
1157	struct tokenstate *state = state_static;
1158
1159	startlinno = plinno;
1160	quotef = 0;
1161	bqlist = NULL;
1162	newvarnest = 0;
1163	level = 0;
1164	state[level].syntax = initialsyntax;
1165	state[level].parenlevel = 0;
1166	state[level].category = TSTATE_TOP;
1167
1168	STARTSTACKSTR(out);
1169	loop: {	/* for each line, until end of word */
1170		CHECKEND();	/* set c to PEOF if at end of here document */
1171		for (;;) {	/* until end of line or end of word */
1172			CHECKSTRSPACE(3, out);	/* permit 3 calls to USTPUTC */
1173
1174			synentry = state[level].syntax[c];
1175
1176			switch(synentry) {
1177			case CNL:	/* '\n' */
1178				if (state[level].syntax == BASESYNTAX)
1179					goto endword;	/* exit outer loop */
1180				USTPUTC(c, out);
1181				plinno++;
1182				if (doprompt)
1183					setprompt(2);
1184				else
1185					setprompt(0);
1186				c = pgetc();
1187				goto loop;		/* continue outer loop */
1188			case CWORD:
1189				USTPUTC(c, out);
1190				break;
1191			case CCTL:
1192				if (eofmark == NULL || initialsyntax != SQSYNTAX)
1193					USTPUTC(CTLESC, out);
1194				USTPUTC(c, out);
1195				break;
1196			case CBACK:	/* backslash */
1197				c = pgetc();
1198				if (c == PEOF) {
1199					USTPUTC('\\', out);
1200					pungetc();
1201				} else if (c == '\n') {
1202					plinno++;
1203					if (doprompt)
1204						setprompt(2);
1205					else
1206						setprompt(0);
1207				} else {
1208					if (state[level].syntax == DQSYNTAX &&
1209					    c != '\\' && c != '`' && c != '$' &&
1210					    (c != '"' || (eofmark != NULL &&
1211						newvarnest == 0)) &&
1212					    (c != '}' || state[level].category != TSTATE_VAR_OLD))
1213						USTPUTC('\\', out);
1214					if (SQSYNTAX[c] == CCTL)
1215						USTPUTC(CTLESC, out);
1216					else if (eofmark == NULL ||
1217					    newvarnest > 0)
1218						USTPUTC(CTLQUOTEMARK, out);
1219					USTPUTC(c, out);
1220					quotef++;
1221				}
1222				break;
1223			case CSQUOTE:
1224				USTPUTC(CTLQUOTEMARK, out);
1225				state[level].syntax = SQSYNTAX;
1226				break;
1227			case CDQUOTE:
1228				USTPUTC(CTLQUOTEMARK, out);
1229				state[level].syntax = DQSYNTAX;
1230				break;
1231			case CENDQUOTE:
1232				if (eofmark != NULL && newvarnest == 0)
1233					USTPUTC(c, out);
1234				else {
1235					if (state[level].category == TSTATE_ARITH)
1236						state[level].syntax = ARISYNTAX;
1237					else
1238						state[level].syntax = BASESYNTAX;
1239					quotef++;
1240				}
1241				break;
1242			case CVAR:	/* '$' */
1243				PARSESUB();		/* parse substitution */
1244				break;
1245			case CENDVAR:	/* '}' */
1246				if (level > 0 &&
1247				    (state[level].category == TSTATE_VAR_OLD ||
1248				    state[level].category == TSTATE_VAR_NEW)) {
1249					if (state[level].category == TSTATE_VAR_OLD)
1250						state[level - 1].syntax = state[level].syntax;
1251					else
1252						newvarnest--;
1253					level--;
1254					USTPUTC(CTLENDVAR, out);
1255				} else {
1256					USTPUTC(c, out);
1257				}
1258				break;
1259			case CLP:	/* '(' in arithmetic */
1260				state[level].parenlevel++;
1261				USTPUTC(c, out);
1262				break;
1263			case CRP:	/* ')' in arithmetic */
1264				if (state[level].parenlevel > 0) {
1265					USTPUTC(c, out);
1266					--state[level].parenlevel;
1267				} else {
1268					if (pgetc() == ')') {
1269						if (level > 0 &&
1270						    state[level].category == TSTATE_ARITH) {
1271							level--;
1272							USTPUTC(CTLENDARI, out);
1273						} else
1274							USTPUTC(')', out);
1275					} else {
1276						/*
1277						 * unbalanced parens
1278						 *  (don't 2nd guess - no error)
1279						 */
1280						pungetc();
1281						USTPUTC(')', out);
1282					}
1283				}
1284				break;
1285			case CBQUOTE:	/* '`' */
1286				out = parsebackq(out, &bqlist, 1,
1287				    state[level].syntax == DQSYNTAX &&
1288				    (eofmark == NULL || newvarnest > 0),
1289				    state[level].syntax == DQSYNTAX || state[level].syntax == ARISYNTAX);
1290				break;
1291			case CEOF:
1292				goto endword;		/* exit outer loop */
1293			default:
1294				if (level == 0)
1295					goto endword;	/* exit outer loop */
1296				USTPUTC(c, out);
1297			}
1298			c = pgetc_macro();
1299		}
1300	}
1301endword:
1302	if (state[level].syntax == ARISYNTAX)
1303		synerror("Missing '))'");
1304	if (state[level].syntax != BASESYNTAX && eofmark == NULL)
1305		synerror("Unterminated quoted string");
1306	if (state[level].category == TSTATE_VAR_OLD ||
1307	    state[level].category == TSTATE_VAR_NEW) {
1308		startlinno = plinno;
1309		synerror("Missing '}'");
1310	}
1311	if (state != state_static)
1312		parser_temp_free_upto(state);
1313	USTPUTC('\0', out);
1314	len = out - stackblock();
1315	out = stackblock();
1316	if (eofmark == NULL) {
1317		if ((c == '>' || c == '<')
1318		 && quotef == 0
1319		 && len <= 2
1320		 && (*out == '\0' || is_digit(*out))) {
1321			PARSEREDIR();
1322			return lasttoken = TREDIR;
1323		} else {
1324			pungetc();
1325		}
1326	}
1327	quoteflag = quotef;
1328	backquotelist = bqlist;
1329	grabstackblock(len);
1330	wordtext = out;
1331	return lasttoken = TWORD;
1332/* end of readtoken routine */
1333
1334
1335/*
1336 * Check to see whether we are at the end of the here document.  When this
1337 * is called, c is set to the first character of the next input line.  If
1338 * we are at the end of the here document, this routine sets the c to PEOF.
1339 */
1340
1341checkend: {
1342	if (eofmark) {
1343		if (striptabs) {
1344			while (c == '\t')
1345				c = pgetc();
1346		}
1347		if (c == *eofmark) {
1348			if (pfgets(line, sizeof line) != NULL) {
1349				char *p, *q;
1350
1351				p = line;
1352				for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
1353				if (*p == '\n' && *q == '\0') {
1354					c = PEOF;
1355					plinno++;
1356					needprompt = doprompt;
1357				} else {
1358					pushstring(line, strlen(line), NULL);
1359				}
1360			}
1361		}
1362	}
1363	goto checkend_return;
1364}
1365
1366
1367/*
1368 * Parse a redirection operator.  The variable "out" points to a string
1369 * specifying the fd to be redirected.  The variable "c" contains the
1370 * first character of the redirection operator.
1371 */
1372
1373parseredir: {
1374	char fd = *out;
1375	union node *np;
1376
1377	np = (union node *)stalloc(sizeof (struct nfile));
1378	if (c == '>') {
1379		np->nfile.fd = 1;
1380		c = pgetc();
1381		if (c == '>')
1382			np->type = NAPPEND;
1383		else if (c == '&')
1384			np->type = NTOFD;
1385		else if (c == '|')
1386			np->type = NCLOBBER;
1387		else {
1388			np->type = NTO;
1389			pungetc();
1390		}
1391	} else {	/* c == '<' */
1392		np->nfile.fd = 0;
1393		c = pgetc();
1394		if (c == '<') {
1395			if (sizeof (struct nfile) != sizeof (struct nhere)) {
1396				np = (union node *)stalloc(sizeof (struct nhere));
1397				np->nfile.fd = 0;
1398			}
1399			np->type = NHERE;
1400			heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
1401			heredoc->here = np;
1402			if ((c = pgetc()) == '-') {
1403				heredoc->striptabs = 1;
1404			} else {
1405				heredoc->striptabs = 0;
1406				pungetc();
1407			}
1408		} else if (c == '&')
1409			np->type = NFROMFD;
1410		else if (c == '>')
1411			np->type = NFROMTO;
1412		else {
1413			np->type = NFROM;
1414			pungetc();
1415		}
1416	}
1417	if (fd != '\0')
1418		np->nfile.fd = digit_val(fd);
1419	redirnode = np;
1420	goto parseredir_return;
1421}
1422
1423
1424/*
1425 * Parse a substitution.  At this point, we have read the dollar sign
1426 * and nothing else.
1427 */
1428
1429parsesub: {
1430	char buf[10];
1431	int subtype;
1432	int typeloc;
1433	int flags;
1434	char *p;
1435	static const char types[] = "}-+?=";
1436	int bracketed_name = 0; /* used to handle ${[0-9]*} variables */
1437	int i;
1438	int linno;
1439	int length;
1440
1441	c = pgetc();
1442	if (c != '(' && c != '{' && (is_eof(c) || !is_name(c)) &&
1443	    !is_special(c)) {
1444		USTPUTC('$', out);
1445		pungetc();
1446	} else if (c == '(') {	/* $(command) or $((arith)) */
1447		if (pgetc() == '(') {
1448			PARSEARITH();
1449		} else {
1450			pungetc();
1451			out = parsebackq(out, &bqlist, 0,
1452			    state[level].syntax == DQSYNTAX &&
1453			    (eofmark == NULL || newvarnest > 0),
1454			    state[level].syntax == DQSYNTAX ||
1455			    state[level].syntax == ARISYNTAX);
1456		}
1457	} else {
1458		USTPUTC(CTLVAR, out);
1459		typeloc = out - stackblock();
1460		USTPUTC(VSNORMAL, out);
1461		subtype = VSNORMAL;
1462		flags = 0;
1463		if (c == '{') {
1464			bracketed_name = 1;
1465			c = pgetc();
1466			if (c == '#') {
1467				if ((c = pgetc()) == '}')
1468					c = '#';
1469				else
1470					subtype = VSLENGTH;
1471			}
1472			else
1473				subtype = 0;
1474		}
1475		if (!is_eof(c) && is_name(c)) {
1476			length = 0;
1477			do {
1478				STPUTC(c, out);
1479				c = pgetc();
1480				length++;
1481			} while (!is_eof(c) && is_in_name(c));
1482			if (length == 6 &&
1483			    strncmp(out - length, "LINENO", length) == 0) {
1484				/* Replace the variable name with the
1485				 * current line number. */
1486				linno = plinno;
1487				if (funclinno != 0)
1488					linno -= funclinno - 1;
1489				snprintf(buf, sizeof(buf), "%d", linno);
1490				STADJUST(-6, out);
1491				for (i = 0; buf[i] != '\0'; i++)
1492					STPUTC(buf[i], out);
1493				flags |= VSLINENO;
1494			}
1495		} else if (is_digit(c)) {
1496			if (bracketed_name) {
1497				do {
1498					STPUTC(c, out);
1499					c = pgetc();
1500				} while (is_digit(c));
1501			} else {
1502				STPUTC(c, out);
1503				c = pgetc();
1504			}
1505		} else {
1506			if (! is_special(c)) {
1507				subtype = VSERROR;
1508				if (c == '}')
1509					pungetc();
1510				else if (c == '\n' || c == PEOF)
1511					synerror("Unexpected end of line in substitution");
1512				else
1513					USTPUTC(c, out);
1514			} else {
1515				USTPUTC(c, out);
1516				c = pgetc();
1517			}
1518		}
1519		if (subtype == 0) {
1520			switch (c) {
1521			case ':':
1522				flags |= VSNUL;
1523				c = pgetc();
1524				/*FALLTHROUGH*/
1525			default:
1526				p = strchr(types, c);
1527				if (p == NULL) {
1528					if (c == '\n' || c == PEOF)
1529						synerror("Unexpected end of line in substitution");
1530					if (flags == VSNUL)
1531						STPUTC(':', out);
1532					STPUTC(c, out);
1533					subtype = VSERROR;
1534				} else
1535					subtype = p - types + VSNORMAL;
1536				break;
1537			case '%':
1538			case '#':
1539				{
1540					int cc = c;
1541					subtype = c == '#' ? VSTRIMLEFT :
1542							     VSTRIMRIGHT;
1543					c = pgetc();
1544					if (c == cc)
1545						subtype++;
1546					else
1547						pungetc();
1548					break;
1549				}
1550			}
1551		} else if (subtype != VSERROR) {
1552			pungetc();
1553		}
1554		STPUTC('=', out);
1555		if (subtype != VSLENGTH && (state[level].syntax == DQSYNTAX ||
1556		    state[level].syntax == ARISYNTAX))
1557			flags |= VSQUOTE;
1558		*(stackblock() + typeloc) = subtype | flags;
1559		if (subtype != VSNORMAL) {
1560			if (level + 1 >= maxnest) {
1561				maxnest *= 2;
1562				if (state == state_static) {
1563					state = parser_temp_alloc(
1564					    maxnest * sizeof(*state));
1565					memcpy(state, state_static,
1566					    MAXNEST_STATIC * sizeof(*state));
1567				} else
1568					state = parser_temp_realloc(state,
1569					    maxnest * sizeof(*state));
1570			}
1571			level++;
1572			state[level].parenlevel = 0;
1573			if (subtype == VSMINUS || subtype == VSPLUS ||
1574			    subtype == VSQUESTION || subtype == VSASSIGN) {
1575				/*
1576				 * For operators that were in the Bourne shell,
1577				 * inherit the double-quote state.
1578				 */
1579				state[level].syntax = state[level - 1].syntax;
1580				state[level].category = TSTATE_VAR_OLD;
1581			} else {
1582				/*
1583				 * The other operators take a pattern,
1584				 * so go to BASESYNTAX.
1585				 * Also, ' and " are now special, even
1586				 * in here documents.
1587				 */
1588				state[level].syntax = BASESYNTAX;
1589				state[level].category = TSTATE_VAR_NEW;
1590				newvarnest++;
1591			}
1592		}
1593	}
1594	goto parsesub_return;
1595}
1596
1597
1598/*
1599 * Parse an arithmetic expansion (indicate start of one and set state)
1600 */
1601parsearith: {
1602
1603	if (level + 1 >= maxnest) {
1604		maxnest *= 2;
1605		if (state == state_static) {
1606			state = parser_temp_alloc(
1607			    maxnest * sizeof(*state));
1608			memcpy(state, state_static,
1609			    MAXNEST_STATIC * sizeof(*state));
1610		} else
1611			state = parser_temp_realloc(state,
1612			    maxnest * sizeof(*state));
1613	}
1614	level++;
1615	state[level].syntax = ARISYNTAX;
1616	state[level].parenlevel = 0;
1617	state[level].category = TSTATE_ARITH;
1618	USTPUTC(CTLARI, out);
1619	if (state[level - 1].syntax == DQSYNTAX)
1620		USTPUTC('"',out);
1621	else
1622		USTPUTC(' ',out);
1623	goto parsearith_return;
1624}
1625
1626} /* end of readtoken */
1627
1628
1629
1630#ifdef mkinit
1631RESET {
1632	tokpushback = 0;
1633	checkkwd = 0;
1634}
1635#endif
1636
1637/*
1638 * Returns true if the text contains nothing to expand (no dollar signs
1639 * or backquotes).
1640 */
1641
1642STATIC int
1643noexpand(char *text)
1644{
1645	char *p;
1646	char c;
1647
1648	p = text;
1649	while ((c = *p++) != '\0') {
1650		if ( c == CTLQUOTEMARK)
1651			continue;
1652		if (c == CTLESC)
1653			p++;
1654		else if (BASESYNTAX[(int)c] == CCTL)
1655			return 0;
1656	}
1657	return 1;
1658}
1659
1660
1661/*
1662 * Return true if the argument is a legal variable name (a letter or
1663 * underscore followed by zero or more letters, underscores, and digits).
1664 */
1665
1666int
1667goodname(const char *name)
1668{
1669	const char *p;
1670
1671	p = name;
1672	if (! is_name(*p))
1673		return 0;
1674	while (*++p) {
1675		if (! is_in_name(*p))
1676			return 0;
1677	}
1678	return 1;
1679}
1680
1681
1682/*
1683 * Called when an unexpected token is read during the parse.  The argument
1684 * is the token that is expected, or -1 if more than one type of token can
1685 * occur at this point.
1686 */
1687
1688STATIC void
1689synexpect(int token)
1690{
1691	char msg[64];
1692
1693	if (token >= 0) {
1694		fmtstr(msg, 64, "%s unexpected (expecting %s)",
1695			tokname[lasttoken], tokname[token]);
1696	} else {
1697		fmtstr(msg, 64, "%s unexpected", tokname[lasttoken]);
1698	}
1699	synerror(msg);
1700}
1701
1702
1703STATIC void
1704synerror(const char *msg)
1705{
1706	if (commandname)
1707		outfmt(out2, "%s: %d: ", commandname, startlinno);
1708	outfmt(out2, "Syntax error: %s\n", msg);
1709	error((char *)NULL);
1710}
1711
1712STATIC void
1713setprompt(int which)
1714{
1715	whichprompt = which;
1716
1717#ifndef NO_HISTORY
1718	if (!el)
1719#endif
1720	{
1721		out2str(getprompt(NULL));
1722		flushout(out2);
1723	}
1724}
1725
1726/*
1727 * called by editline -- any expansions to the prompt
1728 *    should be added here.
1729 */
1730char *
1731getprompt(void *unused __unused)
1732{
1733	static char ps[PROMPTLEN];
1734	char *fmt;
1735	int i, j, trim;
1736	static char internal_error[] = "<internal prompt error>";
1737
1738	/*
1739	 * Select prompt format.
1740	 */
1741	switch (whichprompt) {
1742	case 0:
1743		fmt = nullstr;
1744		break;
1745	case 1:
1746		fmt = ps1val();
1747		break;
1748	case 2:
1749		fmt = ps2val();
1750		break;
1751	default:
1752		return internal_error;
1753	}
1754
1755	/*
1756	 * Format prompt string.
1757	 */
1758	for (i = 0; (i < 127) && (*fmt != '\0'); i++, fmt++)
1759		if (*fmt == '\\')
1760			switch (*++fmt) {
1761
1762				/*
1763				 * Hostname.
1764				 *
1765				 * \h specifies just the local hostname,
1766				 * \H specifies fully-qualified hostname.
1767				 */
1768			case 'h':
1769			case 'H':
1770				ps[i] = '\0';
1771				gethostname(&ps[i], PROMPTLEN - i);
1772				/* Skip to end of hostname. */
1773				trim = (*fmt == 'h') ? '.' : '\0';
1774				while ((ps[i+1] != '\0') && (ps[i+1] != trim))
1775					i++;
1776				break;
1777
1778				/*
1779				 * Working directory.
1780				 *
1781				 * \W specifies just the final component,
1782				 * \w specifies the entire path.
1783				 */
1784			case 'W':
1785			case 'w':
1786				ps[i] = '\0';
1787				getcwd(&ps[i], PROMPTLEN - i);
1788				if (*fmt == 'W' && ps[i + 1] != '\0') {
1789					/* Final path component only. */
1790					trim = 1;
1791					for (j = i; ps[j] != '\0'; j++)
1792					  if (ps[j] == '/')
1793						trim = j + 1;
1794					memmove(&ps[i], &ps[trim],
1795					    j - trim + 1);
1796				}
1797				/* Skip to end of path. */
1798				while (ps[i + 1] != '\0')
1799					i++;
1800				break;
1801
1802				/*
1803				 * Superuser status.
1804				 *
1805				 * '$' for normal users, '#' for root.
1806				 */
1807			case '$':
1808				ps[i] = (geteuid() != 0) ? '$' : '#';
1809				break;
1810
1811				/*
1812				 * A literal \.
1813				 */
1814			case '\\':
1815				ps[i] = '\\';
1816				break;
1817
1818				/*
1819				 * Emit unrecognized formats verbatim.
1820				 */
1821			default:
1822				ps[i++] = '\\';
1823				ps[i] = *fmt;
1824				break;
1825			}
1826		else
1827			ps[i] = *fmt;
1828	ps[i] = '\0';
1829	return (ps);
1830}
1831