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