xref: /plan9/sys/src/cmd/rc/lex.c (revision 4e3613ab15c331a9ada113286cc0f2a35bc0373d)
13e12c5d1SDavid du Colombier #include "rc.h"
23e12c5d1SDavid du Colombier #include "exec.h"
33e12c5d1SDavid du Colombier #include "io.h"
43e12c5d1SDavid du Colombier #include "getflags.h"
53e12c5d1SDavid du Colombier #include "fns.h"
63e12c5d1SDavid du Colombier int getnext(void);
7dc5a79c1SDavid du Colombier 
8dc5a79c1SDavid du Colombier int
wordchr(int c)9dc5a79c1SDavid du Colombier wordchr(int c)
103e12c5d1SDavid du Colombier {
113e12c5d1SDavid du Colombier 	return !strchr("\n \t#;&|^$=`'{}()<>", c) && c!=EOF;
123e12c5d1SDavid du Colombier }
13dc5a79c1SDavid du Colombier 
14dc5a79c1SDavid du Colombier int
idchr(int c)15dc5a79c1SDavid du Colombier idchr(int c)
163e12c5d1SDavid du Colombier {
173e12c5d1SDavid du Colombier 	/*
183e12c5d1SDavid du Colombier 	 * Formerly:
193e12c5d1SDavid du Colombier 	 * return 'a'<=c && c<='z' || 'A'<=c && c<='Z' || '0'<=c && c<='9'
203e12c5d1SDavid du Colombier 	 *	|| c=='_' || c=='*';
213e12c5d1SDavid du Colombier 	 */
223e12c5d1SDavid du Colombier 	return c>' ' && !strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c);
233e12c5d1SDavid du Colombier }
243e12c5d1SDavid du Colombier int future = EOF;
253e12c5d1SDavid du Colombier int doprompt = 1;
263e12c5d1SDavid du Colombier int inquote;
276852fd5aSDavid du Colombier int incomm;
283e12c5d1SDavid du Colombier /*
293e12c5d1SDavid du Colombier  * Look ahead in the input stream
303e12c5d1SDavid du Colombier  */
31dc5a79c1SDavid du Colombier 
32dc5a79c1SDavid du Colombier int
nextc(void)33dc5a79c1SDavid du Colombier nextc(void)
34dc5a79c1SDavid du Colombier {
35dc5a79c1SDavid du Colombier 	if(future==EOF)
36dc5a79c1SDavid du Colombier 		future = getnext();
373e12c5d1SDavid du Colombier 	return future;
383e12c5d1SDavid du Colombier }
393e12c5d1SDavid du Colombier /*
403e12c5d1SDavid du Colombier  * Consume the lookahead character.
413e12c5d1SDavid du Colombier  */
42dc5a79c1SDavid du Colombier 
43dc5a79c1SDavid du Colombier int
advance(void)44dc5a79c1SDavid du Colombier advance(void)
45dc5a79c1SDavid du Colombier {
463e12c5d1SDavid du Colombier 	int c = nextc();
473e12c5d1SDavid du Colombier 	lastc = future;
483e12c5d1SDavid du Colombier 	future = EOF;
493e12c5d1SDavid du Colombier 	return c;
503e12c5d1SDavid du Colombier }
513e12c5d1SDavid du Colombier /*
523e12c5d1SDavid du Colombier  * read a character from the input stream
533e12c5d1SDavid du Colombier  */
54dc5a79c1SDavid du Colombier 
55dc5a79c1SDavid du Colombier int
getnext(void)56dc5a79c1SDavid du Colombier getnext(void)
57dc5a79c1SDavid du Colombier {
58dc5a79c1SDavid du Colombier 	int c;
59d3907fe5SDavid du Colombier 	static int peekc = EOF;
603e12c5d1SDavid du Colombier 	if(peekc!=EOF){
613e12c5d1SDavid du Colombier 		c = peekc;
623e12c5d1SDavid du Colombier 		peekc = EOF;
633e12c5d1SDavid du Colombier 		return c;
643e12c5d1SDavid du Colombier 	}
65dc5a79c1SDavid du Colombier 	if(runq->eof)
66dc5a79c1SDavid du Colombier 		return EOF;
67dc5a79c1SDavid du Colombier 	if(doprompt)
68dc5a79c1SDavid du Colombier 		pprompt();
693e12c5d1SDavid du Colombier 	c = rchr(runq->cmdfd);
703e12c5d1SDavid du Colombier 	if(!inquote && c=='\\'){
713e12c5d1SDavid du Colombier 		c = rchr(runq->cmdfd);
726852fd5aSDavid du Colombier 		if(c=='\n' && !incomm){		/* don't continue a comment */
733e12c5d1SDavid du Colombier 			doprompt = 1;
743e12c5d1SDavid du Colombier 			c=' ';
753e12c5d1SDavid du Colombier 		}
763e12c5d1SDavid du Colombier 		else{
773e12c5d1SDavid du Colombier 			peekc = c;
783e12c5d1SDavid du Colombier 			c='\\';
793e12c5d1SDavid du Colombier 		}
803e12c5d1SDavid du Colombier 	}
813e12c5d1SDavid du Colombier 	doprompt = doprompt || c=='\n' || c==EOF;
82dc5a79c1SDavid du Colombier 	if(c==EOF)
83dc5a79c1SDavid du Colombier 		runq->eof++;
843e12c5d1SDavid du Colombier 	else if(flag['V'] || ndot>=2 && flag['v']) pchr(err, c);
853e12c5d1SDavid du Colombier 	return c;
863e12c5d1SDavid du Colombier }
87dc5a79c1SDavid du Colombier 
88dc5a79c1SDavid du Colombier void
pprompt(void)89dc5a79c1SDavid du Colombier pprompt(void)
90dc5a79c1SDavid du Colombier {
913e12c5d1SDavid du Colombier 	var *prompt;
923e12c5d1SDavid du Colombier 	if(runq->iflag){
933e12c5d1SDavid du Colombier 		pstr(err, promptstr);
943e12c5d1SDavid du Colombier 		flush(err);
953e12c5d1SDavid du Colombier 		prompt = vlook("prompt");
963e12c5d1SDavid du Colombier 		if(prompt->val && prompt->val->next)
973e12c5d1SDavid du Colombier 			promptstr = prompt->val->next->word;
983e12c5d1SDavid du Colombier 		else
993e12c5d1SDavid du Colombier 			promptstr="\t";
1003e12c5d1SDavid du Colombier 	}
1013e12c5d1SDavid du Colombier 	runq->lineno++;
1023e12c5d1SDavid du Colombier 	doprompt = 0;
1033e12c5d1SDavid du Colombier }
104dc5a79c1SDavid du Colombier 
105dc5a79c1SDavid du Colombier void
skipwhite(void)106dc5a79c1SDavid du Colombier skipwhite(void)
107dc5a79c1SDavid du Colombier {
1083e12c5d1SDavid du Colombier 	int c;
1093e12c5d1SDavid du Colombier 	for(;;){
1103e12c5d1SDavid du Colombier 		c = nextc();
1116852fd5aSDavid du Colombier 		/* Why did this used to be  if(!inquote && c=='#') ?? */
1126852fd5aSDavid du Colombier 		if(c=='#'){
1136852fd5aSDavid du Colombier 			incomm = 1;
1143e12c5d1SDavid du Colombier 			for(;;){
1153e12c5d1SDavid du Colombier 				c = nextc();
1166852fd5aSDavid du Colombier 				if(c=='\n' || c==EOF) {
1176852fd5aSDavid du Colombier 					incomm = 0;
118dc5a79c1SDavid du Colombier 					break;
1196852fd5aSDavid du Colombier 				}
1203e12c5d1SDavid du Colombier 				advance();
1213e12c5d1SDavid du Colombier 			}
1223e12c5d1SDavid du Colombier 		}
123dc5a79c1SDavid du Colombier 		if(c==' ' || c=='\t')
124dc5a79c1SDavid du Colombier 			advance();
1253e12c5d1SDavid du Colombier 		else return;
1263e12c5d1SDavid du Colombier 	}
1273e12c5d1SDavid du Colombier }
128dc5a79c1SDavid du Colombier 
129dc5a79c1SDavid du Colombier void
skipnl(void)130dc5a79c1SDavid du Colombier skipnl(void)
131dc5a79c1SDavid du Colombier {
132dc5a79c1SDavid du Colombier 	int c;
1333e12c5d1SDavid du Colombier 	for(;;){
1343e12c5d1SDavid du Colombier 		skipwhite();
1353e12c5d1SDavid du Colombier 		c = nextc();
136dc5a79c1SDavid du Colombier 		if(c!='\n')
137dc5a79c1SDavid du Colombier 			return;
1383e12c5d1SDavid du Colombier 		advance();
1393e12c5d1SDavid du Colombier 	}
1403e12c5d1SDavid du Colombier }
141dc5a79c1SDavid du Colombier 
142dc5a79c1SDavid du Colombier int
nextis(int c)143dc5a79c1SDavid du Colombier nextis(int c)
144dc5a79c1SDavid du Colombier {
1453e12c5d1SDavid du Colombier 	if(nextc()==c){
1463e12c5d1SDavid du Colombier 		advance();
1473e12c5d1SDavid du Colombier 		return 1;
1483e12c5d1SDavid du Colombier 	}
1493e12c5d1SDavid du Colombier 	return 0;
1503e12c5d1SDavid du Colombier }
151dc5a79c1SDavid du Colombier 
152dc5a79c1SDavid du Colombier char*
addtok(char * p,int val)153dc5a79c1SDavid du Colombier addtok(char *p, int val)
154dc5a79c1SDavid du Colombier {
155dc5a79c1SDavid du Colombier 	if(p==0)
156dc5a79c1SDavid du Colombier 		return 0;
1578cc1c73aSDavid du Colombier 	if(p >= &tok[NTOK]){
1583e12c5d1SDavid du Colombier 		*p = 0;
1593e12c5d1SDavid du Colombier 		yyerror("token buffer too short");
1603e12c5d1SDavid du Colombier 		return 0;
1613e12c5d1SDavid du Colombier 	}
1623e12c5d1SDavid du Colombier 	*p++=val;
1633e12c5d1SDavid du Colombier 	return p;
1643e12c5d1SDavid du Colombier }
165dc5a79c1SDavid du Colombier 
166dc5a79c1SDavid du Colombier char*
addutf(char * p,int c)167dc5a79c1SDavid du Colombier addutf(char *p, int c)
168dc5a79c1SDavid du Colombier {
16982726826SDavid du Colombier 	uchar b, m;
17082726826SDavid du Colombier 	int i;
17182726826SDavid du Colombier 
17282726826SDavid du Colombier 	p = addtok(p, c);	/* 1-byte UTF runes are special */
1738cc1c73aSDavid du Colombier 	if(c < Runeself)
17482726826SDavid du Colombier 		return p;
17582726826SDavid du Colombier 
17682726826SDavid du Colombier 	m = 0xc0;
17782726826SDavid du Colombier 	b = 0x80;
17882726826SDavid du Colombier 	for(i=1; i < UTFmax; i++){
17982726826SDavid du Colombier 		if((c&m) == b)
18082726826SDavid du Colombier 			break;
1813e12c5d1SDavid du Colombier 		p = addtok(p, advance());
18282726826SDavid du Colombier 		b = m;
18382726826SDavid du Colombier 		m = (m >> 1)|0x80;
1843e12c5d1SDavid du Colombier 	}
1853e12c5d1SDavid du Colombier 	return p;
1863e12c5d1SDavid du Colombier }
18782726826SDavid du Colombier 
1883e12c5d1SDavid du Colombier int lastdol;	/* was the last token read '$' or '$#' or '"'? */
1893e12c5d1SDavid du Colombier int lastword;	/* was the last token read a word or compound word terminator? */
190dc5a79c1SDavid du Colombier 
191dc5a79c1SDavid du Colombier int
yylex(void)192dc5a79c1SDavid du Colombier yylex(void)
193dc5a79c1SDavid du Colombier {
194dc5a79c1SDavid du Colombier 	int c, d = nextc();
195dc5a79c1SDavid du Colombier 	char *w = tok;
196dc5a79c1SDavid du Colombier 	struct tree *t;
1973e12c5d1SDavid du Colombier 	yylval.tree = 0;
1983e12c5d1SDavid du Colombier 	/*
1993e12c5d1SDavid du Colombier 	 * Embarassing sneakiness:  if the last token read was a quoted or unquoted
2003e12c5d1SDavid du Colombier 	 * WORD then we alter the meaning of what follows.  If the next character
2013e12c5d1SDavid du Colombier 	 * is `(', we return SUB (a subscript paren) and consume the `('.  Otherwise,
2023e12c5d1SDavid du Colombier 	 * if the next character is the first character of a simple or compound word,
2033e12c5d1SDavid du Colombier 	 * we insert a `^' before it.
2043e12c5d1SDavid du Colombier 	 */
2053e12c5d1SDavid du Colombier 	if(lastword){
2063e12c5d1SDavid du Colombier 		lastword = 0;
2073e12c5d1SDavid du Colombier 		if(d=='('){
2083e12c5d1SDavid du Colombier 			advance();
2093e12c5d1SDavid du Colombier 			strcpy(tok, "( [SUB]");
2103e12c5d1SDavid du Colombier 			return SUB;
2113e12c5d1SDavid du Colombier 		}
2123e12c5d1SDavid du Colombier 		if(wordchr(d) || d=='\'' || d=='`' || d=='$' || d=='"'){
2133e12c5d1SDavid du Colombier 			strcpy(tok, "^");
2143e12c5d1SDavid du Colombier 			return '^';
2153e12c5d1SDavid du Colombier 		}
2163e12c5d1SDavid du Colombier 	}
2173e12c5d1SDavid du Colombier 	inquote = 0;
2183e12c5d1SDavid du Colombier 	skipwhite();
2193e12c5d1SDavid du Colombier 	switch(c = advance()){
2203e12c5d1SDavid du Colombier 	case EOF:
2213e12c5d1SDavid du Colombier 		lastdol = 0;
2223e12c5d1SDavid du Colombier 		strcpy(tok, "EOF");
2233e12c5d1SDavid du Colombier 		return EOF;
2243e12c5d1SDavid du Colombier 	case '$':
2253e12c5d1SDavid du Colombier 		lastdol = 1;
2263e12c5d1SDavid du Colombier 		if(nextis('#')){
2273e12c5d1SDavid du Colombier 			strcpy(tok, "$#");
2283e12c5d1SDavid du Colombier 			return COUNT;
2293e12c5d1SDavid du Colombier 		}
2303e12c5d1SDavid du Colombier 		if(nextis('"')){
2313e12c5d1SDavid du Colombier 			strcpy(tok, "$\"");
2323e12c5d1SDavid du Colombier 			return '"';
2333e12c5d1SDavid du Colombier 		}
2343e12c5d1SDavid du Colombier 		strcpy(tok, "$");
2353e12c5d1SDavid du Colombier 		return '$';
2363e12c5d1SDavid du Colombier 	case '&':
2373e12c5d1SDavid du Colombier 		lastdol = 0;
2383e12c5d1SDavid du Colombier 		if(nextis('&')){
2393e12c5d1SDavid du Colombier 			skipnl();
2403e12c5d1SDavid du Colombier 			strcpy(tok, "&&");
2413e12c5d1SDavid du Colombier 			return ANDAND;
2423e12c5d1SDavid du Colombier 		}
2433e12c5d1SDavid du Colombier 		strcpy(tok, "&");
2443e12c5d1SDavid du Colombier 		return '&';
2453e12c5d1SDavid du Colombier 	case '|':
2463e12c5d1SDavid du Colombier 		lastdol = 0;
2473e12c5d1SDavid du Colombier 		if(nextis(c)){
2483e12c5d1SDavid du Colombier 			skipnl();
2493e12c5d1SDavid du Colombier 			strcpy(tok, "||");
2503e12c5d1SDavid du Colombier 			return OROR;
2513e12c5d1SDavid du Colombier 		}
2523e12c5d1SDavid du Colombier 	case '<':
2533e12c5d1SDavid du Colombier 	case '>':
2543e12c5d1SDavid du Colombier 		lastdol = 0;
2553e12c5d1SDavid du Colombier 		/*
2563e12c5d1SDavid du Colombier 		 * funny redirection tokens:
2573e12c5d1SDavid du Colombier 		 *	redir:	arrow | arrow '[' fd ']'
2583e12c5d1SDavid du Colombier 		 *	arrow:	'<' | '<<' | '>' | '>>' | '|'
2593e12c5d1SDavid du Colombier 		 *	fd:	digit | digit '=' | digit '=' digit
2603e12c5d1SDavid du Colombier 		 *	digit:	'0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9'
2613e12c5d1SDavid du Colombier 		 * some possibilities are nonsensical and get a message.
2623e12c5d1SDavid du Colombier 		 */
2633e12c5d1SDavid du Colombier 		*w++=c;
2643e12c5d1SDavid du Colombier 		t = newtree();
2653e12c5d1SDavid du Colombier 		switch(c){
2663e12c5d1SDavid du Colombier 		case '|':
2673e12c5d1SDavid du Colombier 			t->type = PIPE;
2683e12c5d1SDavid du Colombier 			t->fd0 = 1;
2693e12c5d1SDavid du Colombier 			t->fd1 = 0;
2703e12c5d1SDavid du Colombier 			break;
2713e12c5d1SDavid du Colombier 		case '>':
2723e12c5d1SDavid du Colombier 			t->type = REDIR;
2733e12c5d1SDavid du Colombier 			if(nextis(c)){
2743e12c5d1SDavid du Colombier 				t->rtype = APPEND;
2753e12c5d1SDavid du Colombier 				*w++=c;
2763e12c5d1SDavid du Colombier 			}
2773e12c5d1SDavid du Colombier 			else t->rtype = WRITE;
2783e12c5d1SDavid du Colombier 			t->fd0 = 1;
2793e12c5d1SDavid du Colombier 			break;
2803e12c5d1SDavid du Colombier 		case '<':
2813e12c5d1SDavid du Colombier 			t->type = REDIR;
2823e12c5d1SDavid du Colombier 			if(nextis(c)){
2833e12c5d1SDavid du Colombier 				t->rtype = HERE;
2843e12c5d1SDavid du Colombier 				*w++=c;
285119a69faSDavid du Colombier 			} else if (nextis('>')){
286119a69faSDavid du Colombier 				t->rtype = RDWR;
287119a69faSDavid du Colombier 				*w++=c;
288119a69faSDavid du Colombier 			} else t->rtype = READ;
2893e12c5d1SDavid du Colombier 			t->fd0 = 0;
2903e12c5d1SDavid du Colombier 			break;
2913e12c5d1SDavid du Colombier 		}
2923e12c5d1SDavid du Colombier 		if(nextis('[')){
2933e12c5d1SDavid du Colombier 			*w++='[';
2943e12c5d1SDavid du Colombier 			c = advance();
2953e12c5d1SDavid du Colombier 			*w++=c;
2963e12c5d1SDavid du Colombier 			if(c<'0' || '9'<c){
2973e12c5d1SDavid du Colombier 			RedirErr:
2983e12c5d1SDavid du Colombier 				*w = 0;
2993e12c5d1SDavid du Colombier 				yyerror(t->type==PIPE?"pipe syntax"
3003e12c5d1SDavid du Colombier 						:"redirection syntax");
3013e12c5d1SDavid du Colombier 				return EOF;
3023e12c5d1SDavid du Colombier 			}
3033e12c5d1SDavid du Colombier 			t->fd0 = 0;
3043e12c5d1SDavid du Colombier 			do{
3053e12c5d1SDavid du Colombier 				t->fd0 = t->fd0*10+c-'0';
3063e12c5d1SDavid du Colombier 				*w++=c;
3073e12c5d1SDavid du Colombier 				c = advance();
3083e12c5d1SDavid du Colombier 			}while('0'<=c && c<='9');
3093e12c5d1SDavid du Colombier 			if(c=='='){
3103e12c5d1SDavid du Colombier 				*w++='=';
311dc5a79c1SDavid du Colombier 				if(t->type==REDIR)
312dc5a79c1SDavid du Colombier 					t->type = DUP;
3133e12c5d1SDavid du Colombier 				c = advance();
3143e12c5d1SDavid du Colombier 				if('0'<=c && c<='9'){
3153e12c5d1SDavid du Colombier 					t->rtype = DUPFD;
3163e12c5d1SDavid du Colombier 					t->fd1 = t->fd0;
3173e12c5d1SDavid du Colombier 					t->fd0 = 0;
3183e12c5d1SDavid du Colombier 					do{
3193e12c5d1SDavid du Colombier 						t->fd0 = t->fd0*10+c-'0';
3203e12c5d1SDavid du Colombier 						*w++=c;
3213e12c5d1SDavid du Colombier 						c = advance();
3223e12c5d1SDavid du Colombier 					}while('0'<=c && c<='9');
3233e12c5d1SDavid du Colombier 				}
3243e12c5d1SDavid du Colombier 				else{
325dc5a79c1SDavid du Colombier 					if(t->type==PIPE)
326dc5a79c1SDavid du Colombier 						goto RedirErr;
3273e12c5d1SDavid du Colombier 					t->rtype = CLOSE;
3283e12c5d1SDavid du Colombier 				}
3293e12c5d1SDavid du Colombier 			}
3303e12c5d1SDavid du Colombier 			if(c!=']'
3313e12c5d1SDavid du Colombier 			|| t->type==DUP && (t->rtype==HERE || t->rtype==APPEND))
3323e12c5d1SDavid du Colombier 				goto RedirErr;
3333e12c5d1SDavid du Colombier 			*w++=']';
3343e12c5d1SDavid du Colombier 		}
3353e12c5d1SDavid du Colombier 		*w='\0';
3363e12c5d1SDavid du Colombier 		yylval.tree = t;
337dc5a79c1SDavid du Colombier 		if(t->type==PIPE)
338dc5a79c1SDavid du Colombier 			skipnl();
3393e12c5d1SDavid du Colombier 		return t->type;
3403e12c5d1SDavid du Colombier 	case '\'':
3413e12c5d1SDavid du Colombier 		lastdol = 0;
3423e12c5d1SDavid du Colombier 		lastword = 1;
3433e12c5d1SDavid du Colombier 		inquote = 1;
3443e12c5d1SDavid du Colombier 		for(;;){
3453e12c5d1SDavid du Colombier 			c = advance();
346dc5a79c1SDavid du Colombier 			if(c==EOF)
347dc5a79c1SDavid du Colombier 				break;
3483e12c5d1SDavid du Colombier 			if(c=='\''){
3493e12c5d1SDavid du Colombier 				if(nextc()!='\'')
3503e12c5d1SDavid du Colombier 					break;
3513e12c5d1SDavid du Colombier 				advance();
3523e12c5d1SDavid du Colombier 			}
3533e12c5d1SDavid du Colombier 			w = addutf(w, c);
3543e12c5d1SDavid du Colombier 		}
355dc5a79c1SDavid du Colombier 		if(w!=0)
356dc5a79c1SDavid du Colombier 			*w='\0';
3573e12c5d1SDavid du Colombier 		t = token(tok, WORD);
3583e12c5d1SDavid du Colombier 		t->quoted = 1;
3593e12c5d1SDavid du Colombier 		yylval.tree = t;
3603e12c5d1SDavid du Colombier 		return t->type;
3613e12c5d1SDavid du Colombier 	}
3623e12c5d1SDavid du Colombier 	if(!wordchr(c)){
3633e12c5d1SDavid du Colombier 		lastdol = 0;
3643e12c5d1SDavid du Colombier 		tok[0] = c;
3653e12c5d1SDavid du Colombier 		tok[1]='\0';
3663e12c5d1SDavid du Colombier 		return c;
3673e12c5d1SDavid du Colombier 	}
3683e12c5d1SDavid du Colombier 	for(;;){
369*4e3613abSDavid du Colombier 		if(c=='*' || c=='[' || c=='?' || c==GLOB)
3703e12c5d1SDavid du Colombier 			w = addtok(w, GLOB);
3713e12c5d1SDavid du Colombier 		w = addutf(w, c);
3723e12c5d1SDavid du Colombier 		c = nextc();
3733e12c5d1SDavid du Colombier 		if(lastdol?!idchr(c):!wordchr(c)) break;
3743e12c5d1SDavid du Colombier 		advance();
3753e12c5d1SDavid du Colombier 	}
3767dd7cddfSDavid du Colombier 
3773e12c5d1SDavid du Colombier 	lastword = 1;
3783e12c5d1SDavid du Colombier 	lastdol = 0;
379dc5a79c1SDavid du Colombier 	if(w!=0)
380dc5a79c1SDavid du Colombier 		*w='\0';
3813e12c5d1SDavid du Colombier 	t = klook(tok);
382dc5a79c1SDavid du Colombier 	if(t->type!=WORD)
383dc5a79c1SDavid du Colombier 		lastword = 0;
3843e12c5d1SDavid du Colombier 	t->quoted = 0;
3853e12c5d1SDavid du Colombier 	yylval.tree = t;
3863e12c5d1SDavid du Colombier 	return t->type;
3873e12c5d1SDavid du Colombier }
388