1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1982-2012 AT&T Intellectual Property          *
5 *                      and is licensed under the                       *
6 *                 Eclipse Public License, Version 1.0                  *
7 *                    by AT&T Intellectual Property                     *
8 *                                                                      *
9 *                A copy of the License is available at                 *
10 *          http://www.eclipse.org/org/documents/epl-v10.html           *
11 *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12 *                                                                      *
13 *              Information and Software Systems Research               *
14 *                            AT&T Research                             *
15 *                           Florham Park NJ                            *
16 *                                                                      *
17 *                  David Korn <dgk@research.att.com>                   *
18 *                                                                      *
19 ***********************************************************************/
20 #pragma prototyped
21 /*
22  * UNIX shell
23  *
24  * S. R. Bourne
25  * Rewritten by David Korn
26  * AT&T Labs
27  *
28  *  This is the parser for a shell language
29  */
30 
31 #if KSHELL
32 #include	"defs.h"
33 #else
34 #include	<shell.h>
35 #include	<ctype.h>
36 #endif
37 #include	<fcin.h>
38 #include	<error.h>
39 #include	"shlex.h"
40 #include	"history.h"
41 #include	"builtins.h"
42 #include	"test.h"
43 #include	"history.h"
44 
45 #define HERE_MEM	SF_BUFSIZE	/* size of here-docs kept in memory */
46 
47 #if CDT_VERSION < 20111111L
48 #define hash	nvlink.hl._hash
49 #else
50 #define hash	nvlink.lh.__hash
51 #endif
52 
53 /* These routines are local to this module */
54 
55 static Shnode_t	*makeparent(Lex_t*, int, Shnode_t*);
56 static Shnode_t	*makelist(Lex_t*, int, Shnode_t*, Shnode_t*);
57 static struct argnod	*qscan(struct comnod*, int);
58 static struct ionod	*inout(Lex_t*,struct ionod*, int);
59 static Shnode_t	*sh_cmd(Lex_t*,int,int);
60 static Shnode_t	*term(Lex_t*,int);
61 static Shnode_t	*list(Lex_t*,int);
62 static struct regnod	*syncase(Lex_t*,int);
63 static Shnode_t	*item(Lex_t*,int);
64 static Shnode_t	*simple(Lex_t*,int, struct ionod*);
65 static int	skipnl(Lex_t*,int);
66 static Shnode_t	*test_expr(Lex_t*,int);
67 static Shnode_t	*test_and(Lex_t*);
68 static Shnode_t	*test_or(Lex_t*);
69 static Shnode_t	*test_primary(Lex_t*);
70 
71 #define	sh_getlineno(lp)	(lp->lastline)
72 
73 #ifndef NIL
74 #   define NIL(type)	((type)0)
75 #endif /* NIL */
76 #define CNTL(x)		((x)&037)
77 
78 
79 #if !KSHELL
80 static struct stdata
81 {
82 	struct slnod    *staklist;
83 	int	cmdline;
84 } st;
85 #endif
86 
87 static int		opt_get;
88 static int		loop_level;
89 static struct argnod	*label_list;
90 static struct argnod	*label_last;
91 
92 #define getnode(type)	((Shnode_t*)stakalloc(sizeof(struct type)))
93 
94 #if SHOPT_KIA
95 #include	"path.h"
96 /*
97  * write out entities for each item in the list
98  * type=='V' for variable assignment lists
99  * Otherwise type is determined by the command */
100 static unsigned long writedefs(Lex_t *lexp,struct argnod *arglist, int line, int type, struct argnod *cmd)
101 {
102 	register struct argnod *argp = arglist;
103 	register char *cp;
104 	register int n,eline;
105 	int width=0;
106 	unsigned long r=0;
107 	static char atbuff[20];
108 	int  justify=0;
109 	char *attribute = atbuff;
110 	unsigned long parent=lexp->script;
111 	if(type==0)
112 	{
113 		parent = lexp->current;
114 		type = 'v';
115 		switch(*argp->argval)
116 		{
117 		    case 'a':
118 			type='p';
119 			justify = 'a';
120 			break;
121 		    case 'e':
122 			*attribute++ =  'x';
123 			break;
124 		    case 'r':
125 			*attribute++ = 'r';
126 			break;
127 		    case 'l':
128 			break;
129 		}
130 		while(argp = argp->argnxt.ap)
131 		{
132 			if((n= *(cp=argp->argval))!='-' && n!='+')
133 				break;
134 			if(cp[1]==n)
135 				break;
136 			while((n= *++cp))
137 			{
138 				if(isdigit(n))
139 					width = 10*width + n-'0';
140 				else if(n=='L' || n=='R' || n =='Z')
141 					justify=n;
142 				else
143 					*attribute++ = n;
144 			}
145 		}
146 	}
147 	else if(cmd)
148 		parent=kiaentity(lexp,sh_argstr(cmd),-1,'p',-1,-1,lexp->unknown,'b',0,"");
149 	*attribute = 0;
150 	while(argp)
151 	{
152 		if((cp=strchr(argp->argval,'='))||(cp=strchr(argp->argval,'?')))
153 			n = cp-argp->argval;
154 		else
155 			n = strlen(argp->argval);
156 		eline = lexp->sh->inlineno-(lexp->token==NL);
157 		r=kiaentity(lexp,argp->argval,n,type,line,eline,parent,justify,width,atbuff);
158 		sfprintf(lexp->kiatmp,"p;%..64d;v;%..64d;%d;%d;s;\n",lexp->current,r,line,eline);
159 		argp = argp->argnxt.ap;
160 	}
161 	return(r);
162 }
163 #endif /* SHOPT_KIA */
164 
165 static void typeset_order(const char *str,int line)
166 {
167 	register int		c,n=0;
168 	unsigned const char	*cp=(unsigned char*)str;
169 	static unsigned char	*table;
170 	if(*cp!='+' && *cp!='-')
171 		return;
172 	if(!table)
173 	{
174 		table = calloc(1,256);
175 		for(cp=(unsigned char*)"bflmnprstuxACHS";c = *cp; cp++)
176 			table[c] = 1;
177 		for(cp=(unsigned char*)"aiEFLRXhTZ";c = *cp; cp++)
178 			table[c] = 2;
179 		for(c='0'; c <='9'; c++)
180 			table[c] = 3;
181 	}
182 	for(cp=(unsigned char*)str; c= *cp++; n=table[c])
183 	{
184 		if(table[c] < n)
185 			errormsg(SH_DICT,ERROR_warn(0),e_lextypeset,line,str);
186 	}
187 }
188 
189 /*
190  * add type definitions when compiling with -n
191  */
192 static void check_typedef(struct comnod *tp)
193 {
194 	char	*cp=0;
195 	if(tp->comtyp&COMSCAN)
196 	{
197 		struct argnod *ap = tp->comarg;
198 		while(ap = ap->argnxt.ap)
199 		{
200 			if(!(ap->argflag&ARG_RAW) || memcmp(ap->argval,"--",2))
201 				break;
202 			if(sh_isoption(SH_NOEXEC))
203 				typeset_order(ap->argval,tp->comline);
204 			if(memcmp(ap->argval,"-T",2)==0)
205 			{
206 				if(ap->argval[2])
207 					cp = ap->argval+2;
208 				else if((ap->argnxt.ap)->argflag&ARG_RAW)
209 					cp = (ap->argnxt.ap)->argval;
210 				if(cp)
211 					break;
212 			}
213 		}
214 	}
215 	else
216 	{
217 		struct dolnod *dp = (struct dolnod*)tp->comarg;
218 		char **argv = dp->dolval + dp->dolbot+1;
219 		while((cp= *argv++) && memcmp(cp,"--",2))
220 		{
221 			if(sh_isoption(SH_NOEXEC))
222 				typeset_order(cp,tp->comline);
223 			if(memcmp(cp,"-T",2)==0)
224 			{
225 				if(cp[2])
226 					cp = cp+2;
227 				else
228 					cp = *argv;
229 				break;
230 			}
231 		}
232 	}
233 	if(cp)
234 	{
235 		Namval_t	*mp=(Namval_t*)tp->comnamp ,*bp;
236 		bp = sh_addbuiltin(cp, (Shbltin_f)mp->nvalue.bfp, (void*)0);
237 		nv_onattr(bp,nv_isattr(mp,NV_PUBLIC));
238 	}
239 }
240 
241 /*
242  * Make a parent node for fork() or io-redirection
243  */
244 static Shnode_t	*makeparent(Lex_t *lp, int flag, Shnode_t *child)
245 {
246 	register Shnode_t	*par = getnode(forknod);
247 	par->fork.forktyp = flag;
248 	par->fork.forktre = child;
249 	par->fork.forkio = 0;
250 	par->fork.forkline = sh_getlineno(lp)-1;
251 	return(par);
252 }
253 
254 static int paramsub(const char *str)
255 {
256 	register int c,sub=0,lit=0;
257 	while(c= *str++)
258 	{
259 		if(c=='$' && !lit)
260 		{
261 			if(*str=='(')
262 				return(0);
263 			if(sub)
264 				continue;
265 			if(*str=='{')
266 				str++;
267 			if(!isdigit(*str) && strchr("?#@*!$ ",*str)==0)
268 				return(1);
269 		}
270 		else if(c=='`')
271 			return(0);
272 		else if(c=='[' && !lit)
273 			sub++;
274 		else if(c==']' && !lit)
275 			sub--;
276 		else if(c=='\'')
277 			lit = !lit;
278 	}
279 	return(0);
280 }
281 
282 static Shnode_t *getanode(Lex_t *lp, struct argnod *ap)
283 {
284 	register Shnode_t *t = getnode(arithnod);
285 	t->ar.artyp = TARITH;
286 	t->ar.arline = sh_getlineno(lp);
287 	t->ar.arexpr = ap;
288 	if(ap->argflag&ARG_RAW)
289 		t->ar.arcomp = sh_arithcomp(lp->sh,ap->argval);
290 	else
291 	{
292 		if(sh_isoption(SH_NOEXEC) && (ap->argflag&ARG_MAC) && paramsub(ap->argval))
293 			errormsg(SH_DICT,ERROR_warn(0),e_lexwarnvar,lp->sh->inlineno);
294 		t->ar.arcomp = 0;
295 	}
296 	return(t);
297 }
298 
299 /*
300  *  Make a node corresponding to a command list
301  */
302 static Shnode_t	*makelist(Lex_t *lexp, int type, Shnode_t *l, Shnode_t *r)
303 {
304 	register Shnode_t	*t;
305 	if(!l || !r)
306 		sh_syntax(lexp);
307 	else
308 	{
309 		if((type&COMMSK) == TTST)
310 			t = getnode(tstnod);
311 		else
312 			t = getnode(lstnod);
313 		t->lst.lsttyp = type;
314 		t->lst.lstlef = l;
315 		t->lst.lstrit = r;
316 	}
317 	return(t);
318 }
319 
320 /*
321  * entry to shell parser
322  * Flag can be the union of SH_EOF|SH_NL
323  */
324 
325 void	*sh_parse(Shell_t *shp, Sfio_t *iop, int flag)
326 {
327 	register Shnode_t	*t;
328 	Lex_t			*lexp = (Lex_t*)shp->lex_context;
329 	Fcin_t	sav_input;
330 	struct argnod *sav_arg = lexp->arg;
331 	int	sav_prompt = shp->nextprompt;
332 	if(shp->binscript && (sffileno(iop)==shp->infd || (flag&SH_FUNEVAL)))
333 		return((void*)sh_trestore(shp,iop));
334 	fcsave(&sav_input);
335 	shp->st.staklist = 0;
336 	lexp->noreserv = 0;
337 	lexp->heredoc = 0;
338 	lexp->inlineno = shp->inlineno;
339 	lexp->firstline = shp->st.firstline;
340 	shp->nextprompt = 1;
341 	loop_level = 0;
342 	label_list = label_last = 0;
343 	if(sh_isoption(SH_INTERACTIVE))
344 		sh_onstate(SH_INTERACTIVE);
345 	if(sh_isoption(SH_VERBOSE))
346 		sh_onstate(SH_VERBOSE);
347 	sh_lexopen(lexp,shp,0);
348 	if(fcfopen(iop) < 0)
349 		return(NIL(void*));
350 	if(fcfile())
351 	{
352 		char *cp = fcfirst();
353 		if( cp[0]==CNTL('k') &&  cp[1]==CNTL('s') && cp[2]==CNTL('h') && cp[3]==0)
354 		{
355 			int version;
356 			fcseek(4);
357 			fcgetc(version);
358 			fcclose();
359 			fcrestore(&sav_input);
360 			lexp->arg = sav_arg;
361 			if(version > 3)
362 				errormsg(SH_DICT,ERROR_exit(1),e_lexversion);
363 			if(sffileno(iop)==shp->infd || (flag&SH_FUNEVAL))
364 				shp->binscript = 1;
365 			sfgetc(iop);
366 			t = sh_trestore(shp,iop);
367 			if(flag&SH_NL)
368 			{
369 				Shnode_t *tt;
370 				while(1)
371 				{
372 					if(!(tt = sh_trestore(shp,iop)))
373 						break;
374 					t =makelist(lexp,TLST, t, tt);
375 				}
376 			}
377 			return((void*)t);
378 		}
379 	}
380 	flag &= ~SH_FUNEVAL;
381 	if((flag&SH_NL) && (shp->inlineno=error_info.line+shp->st.firstline)==0)
382 		shp->inlineno=1;
383 #if KSHELL
384 	shp->nextprompt = 2;
385 #endif
386 	t = sh_cmd(lexp,(flag&SH_EOF)?EOFSYM:'\n',SH_SEMI|SH_EMPTY|(flag&SH_NL));
387 	fcclose();
388 	fcrestore(&sav_input);
389 	lexp->arg = sav_arg;
390 	/* unstack any completed alias expansions */
391 	if((sfset(iop,0,0)&SF_STRING) && !sfreserve(iop,0,-1))
392 	{
393 		Sfio_t *sp = sfstack(iop,NULL);
394 		if(sp)
395 			sfclose(sp);
396 	}
397 	shp->nextprompt = sav_prompt;
398 	if(flag&SH_NL)
399 	{
400 		shp->st.firstline = lexp->firstline;
401 		shp->inlineno = lexp->inlineno;
402 	}
403 	stkseek(shp->stk,0);
404 	return((void*)t);
405 }
406 
407 /*
408  * This routine parses up the matching right parenthesis and returns
409  * the parse tree
410  */
411 Shnode_t *sh_dolparen(Lex_t* lp)
412 {
413 	register Shnode_t *t=0;
414 	Sfio_t *sp = fcfile();
415 	int line = lp->sh->inlineno;
416 	lp->sh->inlineno = error_info.line+lp->sh->st.firstline;
417 	sh_lexopen(lp,lp->sh,1);
418 	lp->comsub = 1;
419 	switch(sh_lex(lp))
420 	{
421 	    /* ((...)) arithmetic expression */
422 	    case EXPRSYM:
423 		t = getanode(lp,lp->arg);
424 		break;
425 	    case LPAREN:
426 		t = sh_cmd(lp,RPAREN,SH_NL|SH_EMPTY);
427 		break;
428 	    case LBRACE:
429 		t = sh_cmd(lp,RBRACE,SH_NL|SH_EMPTY);
430 		break;
431 	}
432 	lp->comsub = 0;
433 	if(!sp && (sp=fcfile()))
434 	{
435 		/*
436 		 * This code handles the case where string has been converted
437 		 * to a file by an alias setup
438 		 */
439 		register int c;
440 		char *cp;
441 		if(fcgetc(c) > 0)
442 			fcseek(-1);
443 		cp = fcseek(0);
444 		fcclose();
445 		fcsopen(cp);
446 		sfclose(sp);
447 	}
448 	lp->sh->inlineno = line;
449 	return(t);
450 }
451 
452 /*
453  * remove temporary files and stacks
454  */
455 
456 void	sh_freeup(Shell_t *shp)
457 {
458 	if(shp->st.staklist)
459 		sh_funstaks(shp->st.staklist,-1);
460 	shp->st.staklist = 0;
461 }
462 
463 /*
464  * increase reference count for each stack in function list when flag>0
465  * decrease reference count for each stack in function list when flag<=0
466  * stack is freed when reference count is zero
467  */
468 
469 void sh_funstaks(register struct slnod *slp,int flag)
470 {
471 	register struct slnod *slpold;
472 	while(slpold=slp)
473 	{
474 		if(slp->slchild)
475 			sh_funstaks(slp->slchild,flag);
476 		slp = slp->slnext;
477 		if(flag<=0)
478 			stakdelete(slpold->slptr);
479 		else
480 			staklink(slpold->slptr);
481 	}
482 }
483 /*
484  * cmd
485  *	empty
486  *	list
487  *	list & [ cmd ]
488  *	list [ ; cmd ]
489  */
490 
491 static Shnode_t	*sh_cmd(Lex_t *lexp, register int sym, int flag)
492 {
493 	register Shnode_t	*left, *right;
494 	register int type = FINT|FAMP;
495 	if(sym==NL)
496 		lexp->lasttok = 0;
497 	left = list(lexp,flag);
498 	if(lexp->token==NL)
499 	{
500 		if(flag&SH_NL)
501 			lexp->token=';';
502 	}
503 	else if(!left && !(flag&SH_EMPTY))
504 		sh_syntax(lexp);
505 	switch(lexp->token)
506 	{
507 	    case COOPSYM:		/* set up a cooperating process */
508 		type |= (FPIN|FPOU|FPCL|FCOOP);
509 		/* FALLTHROUGH */
510 	    case '&':
511 		if(left)
512 		{
513 			/* (...)& -> {...;} & */
514 			if(left->tre.tretyp==TPAR)
515 				left = left->par.partre;
516 			left = makeparent(lexp,TFORK|type, left);
517 		}
518 		/* FALLTHROUGH */
519 	    case ';':
520 		if(!left)
521 			sh_syntax(lexp);
522 		if(right=sh_cmd(lexp,sym,flag|SH_EMPTY))
523 			left=makelist(lexp,TLST, left, right);
524 		break;
525 	    case EOFSYM:
526 		if(sym==NL)
527 			break;
528 		/* FALLTHROUGH */
529 	    default:
530 		if(sym && sym!=lexp->token)
531 		{
532 			if(sym!=ELSESYM || (lexp->token!=ELIFSYM && lexp->token!=FISYM))
533 				sh_syntax(lexp);
534 		}
535 	}
536 	return(left);
537 }
538 
539 /*
540  * list
541  *	term
542  *	list && term
543  *	list || term
544  *      unfortunately, these are equal precedence
545  */
546 static Shnode_t	*list(Lex_t *lexp, register int flag)
547 {
548 	register Shnode_t	*t = term(lexp,flag);
549 	register int 	token;
550 	while(t && ((token=lexp->token)==ANDFSYM || token==ORFSYM))
551 		t = makelist(lexp,(token==ANDFSYM?TAND:TORF), t, term(lexp,SH_NL|SH_SEMI));
552 	return(t);
553 }
554 
555 /*
556  * term
557  *	item
558  *	item | term
559  */
560 static Shnode_t	*term(Lex_t *lexp,register int flag)
561 {
562 	register Shnode_t	*t;
563 	register int token;
564 	if(flag&SH_NL)
565 		token = skipnl(lexp,flag);
566 	else
567 		token = sh_lex(lexp);
568 	/* check to see if pipeline is to be timed */
569 	if(token==TIMESYM || token==NOTSYM)
570 	{
571 		t = getnode(parnod);
572 		t->par.partyp=TTIME;
573 		if(lexp->token==NOTSYM)
574 			t->par.partyp |= COMSCAN;
575 		t->par.partre = term(lexp,0);
576 	}
577 #if SHOPT_COSHELL
578 	else if((t=item(lexp,SH_NL|SH_EMPTY|(flag&SH_SEMI))) && (lexp->token=='|' || lexp->token==PIPESYM2))
579 #else
580 	else if((t=item(lexp,SH_NL|SH_EMPTY|(flag&SH_SEMI))) && lexp->token=='|')
581 #endif /* SHOPT_COSHELL */
582 	{
583 		register Shnode_t	*tt;
584 		int showme = t->tre.tretyp&FSHOWME;
585 		t = makeparent(lexp,TFORK|FPOU,t);
586 #if SHOPT_COSHELL
587 		if(lexp->token==PIPESYM2)
588 			t->tre.tretyp |= FALTPIPE;
589 #endif /* SHOPT_COSHELL */
590 		if(tt=term(lexp,SH_NL))
591 		{
592 			switch(tt->tre.tretyp&COMMSK)
593 			{
594 			    case TFORK:
595 				tt->tre.tretyp |= FPIN|FPCL;
596 				break;
597 			    case TFIL:
598 				tt->lst.lstlef->tre.tretyp |= FPIN|FPCL;
599 				break;
600 			    default:
601 				tt= makeparent(lexp,TSETIO|FPIN|FPCL,tt);
602 			}
603 			t=makelist(lexp,TFIL,t,tt);
604 			t->tre.tretyp |= showme;
605 		}
606 		else if(lexp->token)
607 			sh_syntax(lexp);
608 	}
609 	return(t);
610 }
611 
612 /*
613  * case statement
614  */
615 static struct regnod*	syncase(Lex_t *lexp,register int esym)
616 {
617 	register int tok = skipnl(lexp,0);
618 	register struct regnod	*r;
619 	if(tok==esym)
620 		return(NIL(struct regnod*));
621 	r = (struct regnod*)stakalloc(sizeof(struct regnod));
622 	r->regptr=0;
623 	r->regflag=0;
624 	if(tok==LPAREN)
625 		skipnl(lexp,0);
626 	while(1)
627 	{
628 		if(!lexp->arg)
629 			sh_syntax(lexp);
630 		lexp->arg->argnxt.ap=r->regptr;
631 		r->regptr = lexp->arg;
632 		if((tok=sh_lex(lexp))==RPAREN)
633 			break;
634 		else if(tok=='|')
635 			sh_lex(lexp);
636 		else
637 			sh_syntax(lexp);
638 	}
639 	r->regcom=sh_cmd(lexp,0,SH_NL|SH_EMPTY|SH_SEMI);
640 	if((tok=lexp->token)==BREAKCASESYM)
641 		r->regnxt=syncase(lexp,esym);
642 	else if(tok==FALLTHRUSYM)
643 	{
644 		r->regflag++;
645 		r->regnxt=syncase(lexp,esym);
646 	}
647 	else
648 	{
649 		if(tok!=esym && tok!=EOFSYM)
650 			sh_syntax(lexp);
651 		r->regnxt=0;
652 	}
653 	if(lexp->token==EOFSYM)
654 		return(NIL(struct regnod*));
655 	return(r);
656 }
657 
658 /*
659  * This routine creates the parse tree for the arithmetic for
660  * When called, shlex.arg contains the string inside ((...))
661  * When the first argument is missing, a while node is returned
662  * Otherise a list containing an arithmetic command and a while
663  * is returned.
664  */
665 static Shnode_t	*arithfor(Lex_t *lexp,register Shnode_t *tf)
666 {
667 	register Shnode_t	*t, *tw = tf;
668 	register int	offset;
669 	register struct argnod *argp;
670 	register int n;
671 	Stk_t		*stkp = lexp->sh->stk;
672 	int argflag = lexp->arg->argflag;
673 	/* save current input */
674 	Fcin_t	sav_input;
675 	fcsave(&sav_input);
676 	fcsopen(lexp->arg->argval);
677 	/* split ((...)) into three expressions */
678 	for(n=0; ; n++)
679 	{
680 		register int c;
681 		argp = (struct argnod*)stkseek(stkp,ARGVAL);
682 		argp->argnxt.ap = 0;
683 		argp->argchn.cp = 0;
684 		argp->argflag = argflag;
685 		if(n==2)
686 			break;
687 		/* copy up to ; onto the stack */
688 		sh_lexskip(lexp,';',1,ST_NESTED);
689 		offset = stktell(stkp)-1;
690 		if((c=fcpeek(-1))!=';')
691 			break;
692 		/* remove trailing white space */
693 		while(offset>ARGVAL && ((c= *stkptr(stkp,offset-1)),isspace(c)))
694 			offset--;
695 		/* check for empty initialization expression  */
696 		if(offset==ARGVAL && n==0)
697 			continue;
698 		stkseek(stkp,offset);
699 		/* check for empty condition and treat as while((1)) */
700 		if(offset==ARGVAL)
701 			sfputc(stkp,'1');
702 		argp = (struct argnod*)stkfreeze(stkp,1);
703 		t = getanode(lexp,argp);
704 		if(n==0)
705 			tf = makelist(lexp,TLST,t,tw);
706 		else
707 			tw->wh.whtre = t;
708 	}
709 	while((offset=fcpeek(0)) && isspace(offset))
710 		fcseek(1);
711 	stakputs(fcseek(0));
712 	argp = (struct argnod*)stakfreeze(1);
713 	fcrestore(&sav_input);
714 	if(n<2)
715 	{
716 		lexp->token = RPAREN|SYMREP;
717 		sh_syntax(lexp);
718 	}
719 	/* check whether the increment is present */
720 	if(*argp->argval)
721 	{
722 		t = getanode(lexp,argp);
723 		tw->wh.whinc = (struct arithnod*)t;
724 	}
725 	else
726 		tw->wh.whinc = 0;
727 	sh_lexopen(lexp, lexp->sh,1);
728 	if((n=sh_lex(lexp))==NL)
729 		n = skipnl(lexp,0);
730 	else if(n==';')
731 		n = sh_lex(lexp);
732 	if(n!=DOSYM && n!=LBRACE)
733 		sh_syntax(lexp);
734 	tw->wh.dotre = sh_cmd(lexp,n==DOSYM?DONESYM:RBRACE,SH_NL|SH_SEMI);
735 	tw->wh.whtyp = TWH;
736 	return(tf);
737 
738 }
739 
740 static Shnode_t *funct(Lex_t *lexp)
741 {
742 	Shell_t	*shp = lexp->sh;
743 	register Shnode_t *t;
744 	register int flag;
745 	struct slnod *volatile slp=0;
746 	Stak_t *savstak = NULL;
747 	Sfoff_t	first, last;
748 	struct functnod *volatile fp;
749 	Sfio_t *iop;
750 #if SHOPT_KIA
751 	unsigned long current = lexp->current;
752 #endif /* SHOPT_KIA */
753 	int nargs=0,size=0,jmpval, saveloop=loop_level;
754 	struct argnod *savelabel = label_last;
755 	struct  checkpt buff;
756 	int save_optget = opt_get;
757 	void	*in_mktype = shp->mktype;
758 	shp->mktype = 0;
759 	opt_get = 0;
760 	t = getnode(functnod);
761 	t->funct.functline = shp->inlineno;
762 	t->funct.functtyp=TFUN;
763 	t->funct.functargs = 0;
764 	if(!(flag = (lexp->token==FUNCTSYM)))
765 		t->funct.functtyp |= FPOSIX;
766 	else if(sh_lex(lexp))
767 		sh_syntax(lexp);
768 	if(!(iop=fcfile()))
769 	{
770 		iop = sfopen(NIL(Sfio_t*),fcseek(0),"s");
771 		fcclose();
772 		fcfopen(iop);
773 	}
774 	t->funct.functloc = first = fctell();
775 	if(!shp->st.filename || sffileno(iop)<0)
776 	{
777 		if(fcfill() >= 0)
778 			fcseek(-1);
779 		if(sh_isstate(SH_HISTORY) && shp->gd->hist_ptr)
780 			t->funct.functloc = sfseek(shp->gd->hist_ptr->histfp,(off_t)0,SEEK_CUR);
781 		else
782 		{
783 			/* copy source to temporary file */
784 			t->funct.functloc = 0;
785 			if(lexp->sh->heredocs)
786 				t->funct.functloc = sfseek(lexp->sh->heredocs,(Sfoff_t)0, SEEK_END);
787 			else
788 				lexp->sh->heredocs = sftmp(HERE_MEM);
789 			lexp->sh->funlog = lexp->sh->heredocs;
790 			t->funct.functtyp |= FPIN;
791 		}
792 	}
793 	t->funct.functnam= (char*)lexp->arg->argval;
794 #if SHOPT_KIA
795 	if(lexp->kiafile)
796 		lexp->current = kiaentity(lexp,t->funct.functnam,-1,'p',-1,-1,lexp->script,'p',0,"");
797 #endif /* SHOPT_KIA */
798 	if(flag)
799 	{
800 		lexp->token = sh_lex(lexp);
801 #if SHOPT_BASH
802 		if(lexp->token == LPAREN)
803 		{
804 			if((lexp->token = sh_lex(lexp)) == RPAREN)
805 				t->funct.functtyp |= FPOSIX;
806 			else
807 				sh_syntax(lexp);
808 		}
809 #endif
810 	}
811 	if(t->funct.functtyp&FPOSIX)
812 		skipnl(lexp,0);
813 	else
814 	{
815 		if(lexp->token==0)
816 		{
817 			struct comnod	*ac;
818 			char		*cp, **argv, **argv0;
819 			int		c;
820 			t->funct.functargs = ac = (struct comnod*)simple(lexp,SH_NOIO|SH_FUNDEF,NIL(struct ionod*));
821 			if(ac->comset || (ac->comtyp&COMSCAN))
822 				errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax4,lexp->sh->inlineno);
823 			argv0 = argv = ((struct dolnod*)ac->comarg)->dolval+ARG_SPARE;
824 			while(cp= *argv++)
825 			{
826 				size += strlen(cp)+1;
827 				if((c = mbchar(cp)) && isaletter(c))
828 		                        while(c=mbchar(cp), isaname(c));
829 			}
830 			if(c)
831 				errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax4,lexp->sh->inlineno);
832 			nargs = argv-argv0;
833 			size += sizeof(struct dolnod)+(nargs+ARG_SPARE)*sizeof(char*);
834 			if(shp->shcomp && memcmp(".sh.math.",t->funct.functnam,9)==0)
835 			{
836 				Namval_t *np= nv_open(t->funct.functnam,shp->fun_tree,NV_ADD|NV_VARNAME);
837 				np->nvalue.rp = new_of(struct Ufunction,shp->funload?sizeof(Dtlink_t):0);
838 				memset((void*)np->nvalue.rp,0,sizeof(struct Ufunction));
839 				np->nvalue.rp->argc = ((struct dolnod*)ac->comarg)->dolnum;
840 			}
841 		}
842 		while(lexp->token==NL)
843 			lexp->token = sh_lex(lexp);
844 	}
845 	if((flag && lexp->token!=LBRACE) || lexp->token==EOFSYM)
846 		sh_syntax(lexp);
847 	sh_pushcontext(shp,&buff,1);
848 	jmpval = sigsetjmp(buff.buff,0);
849 	if(jmpval == 0)
850 	{
851 		/* create a new stak frame to compile the command */
852 		savstak = stakcreate(STAK_SMALL);
853 		savstak = stakinstall(savstak, 0);
854 		slp = (struct slnod*)stakalloc(sizeof(struct slnod)+sizeof(struct functnod));
855 		slp->slchild = 0;
856 		slp->slnext = shp->st.staklist;
857 		shp->st.staklist = 0;
858 		t->funct.functstak = (struct slnod*)slp;
859 		/*
860 		 * store the pathname of function definition file on stack
861 		 * in name field of fake for node
862 		 */
863 		fp = (struct functnod*)(slp+1);
864 		fp->functtyp = TFUN|FAMP;
865 		fp->functnam = 0;
866 		fp->functargs = 0;
867 		fp->functline = t->funct.functline;
868 		if(shp->st.filename)
869 			fp->functnam = stakcopy(shp->st.filename);
870 		loop_level = 0;
871 		label_last = label_list;
872 		if(size)
873 		{
874 			struct dolnod *dp = (struct dolnod*)stakalloc(size);
875 			char *cp, *sp, **argv, **old = ((struct dolnod*)t->funct.functargs->comarg)->dolval+1;
876 			argv = ((char**)(dp->dolval))+1;
877 			dp->dolnum = ((struct dolnod*)t->funct.functargs->comarg)->dolnum;
878 			t->funct.functargs->comarg = (struct argnod*)dp;
879 			for(cp=(char*)&argv[nargs]; sp= *old++; cp++)
880 			{
881 				*argv++ = cp;
882 				cp = strcopy(cp,sp);
883 			}
884 			*argv = 0;
885 		}
886 		if(!flag && lexp->token==0)
887 		{
888 			/* copy current word token to current stak frame */
889 			struct argnod *ap;
890 			flag = ARGVAL + strlen(lexp->arg->argval);
891 			ap = (struct argnod*)stakalloc(flag);
892 			memcpy(ap,lexp->arg,flag);
893 			lexp->arg = ap;
894 		}
895 		t->funct.functtre = item(lexp,SH_NOIO);
896 	}
897 	else if(shp->shcomp)
898 		exit(1);
899 	sh_popcontext(shp,&buff);
900 	loop_level = saveloop;
901 	label_last = savelabel;
902 	/* restore the old stack */
903 	if(slp)
904 	{
905 		slp->slptr =  stakinstall(savstak,0);
906 		slp->slchild = shp->st.staklist;
907 	}
908 #if SHOPT_KIA
909 	lexp->current = current;
910 #endif /* SHOPT_KIA */
911 	if(jmpval)
912 	{
913 		if(slp && slp->slptr)
914 		{
915 			shp->st.staklist = slp->slnext;
916 			stakdelete(slp->slptr);
917 		}
918 		siglongjmp(*shp->jmplist,jmpval);
919 	}
920 	shp->st.staklist = (struct slnod*)slp;
921 	last = fctell();
922 	fp->functline = (last-first);
923 	fp->functtre = t;
924 	shp->mktype = in_mktype;
925 	if(lexp->sh->funlog)
926 	{
927 		if(fcfill()>0)
928 			fcseek(-1);
929 		lexp->sh->funlog = 0;
930 	}
931 #if 	SHOPT_KIA
932 	if(lexp->kiafile)
933 		kiaentity(lexp,t->funct.functnam,-1,'p',t->funct.functline,shp->inlineno-1,lexp->current,'p',0,"");
934 #endif /* SHOPT_KIA */
935 	t->funct.functtyp |= opt_get;
936 	opt_get = save_optget;
937 	return(t);
938 }
939 
940 /*
941  * Compound assignment
942  */
943 static struct argnod *assign(Lex_t *lexp, register struct argnod *ap, int type)
944 {
945 	register int n;
946 	register Shnode_t *t, **tp;
947 	register struct comnod *ac;
948 	Stk_t	*stkp = lexp->sh->stk;
949 	int array=0, index=0;
950 	Namval_t *np;
951 	n = strlen(ap->argval)-1;
952 	if(ap->argval[n]!='=')
953 		sh_syntax(lexp);
954 	if(ap->argval[n-1]=='+')
955 	{
956 		ap->argval[n--]=0;
957 		array = ARG_APPEND;
958 		type |= NV_APPEND;
959 	}
960 	/* shift right */
961 	while(n > 0)
962 	{
963 		ap->argval[n] = ap->argval[n-1];
964 		n--;
965 	}
966 	*ap->argval=0;
967 	t = getnode(fornod);
968 	t->for_.fornam = (char*)(ap->argval+1);
969 	t->for_.fortyp = sh_getlineno(lexp);
970 	tp = &t->for_.fortre;
971 	ap->argchn.ap = (struct argnod*)t;
972 	ap->argflag &= ARG_QUOTED;
973 	ap->argflag |= array;
974 	lexp->assignok = SH_ASSIGN;
975 	if(type==NV_ARRAY)
976 	{
977 		lexp->noreserv = 1;
978 		lexp->assignok = 0;
979 	}
980 	else
981 		lexp->aliasok = 2;
982 	array= (type==NV_ARRAY)?SH_ARRAY:0;
983 	if((n=skipnl(lexp,0))==RPAREN || n==LPAREN)
984 	{
985 		struct argnod *ar,*aq,**settail;
986 		ac = (struct comnod*)getnode(comnod);
987 		memset((void*)ac,0,sizeof(*ac));
988 	comarray:
989 		settail= &ac->comset;
990 		ac->comline = sh_getlineno(lexp);
991 		while(n==LPAREN)
992 		{
993 			ar = (struct argnod*)stkseek(stkp,ARGVAL);
994 			ar->argflag= ARG_ASSIGN;
995 			sfprintf(stkp,"[%d]=",index++);
996 			if(aq=ac->comarg)
997 			{
998 				ac->comarg = aq->argnxt.ap;
999 				sfprintf(stkp,"%s",aq->argval);
1000 				ar->argflag |= aq->argflag;
1001 			}
1002 			ar = (struct argnod*)stkfreeze(stkp,1);
1003 			ar->argnxt.ap = 0;
1004 			if(!aq)
1005 				ar = assign(lexp,ar,0);
1006 			ar->argflag |= ARG_MESSAGE;
1007 			*settail = ar;
1008 			settail = &(ar->argnxt.ap);
1009 			if(aq)
1010 				continue;
1011 			while((n = skipnl(lexp,0))==0)
1012 			{
1013 				ar = (struct argnod*)stkseek(stkp,ARGVAL);
1014 				ar->argflag= ARG_ASSIGN;
1015 				sfprintf(stkp,"[%d]=",index++);
1016 				stakputs(lexp->arg->argval);
1017 				ar = (struct argnod*)stkfreeze(stkp,1);
1018 				ar->argnxt.ap = 0;
1019 				ar->argflag = lexp->arg->argflag;
1020 				*settail = ar;
1021 				settail = &(ar->argnxt.ap);
1022 			}
1023 		}
1024 	}
1025 	else if(n && n!=FUNCTSYM)
1026 		sh_syntax(lexp);
1027 	else if(type!=NV_ARRAY && n!=FUNCTSYM && !(lexp->arg->argflag&ARG_ASSIGN) && !((np=nv_search(lexp->arg->argval,lexp->sh->fun_tree,0)) && (nv_isattr(np,BLT_DCL)|| np==SYSDOT)))
1028 	{
1029 		array=SH_ARRAY;
1030 		if(fcgetc(n)==LPAREN)
1031 		{
1032 			int c;
1033 			if(fcgetc(c)==RPAREN)
1034 			{
1035 				lexp->token =  SYMRES;
1036 				array = 0;
1037 			}
1038 			else
1039 				fcseek(-2);
1040 		}
1041 		else if(n>0)
1042 			fcseek(-1);
1043 		if(array && type==NV_TYPE)
1044 		{
1045 			struct argnod *arg = lexp->arg;
1046 			n = lexp->token;
1047 			if(path_search(lexp->sh,lexp->arg->argval,NIL(Pathcomp_t**),1) && (np=nv_search(lexp->arg->argval,lexp->sh->fun_tree,0)) && nv_isattr(np,BLT_DCL))
1048 			{
1049 				lexp->token = n;
1050 				lexp->arg = arg;
1051 				array = 0;
1052 			}
1053 			else
1054 				sh_syntax(lexp);
1055 		}
1056 	}
1057 	lexp->noreserv = 0;
1058 	while(1)
1059 	{
1060 		if((n=lexp->token)==RPAREN)
1061 			break;
1062 		if(n==FUNCTSYM || n==SYMRES)
1063 			ac = (struct comnod*)funct(lexp);
1064 		else
1065 			ac = (struct comnod*)simple(lexp,SH_NOIO|SH_ASSIGN|type|array,NIL(struct ionod*));
1066 		if((n=lexp->token)==RPAREN)
1067 			break;
1068 		if(n!=NL && n!=';')
1069 		{
1070 			if(array && n==LPAREN)
1071 				goto comarray;
1072 			sh_syntax(lexp);
1073 		}
1074 		lexp->assignok = SH_ASSIGN;
1075 		if((n=skipnl(lexp,0)) || array)
1076 		{
1077 			if(n==RPAREN)
1078 				break;
1079 			if(array ||  n!=FUNCTSYM)
1080 				sh_syntax(lexp);
1081 		}
1082 		if((n!=FUNCTSYM) && !(lexp->arg->argflag&ARG_ASSIGN) && !((np=nv_search(lexp->arg->argval,lexp->sh->fun_tree,0)) && (nv_isattr(np,BLT_DCL)||np==SYSDOT)))
1083 		{
1084 			struct argnod *arg = lexp->arg;
1085 			if(n!=0)
1086 				sh_syntax(lexp);
1087 			/* check for sys5 style function */
1088 			if(sh_lex(lexp)!=LPAREN || sh_lex(lexp)!=RPAREN)
1089 			{
1090 				lexp->arg = arg;
1091 				lexp->token = 0;
1092 				sh_syntax(lexp);
1093 			}
1094 			lexp->arg = arg;
1095 			lexp->token = SYMRES;
1096 		}
1097 		t = makelist(lexp,TLST,(Shnode_t*)ac,t);
1098 		*tp = t;
1099 		tp = &t->lst.lstrit;
1100 	}
1101 	*tp = (Shnode_t*)ac;
1102 	lexp->assignok = 0;
1103 	return(ap);
1104 }
1105 
1106 /*
1107  * item
1108  *
1109  *	( cmd ) [ < in ] [ > out ]
1110  *	word word* [ < in ] [ > out ]
1111  *	if ... then ... else ... fi
1112  *	for ... while ... do ... done
1113  *	case ... in ... esac
1114  *	begin ... end
1115  */
1116 
1117 static Shnode_t	*item(Lex_t *lexp,int flag)
1118 {
1119 	register Shnode_t	*t;
1120 	register struct ionod	*io;
1121 	register int tok = (lexp->token&0xff);
1122 	int savwdval = lexp->lasttok;
1123 	int savline = lexp->lastline;
1124 	int showme=0, comsub;
1125 	if(!(flag&SH_NOIO) && (tok=='<' || tok=='>' || lexp->token==IOVNAME))
1126 		io=inout(lexp,NIL(struct ionod*),1);
1127 	else
1128 		io=0;
1129 	if((tok=lexp->token) && tok!=EOFSYM && tok!=FUNCTSYM)
1130 	{
1131 		lexp->lastline =  sh_getlineno(lexp);
1132 		lexp->lasttok = lexp->token;
1133 	}
1134 	switch(tok)
1135 	{
1136 	    /* [[ ... ]] test expression */
1137 	    case BTESTSYM:
1138 		t = test_expr(lexp,ETESTSYM);
1139 		t->tre.tretyp &= ~TTEST;
1140 		break;
1141 	    /* ((...)) arithmetic expression */
1142 	    case EXPRSYM:
1143 		t = getanode(lexp,lexp->arg);
1144 		sh_lex(lexp);
1145 		goto done;
1146 
1147 	    /* case statement */
1148 	    case CASESYM:
1149 	    {
1150 		int savetok = lexp->lasttok;
1151 		int saveline = lexp->lastline;
1152 		t = getnode(swnod);
1153 		if(sh_lex(lexp))
1154 			sh_syntax(lexp);
1155 		t->sw.swarg=lexp->arg;
1156 		t->sw.swtyp=TSW;
1157 		t->sw.swio = 0;
1158 		t->sw.swtyp |= FLINENO;
1159 		t->sw.swline =  lexp->sh->inlineno;
1160 		if((tok=skipnl(lexp,0))!=INSYM && tok!=LBRACE)
1161 			sh_syntax(lexp);
1162 		if(!(t->sw.swlst=syncase(lexp,tok==INSYM?ESACSYM:RBRACE)) && lexp->token==EOFSYM)
1163 		{
1164 			lexp->lasttok = savetok;
1165 			lexp->lastline = saveline;
1166 			sh_syntax(lexp);
1167 		}
1168 		break;
1169 	    }
1170 
1171 	    /* if statement */
1172 	    case IFSYM:
1173 	    {
1174 		register Shnode_t	*tt;
1175 		t = getnode(ifnod);
1176 		t->if_.iftyp=TIF;
1177 		t->if_.iftre=sh_cmd(lexp,THENSYM,SH_NL);
1178 		t->if_.thtre=sh_cmd(lexp,ELSESYM,SH_NL|SH_SEMI);
1179 		tok = lexp->token;
1180 		t->if_.eltre=(tok==ELSESYM?sh_cmd(lexp,FISYM,SH_NL|SH_SEMI):
1181 			(tok==ELIFSYM?(lexp->token=IFSYM, tt=item(lexp,SH_NOIO)):0));
1182 		if(tok==ELIFSYM)
1183 		{
1184 			if(!tt || tt->tre.tretyp!=TSETIO)
1185 				goto done;
1186 			t->if_.eltre = tt->fork.forktre;
1187 			tt->fork.forktre = t;
1188 			t = tt;
1189 			goto done;
1190 		}
1191 		break;
1192 	    }
1193 
1194 	    /* for and select statement */
1195 	    case FORSYM:
1196 	    case SELECTSYM:
1197 	    {
1198 		t = getnode(fornod);
1199 		t->for_.fortyp=(lexp->token==FORSYM?TFOR:TSELECT);
1200 		t->for_.forlst=0;
1201 		t->for_.forline =  lexp->sh->inlineno;
1202 		if(sh_lex(lexp))
1203 		{
1204 			if(lexp->token!=EXPRSYM || t->for_.fortyp!=TFOR)
1205 				sh_syntax(lexp);
1206 			/* arithmetic for */
1207 			t = arithfor(lexp,t);
1208 			break;
1209 		}
1210 		t->for_.fornam=(char*) lexp->arg->argval;
1211 		t->for_.fortyp |= FLINENO;
1212 #if SHOPT_KIA
1213 		if(lexp->kiafile)
1214 			writedefs(lexp,lexp->arg,lexp->sh->inlineno,'v',NIL(struct argnod*));
1215 #endif /* SHOPT_KIA */
1216 		while((tok=sh_lex(lexp))==NL);
1217 		if(tok==INSYM)
1218 		{
1219 			if(sh_lex(lexp))
1220 			{
1221 				if(lexp->token != NL && lexp->token !=';')
1222 					sh_syntax(lexp);
1223 				/* some Linux scripts assume this */
1224 				if(sh_isoption(SH_NOEXEC))
1225 					errormsg(SH_DICT,ERROR_warn(0),e_lexemptyfor,lexp->sh->inlineno-(lexp->token=='\n'));
1226 				t->for_.forlst = (struct comnod*)getnode(comnod);
1227 				(t->for_.forlst)->comarg = 0;
1228 				(t->for_.forlst)->comset = 0;
1229 				(t->for_.forlst)->comnamp = 0;
1230 				(t->for_.forlst)->comnamq = 0;
1231 				(t->for_.forlst)->comstate = 0;
1232 				(t->for_.forlst)->comio = 0;
1233 				(t->for_.forlst)->comtyp = 0;
1234 			}
1235 			else
1236 				t->for_.forlst=(struct comnod*)simple(lexp,SH_NOIO,NIL(struct ionod*));
1237 			if(lexp->token != NL && lexp->token !=';')
1238 				sh_syntax(lexp);
1239 			tok = skipnl(lexp,0);
1240 		}
1241 		/* 'for i;do cmd' is valid syntax */
1242 		else if(tok==';')
1243 			while((tok=sh_lex(lexp))==NL);
1244 		if(tok!=DOSYM && tok!=LBRACE)
1245 			sh_syntax(lexp);
1246 		loop_level++;
1247 		t->for_.fortre=sh_cmd(lexp,tok==DOSYM?DONESYM:RBRACE,SH_NL|SH_SEMI);
1248 		if(--loop_level==0)
1249 			label_last = label_list;
1250 		break;
1251 	    }
1252 
1253 	    /* This is the code for parsing function definitions */
1254 	    case FUNCTSYM:
1255 		return(funct(lexp));
1256 
1257 #if SHOPT_NAMESPACE
1258 	    case NSPACESYM:
1259 		t = getnode(functnod);
1260 		t->funct.functtyp=TNSPACE;
1261 		t->funct.functargs = 0;
1262 		t->funct.functloc = 0;
1263 		if(sh_lex(lexp))
1264 			sh_syntax(lexp);
1265 		t->funct.functnam=(char*) lexp->arg->argval;
1266 		while((tok=sh_lex(lexp))==NL);
1267 		if(tok!=LBRACE)
1268 			sh_syntax(lexp);
1269 		t->funct.functtre = sh_cmd(lexp,RBRACE,SH_NL);
1270 		break;
1271 #endif /* SHOPT_NAMESPACE */
1272 
1273 	    /* while and until */
1274 	    case WHILESYM:
1275 	    case UNTILSYM:
1276 		t = getnode(whnod);
1277 		t->wh.whtyp=(lexp->token==WHILESYM ? TWH : TUN);
1278 		loop_level++;
1279 		t->wh.whtre = sh_cmd(lexp,DOSYM,SH_NL);
1280 		t->wh.dotre = sh_cmd(lexp,DONESYM,SH_NL|SH_SEMI);
1281 		if(--loop_level==0)
1282 			label_last = label_list;
1283 		t->wh.whinc = 0;
1284 		break;
1285 
1286 	    case LABLSYM:
1287 	    {
1288 		register struct argnod *argp = label_list;
1289 		while(argp)
1290 		{
1291 			if(strcmp(argp->argval,lexp->arg->argval)==0)
1292 				errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax3,lexp->sh->inlineno,argp->argval);
1293 			argp = argp->argnxt.ap;
1294 		}
1295 		lexp->arg->argnxt.ap = label_list;
1296 		label_list = lexp->arg;
1297 		label_list->argchn.len = sh_getlineno(lexp);
1298 		label_list->argflag = loop_level;
1299 		skipnl(lexp,flag);
1300 		if(!(t = item(lexp,SH_NL)))
1301 			sh_syntax(lexp);
1302 		tok = (t->tre.tretyp&(COMSCAN|COMSCAN-1));
1303 		if(sh_isoption(SH_NOEXEC) && tok!=TWH && tok!=TUN && tok!=TFOR && tok!=TSELECT)
1304 			errormsg(SH_DICT,ERROR_warn(0),e_lexlabignore,label_list->argchn.len,label_list->argval);
1305 		return(t);
1306 	    }
1307 
1308 	    /* command group with {...} */
1309 	    case LBRACE:
1310 		comsub = lexp->comsub;
1311 		lexp->comsub = 0;
1312 		t = sh_cmd(lexp,RBRACE,SH_NL|SH_SEMI);
1313 		lexp->comsub = comsub;
1314 		break;
1315 
1316 	    case LPAREN:
1317 		t = getnode(parnod);
1318 		t->par.partre=sh_cmd(lexp,RPAREN,SH_NL|SH_SEMI);
1319 		t->par.partyp=TPAR;
1320 		break;
1321 
1322 #if SHOPT_COSHELL
1323 	    case '&':
1324 		if(tok=sh_lex(lexp))
1325 		{
1326 			if(tok!=NL)
1327 				sh_syntax(lexp);
1328 			t = getnode(comnod);
1329 			memset(t,0,sizeof(struct comnod));
1330 			t->com.comline = sh_getlineno(lexp);
1331 		}
1332 		else
1333 			t = (Shnode_t*)simple(lexp,SH_NOIO,NIL(struct ionod*));
1334 		t->com.comtyp |= FAMP;
1335 		if(lexp->token=='&' || lexp->token=='|')
1336 			sh_syntax(lexp);
1337 		return(t);
1338 		break;
1339 #endif /* SHOPT_COSHELL */
1340 	    default:
1341 		if(io==0)
1342 			return(0);
1343 		/* FALLTHROUGH */
1344 
1345 	    case ';':
1346 		if(io==0)
1347 		{
1348 			if(!(flag&SH_SEMI))
1349 				return(0);
1350 			if(sh_lex(lexp)==';')
1351 				sh_syntax(lexp);
1352 			showme =  FSHOWME;
1353 		}
1354 		/* FALLTHROUGH */
1355 	    case 0:
1356 		t = (Shnode_t*)simple(lexp,flag,io);
1357 		if(t->com.comarg && lexp->intypeset)
1358 			check_typedef(&t->com);
1359 		lexp->intypeset = 0;
1360 		lexp->inexec = 0;
1361 		t->tre.tretyp |= showme;
1362 		return(t);
1363 	}
1364 	sh_lex(lexp);
1365 	if(io=inout(lexp,io,0))
1366 	{
1367 		if((tok=t->tre.tretyp&COMMSK) != TFORK)
1368 			tok = TSETIO;
1369 		t=makeparent(lexp,tok,t);
1370 		t->tre.treio=io;
1371 	}
1372 done:
1373 	lexp->lasttok = savwdval;
1374 	lexp->lastline = savline;
1375 	return(t);
1376 }
1377 
1378 static struct argnod *process_sub(Lex_t *lexp,int tok)
1379 {
1380 	struct argnod *argp;
1381 	Shnode_t *t;
1382 	int mode = (tok==OPROCSYM);
1383 	t = sh_cmd(lexp,RPAREN,SH_NL);
1384 	argp = (struct argnod*)stkalloc(lexp->sh->stk,sizeof(struct argnod));
1385 	*argp->argval = 0;
1386 	argp->argchn.ap = (struct argnod*)makeparent(lexp,mode?TFORK|FPIN|FAMP|FPCL:TFORK|FPOU,t);
1387 	argp->argflag =  (ARG_EXP|mode);
1388 	return(argp);
1389 }
1390 
1391 
1392 /*
1393  * This is for a simple command, for list, or compound assignment
1394  */
1395 static Shnode_t *simple(Lex_t *lexp,int flag, struct ionod *io)
1396 {
1397 	register struct comnod *t;
1398 	register struct argnod	*argp;
1399 	register int tok;
1400 	Stk_t		*stkp = lexp->sh->stk;
1401 	struct argnod	**argtail;
1402 	struct argnod	**settail;
1403 	int	cmdarg=0;
1404 	int	argno = 0;
1405 	int	assignment = 0;
1406 	int	key_on = (!(flag&SH_NOIO) && sh_isoption(SH_KEYWORD));
1407 	int	associative=0;
1408 	if((argp=lexp->arg) && (argp->argflag&ARG_ASSIGN) && argp->argval[0]=='[')
1409 	{
1410 		flag |= SH_ARRAY;
1411 		associative = 1;
1412 	}
1413 	t = (struct comnod*)getnode(comnod);
1414 	t->comio=io; /*initial io chain*/
1415 	/* set command line number for error messages */
1416 	t->comline = sh_getlineno(lexp);
1417 	argtail = &(t->comarg);
1418 	t->comset = 0;
1419 	t->comnamp = 0;
1420 	t->comnamq = 0;
1421 	t->comstate = 0;
1422 	settail = &(t->comset);
1423 	while(lexp->token==0)
1424 	{
1425 		argp = lexp->arg;
1426 		if(*argp->argval==LBRACE && (flag&SH_FUNDEF) && argp->argval[1]==0)
1427 		{
1428 			lexp->token = LBRACE;
1429 			break;
1430 		}
1431 		if(associative && argp->argval[0]!='[')
1432 			sh_syntax(lexp);
1433 		/* check for assignment argument */
1434 		if((argp->argflag&ARG_ASSIGN) && assignment!=2)
1435 		{
1436 			*settail = argp;
1437 			settail = &(argp->argnxt.ap);
1438 			lexp->assignok = (flag&SH_ASSIGN)?SH_ASSIGN:1;
1439 			if(assignment)
1440 			{
1441 				struct argnod *ap=argp;
1442 				char *last, *cp;
1443 				if(assignment==1)
1444 				{
1445 					last = strchr(argp->argval,'=');
1446 					if(last && (last[-1]==']'|| (last[-1]=='+' && last[-2]==']')) && (cp=strchr(argp->argval,'[')) && (cp < last) && cp[-1]!='.')
1447 						last = cp;
1448 					stkseek(stkp,ARGVAL);
1449 					sfwrite(stkp,argp->argval,last-argp->argval);
1450 					ap=(struct argnod*)stkfreeze(stkp,1);
1451 					ap->argflag = ARG_RAW;
1452 					ap->argchn.ap = 0;
1453 				}
1454 				*argtail = ap;
1455 				argtail = &(ap->argnxt.ap);
1456 				if(argno>=0)
1457 					argno++;
1458 			}
1459 			else /* alias substitutions allowed */
1460 				lexp->aliasok = 1;
1461 		}
1462 		else
1463 		{
1464 			if(!(argp->argflag&ARG_RAW))
1465 				argno = -1;
1466 			if(argno>=0 && argno++==cmdarg && !(flag&SH_ARRAY) && *argp->argval!='/')
1467 			{
1468 				/* check for builtin command */
1469 				Namval_t *np=nv_bfsearch(argp->argval,lexp->sh->fun_tree, (Namval_t**)&t->comnamq,(char**)0);
1470 				if(cmdarg==0)
1471 					t->comnamp = (void*)np;
1472 				if(np && is_abuiltin(np))
1473 				{
1474 					if(nv_isattr(np,BLT_DCL))
1475 					{
1476 						assignment = 1+(*argp->argval=='a');
1477 						if(np==SYSTYPESET)
1478 							lexp->intypeset = 1;
1479 						key_on = 1;
1480 					}
1481 					else if(np==SYSCOMMAND)
1482 						cmdarg++;
1483 					else if(np==SYSEXEC)
1484 						lexp->inexec = 1;
1485 					else if(np->nvalue.bfp==(Nambfp_f)b_getopts)
1486 						opt_get |= FOPTGET;
1487 				}
1488 			}
1489 			if((flag&NV_COMVAR) && !assignment)
1490 				sh_syntax(lexp);
1491 			*argtail = argp;
1492 			argtail = &(argp->argnxt.ap);
1493 			if(!(lexp->assignok=key_on)  && !(flag&SH_NOIO) && sh_isoption(SH_NOEXEC))
1494 				lexp->assignok = SH_COMPASSIGN;
1495 			lexp->aliasok = 0;
1496 		}
1497 	retry:
1498 		tok = sh_lex(lexp);
1499 		if(tok==LABLSYM && (flag&SH_ASSIGN))
1500 			lexp->token = tok = 0;
1501 		if((tok==IPROCSYM || tok==OPROCSYM))
1502 		{
1503 			argp = process_sub(lexp,tok);
1504 			argno = -1;
1505 			*argtail = argp;
1506 			argtail = &(argp->argnxt.ap);
1507 			goto retry;
1508 		}
1509 		if(tok==LPAREN)
1510 		{
1511 			if(argp->argflag&ARG_ASSIGN)
1512 			{
1513 				int intypeset = lexp->intypeset;
1514 				int type = 0;
1515 				lexp->intypeset = 0;
1516 				if(t->comnamp==SYSTYPESET)
1517 				{
1518 					struct argnod  *ap;
1519 					for(ap=t->comarg->argnxt.ap;ap;ap=ap->argnxt.ap)
1520 					{
1521 						if(*ap->argval!='-')
1522 							break;
1523 						if(strchr(ap->argval,'T'))
1524 							type = NV_TYPE;
1525 						else if(strchr(ap->argval,'a'))
1526 							type = NV_ARRAY;
1527 						else if(strchr(ap->argval,'C'))
1528 							type = NV_COMVAR;
1529 						else
1530 							continue;
1531 						break;
1532 					}
1533 				}
1534 				argp = assign(lexp,argp,type);
1535 				lexp->intypeset = intypeset;
1536 				if(associative)
1537 					lexp->assignok |= SH_ASSIGN;
1538 				goto retry;
1539 			}
1540 			else if(argno==1 && !t->comset)
1541 			{
1542 				/* SVR2 style function */
1543 				if(!(flag&SH_ARRAY) && sh_lex(lexp) == RPAREN)
1544 				{
1545 					lexp->arg = argp;
1546 					return(funct(lexp));
1547 				}
1548 				lexp->token = LPAREN;
1549 			}
1550 		}
1551 		else if(flag&SH_ASSIGN)
1552 		{
1553 			if(tok==RPAREN)
1554 				break;
1555 			else if(tok==NL && (flag&SH_ARRAY))
1556 			{
1557 				lexp->comp_assign = 2;
1558 				goto retry;
1559 			}
1560 
1561 		}
1562 		if(!(flag&SH_NOIO))
1563 		{
1564 			if(io)
1565 			{
1566 				while(io->ionxt)
1567 					io = io->ionxt;
1568 				io->ionxt = inout(lexp,(struct ionod*)0,0);
1569 			}
1570 			else
1571 				t->comio = io = inout(lexp,(struct ionod*)0,0);
1572 		}
1573 	}
1574 	*argtail = 0;
1575 	t->comtyp = TCOM;
1576 #if SHOPT_KIA
1577 	if(lexp->kiafile && !(flag&SH_NOIO))
1578 	{
1579 		register Namval_t *np=(Namval_t*)t->comnamp;
1580 		unsigned long r=0;
1581 		int line = t->comline;
1582 		argp = t->comarg;
1583 		if(np)
1584 			r = kiaentity(lexp,nv_name(np),-1,'p',-1,0,lexp->unknown,'b',0,"");
1585 		else if(argp)
1586 			r = kiaentity(lexp,sh_argstr(argp),-1,'p',-1,0,lexp->unknown,'c',0,"");
1587 		if(r>0)
1588 			sfprintf(lexp->kiatmp,"p;%..64d;p;%..64d;%d;%d;c;\n",lexp->current,r,line,line);
1589 		if(t->comset && argno==0)
1590 			writedefs(lexp,t->comset,line,'v',t->comarg);
1591 		else if(np && nv_isattr(np,BLT_DCL))
1592 			writedefs(lexp,argp,line,0,NIL(struct argnod*));
1593 		else if(argp && strcmp(argp->argval,"read")==0)
1594 			writedefs(lexp,argp,line,0,NIL(struct argnod*));
1595 #if 0
1596 		else if(argp && strcmp(argp->argval,"unset")==0)
1597 			writedefs(lexp,argp,line,'u',NIL(struct argnod*));
1598 #endif
1599 		else if(argp && *argp->argval=='.' && argp->argval[1]==0 && (argp=argp->argnxt.ap))
1600 		{
1601 			r = kiaentity(lexp,sh_argstr(argp),-1,'p',0,0,lexp->script,'d',0,"");
1602 			sfprintf(lexp->kiatmp,"p;%..64d;p;%..64d;%d;%d;d;\n",lexp->current,r,line,line);
1603 		}
1604 	}
1605 #endif /* SHOPT_KIA */
1606 	if(t->comnamp && (argp=t->comarg->argnxt.ap))
1607 	{
1608 		Namval_t *np=(Namval_t*)t->comnamp;
1609 		if((np==SYSBREAK || np==SYSCONT) && (argp->argflag&ARG_RAW) && !isdigit(*argp->argval))
1610 		{
1611 			register char *cp = argp->argval;
1612 			/* convert break/continue labels to numbers */
1613 			tok = 0;
1614 			for(argp=label_list;argp!=label_last;argp=argp->argnxt.ap)
1615 			{
1616 				if(strcmp(cp,argp->argval))
1617 					continue;
1618 				tok = loop_level-argp->argflag;
1619 				if(tok>=1)
1620 				{
1621 					argp = t->comarg->argnxt.ap;
1622 					if(tok>9)
1623 					{
1624 						argp->argval[1] = '0'+tok%10;
1625 						argp->argval[2] = 0;
1626 						tok /= 10;
1627 					}
1628 					else
1629 						argp->argval[1] = 0;
1630 					*argp->argval = '0'+tok;
1631 				}
1632 				break;
1633 			}
1634 			if(sh_isoption(SH_NOEXEC) && tok==0)
1635 				errormsg(SH_DICT,ERROR_warn(0),e_lexlabunknown,lexp->sh->inlineno-(lexp->token=='\n'),cp);
1636 		}
1637 		else if(sh_isoption(SH_NOEXEC) && np==SYSSET && ((tok= *argp->argval)=='-'||tok=='+') &&
1638 			(argp->argval[1]==0||strchr(argp->argval,'k')))
1639 			errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete5,lexp->sh->inlineno-(lexp->token=='\n'),argp->argval);
1640 	}
1641 	/* expand argument list if possible */
1642 	if(argno>0 && !(flag&(SH_ARRAY|NV_APPEND)))
1643 		t->comarg = qscan(t,argno);
1644 	else if(t->comarg)
1645 		t->comtyp |= COMSCAN;
1646 	lexp->aliasok = 0;
1647 	return((Shnode_t*)t);
1648 }
1649 
1650 /*
1651  * skip past newlines but issue prompt if interactive
1652  */
1653 static int	skipnl(Lex_t *lexp,int flag)
1654 {
1655 	register int token;
1656 	while((token=sh_lex(lexp))==NL);
1657 	if(token==';' && !(flag&SH_SEMI))
1658 		sh_syntax(lexp);
1659 	return(token);
1660 }
1661 
1662 /*
1663  * check for and process and i/o redirections
1664  * if flag>0 then an alias can be in the next word
1665  * if flag<0 only one redirection will be processed
1666  */
1667 static struct ionod	*inout(Lex_t *lexp,struct ionod *lastio,int flag)
1668 {
1669 	register int 		iof = lexp->digits, token=lexp->token;
1670 	register struct ionod	*iop;
1671 	Stk_t			*stkp = lexp->sh->stk;
1672 	char *iovname=0;
1673 	register int		errout=0;
1674 	if(token==IOVNAME)
1675 	{
1676 		iovname=lexp->arg->argval+1;
1677 		token= sh_lex(lexp);
1678 		iof = 0;
1679 	}
1680 	switch(token&0xff)
1681 	{
1682 	    case '<':
1683 		if(token==IODOCSYM)
1684 			iof |= (IODOC|IORAW);
1685 		else if(token==IOMOV0SYM)
1686 			iof |= IOMOV;
1687 		else if(token==IORDWRSYMT)
1688 			iof |= IORDW|IOREWRITE;
1689 		else if(token==IORDWRSYM)
1690 			iof |= IORDW;
1691 		else if((token&SYMSHARP) == SYMSHARP)
1692 		{
1693 			int n;
1694 			iof |= IOLSEEK;
1695 			if(fcgetc(n)=='#')
1696 				iof |= IOCOPY;
1697 			else if(n>0)
1698 				fcseek(-1);
1699 		}
1700 		break;
1701 
1702 	    case '>':
1703 		if(iof<0)
1704 		{
1705 			errout = 1;
1706 			iof = 1;
1707 		}
1708 		iof |= IOPUT;
1709 		if(token==IOAPPSYM)
1710 			iof |= IOAPP;
1711 		else if(token==IOMOV1SYM)
1712 			iof |= IOMOV;
1713 		else if(token==IOCLOBSYM)
1714 			iof |= IOCLOB;
1715 		else if((token&SYMSHARP) == SYMSHARP)
1716 			iof |= IOLSEEK;
1717 		else if((token&SYMSEMI) == SYMSEMI)
1718 			iof |= IOREWRITE;
1719 		break;
1720 
1721 	    default:
1722 		return(lastio);
1723 	}
1724 	lexp->digits=0;
1725 	iop=(struct ionod*) stkalloc(stkp,sizeof(struct ionod));
1726 	iop->iodelim = 0;
1727 	if(token=sh_lex(lexp))
1728 	{
1729 		if(token==RPAREN && (iof&IOLSEEK) && lexp->comsub)
1730 		{
1731 			lexp->arg = (struct argnod*)stkalloc(stkp,sizeof(struct argnod)+3);
1732 			strcpy(lexp->arg->argval,"CUR");
1733 			lexp->arg->argflag = ARG_RAW;
1734 			iof |= IOARITH;
1735 			fcseek(-1);
1736 		}
1737 		else if(token==EXPRSYM && (iof&IOLSEEK))
1738 			iof |= IOARITH;
1739 		else if(((token==IPROCSYM && !(iof&IOPUT)) || (token==OPROCSYM && (iof&IOPUT))) && !(iof&(IOLSEEK|IOREWRITE|IOMOV|IODOC)))
1740 		{
1741 			lexp->arg = process_sub(lexp,token);
1742 			iof |= IOPROCSUB;
1743 		}
1744 		else
1745 			sh_syntax(lexp);
1746 	}
1747 	if( (iof&IOPROCSUB) && !(iof&IOLSEEK))
1748 		iop->ioname= (char*)lexp->arg->argchn.ap;
1749 	else
1750 		iop->ioname=lexp->arg->argval;
1751 	iop->iovname = iovname;
1752 	if(iof&IODOC)
1753 	{
1754 		if(lexp->digits==2)
1755 		{
1756 			iof |= IOSTRG;
1757 			if(!(lexp->arg->argflag&ARG_RAW))
1758 				iof &= ~IORAW;
1759 		}
1760 		else
1761 		{
1762 			if(!lexp->sh->heredocs)
1763 				lexp->sh->heredocs = sftmp(HERE_MEM);
1764 			iop->iolst=lexp->heredoc;
1765 			lexp->heredoc=iop;
1766 			if(lexp->arg->argflag&ARG_QUOTED)
1767 				iof |= IOQUOTE;
1768 			if(lexp->digits==3)
1769 				iof |= IOLSEEK;
1770 			if(lexp->digits)
1771 				iof |= IOSTRIP;
1772 		}
1773 	}
1774 	else
1775 	{
1776 		iop->iolst = 0;
1777 		if(lexp->arg->argflag&ARG_RAW)
1778 			iof |= IORAW;
1779 	}
1780 	iop->iofile=iof;
1781 	if(flag>0)
1782 		/* allow alias substitutions and parameter assignments */
1783 		lexp->aliasok = lexp->assignok = 1;
1784 #if SHOPT_KIA
1785 	if(lexp->kiafile)
1786 	{
1787 		int n = lexp->sh->inlineno-(lexp->token=='\n');
1788 		if(!(iof&IOMOV))
1789 		{
1790 			unsigned long r=kiaentity(lexp,(iof&IORAW)?sh_fmtq(iop->ioname):iop->ioname,-1,'f',0,0,lexp->script,'f',0,"");
1791 			sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;%c;%d\n",lexp->current,r,n,n,(iof&IOPUT)?((iof&IOAPP)?'a':'w'):((iof&IODOC)?'h':'r'),iof&IOUFD);
1792 		}
1793 	}
1794 #endif /* SHOPT_KIA */
1795 	if(flag>=0)
1796 	{
1797 		struct ionod *ioq=iop;
1798 		sh_lex(lexp);
1799 		if(errout)
1800 		{
1801 			/* redirect standard output to standard error */
1802 			ioq = (struct ionod*)stkalloc(stkp,sizeof(struct ionod));
1803 			memset(ioq,0,sizeof(*ioq));
1804 			ioq->ioname = "1";
1805 			ioq->iolst = 0;
1806 			ioq->iodelim = 0;
1807 			ioq->iofile = IORAW|IOPUT|IOMOV|2;
1808 			iop->ionxt=ioq;
1809 		}
1810 		ioq->ionxt=inout(lexp,lastio,flag);
1811 	}
1812 	else
1813 		iop->ionxt=0;
1814 	return(iop);
1815 }
1816 
1817 /*
1818  * convert argument chain to argument list when no special arguments
1819  */
1820 
1821 static struct argnod *qscan(struct comnod *ac,int argn)
1822 {
1823 	register char **cp;
1824 	register struct argnod *ap;
1825 	register struct dolnod* dp;
1826 	register int special=0;
1827 	/* special hack for test -t compatibility */
1828 	if((Namval_t*)ac->comnamp==SYSTEST)
1829 		special = 2;
1830 	else if(*(ac->comarg->argval)=='[' && ac->comarg->argval[1]==0)
1831 		special = 3;
1832 	if(special)
1833 	{
1834 		ap = ac->comarg->argnxt.ap;
1835 		if(argn==(special+1) && ap->argval[1]==0 && *ap->argval=='!')
1836 			ap = ap->argnxt.ap;
1837 		else if(argn!=special)
1838 			special=0;
1839 	}
1840 	if(special)
1841 	{
1842 		const char *message;
1843 		if(strcmp(ap->argval,"-t"))
1844 		{
1845 			message = "line %d: Invariant test";
1846 			special=0;
1847 		}
1848 		else
1849 		{
1850 			message = "line %d: -t requires argument";
1851 			argn++;
1852 		}
1853 		if(sh_isoption(SH_NOEXEC))
1854 			errormsg(SH_DICT,ERROR_warn(0),message,ac->comline);
1855 	}
1856 	/* leave space for an extra argument at the front */
1857 	dp = (struct dolnod*)stakalloc((unsigned)sizeof(struct dolnod) + ARG_SPARE*sizeof(char*) + argn*sizeof(char*));
1858 	cp = dp->dolval+ARG_SPARE;
1859 	dp->dolnum = argn;
1860 	dp->dolbot = ARG_SPARE;
1861 	ap = ac->comarg;
1862 	while(ap)
1863 	{
1864 		*cp++ = ap->argval;
1865 		ap = ap->argnxt.ap;
1866 	}
1867 	if(special==3)
1868 	{
1869 		cp[0] = cp[-1];
1870 		cp[-1] = "1";
1871 		cp++;
1872 	}
1873 	else if(special)
1874 		*cp++ = "1";
1875 	*cp = 0;
1876 	return((struct argnod*)dp);
1877 }
1878 
1879 static Shnode_t *test_expr(Lex_t *lp,int sym)
1880 {
1881 	register Shnode_t *t = test_or(lp);
1882 	if(lp->token!=sym)
1883 		sh_syntax(lp);
1884 	return(t);
1885 }
1886 
1887 static Shnode_t *test_or(Lex_t *lp)
1888 {
1889 	register Shnode_t *t = test_and(lp);
1890 	while(lp->token==ORFSYM)
1891 		t = makelist(lp,TORF|TTEST,t,test_and(lp));
1892 	return(t);
1893 }
1894 
1895 static Shnode_t *test_and(Lex_t *lp)
1896 {
1897 	register Shnode_t *t = test_primary(lp);
1898 	while(lp->token==ANDFSYM)
1899 		t = makelist(lp,TAND|TTEST,t,test_primary(lp));
1900 	return(t);
1901 }
1902 
1903 /*
1904  * convert =~ into == ~(E)
1905  */
1906 static void ere_match(void)
1907 {
1908 	Sfio_t *base, *iop = sfopen((Sfio_t*)0," ~(E)","s");
1909 	register int c;
1910 	while( fcgetc(c),(c==' ' || c=='\t'));
1911 	if(c)
1912 		fcseek(-1);
1913 	if(!(base=fcfile()))
1914 		base = sfopen(NIL(Sfio_t*),fcseek(0),"s");
1915 	fcclose();
1916         sfstack(base,iop);
1917         fcfopen(base);
1918 }
1919 
1920 static Shnode_t *test_primary(Lex_t *lexp)
1921 {
1922 	register struct argnod *arg;
1923 	register Shnode_t *t;
1924 	register int num,token;
1925 	token = skipnl(lexp,0);
1926 	num = lexp->digits;
1927 	switch(token)
1928 	{
1929 	    case '(':
1930 		t = test_expr(lexp,')');
1931 		t = makelist(lexp,TTST|TTEST|TPAREN ,t, (Shnode_t*)pointerof(lexp->sh->inlineno));
1932 		break;
1933 	    case '!':
1934 		if(!(t = test_primary(lexp)))
1935 			sh_syntax(lexp);
1936 		t->tre.tretyp |= TNEGATE;
1937 		return(t);
1938 	    case TESTUNOP:
1939 		if(sh_lex(lexp))
1940 			sh_syntax(lexp);
1941 #if SHOPT_KIA
1942 		if(lexp->kiafile && !strchr("sntzoOG",num))
1943 		{
1944 			int line = lexp->sh->inlineno- (lexp->token==NL);
1945 			unsigned long r;
1946 			r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->script,'t',0,"");
1947 			sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line);
1948 		}
1949 #endif /* SHOPT_KIA */
1950 		t = makelist(lexp,TTST|TTEST|TUNARY|(num<<TSHIFT),
1951 			(Shnode_t*)lexp->arg,(Shnode_t*)lexp->arg);
1952 		t->tst.tstline =  lexp->sh->inlineno;
1953 		break;
1954 	    /* binary test operators */
1955 	    case 0:
1956 		arg = lexp->arg;
1957 		if((token=sh_lex(lexp))==TESTBINOP)
1958 		{
1959 			num = lexp->digits;
1960 			if(num==TEST_REP)
1961 			{
1962 				ere_match();
1963 				num = TEST_PEQ;
1964 			}
1965 		}
1966 		else if(token=='<')
1967 			num = TEST_SLT;
1968 		else if(token=='>')
1969 			num = TEST_SGT;
1970 		else if(token==ANDFSYM||token==ORFSYM||token==ETESTSYM||token==RPAREN)
1971 		{
1972 			t = makelist(lexp,TTST|TTEST|TUNARY|('n'<<TSHIFT),
1973 				(Shnode_t*)arg,(Shnode_t*)arg);
1974 			t->tst.tstline =  lexp->sh->inlineno;
1975 			return(t);
1976 		}
1977 		else
1978 			sh_syntax(lexp);
1979 #if SHOPT_KIA
1980 		if(lexp->kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT))
1981 		{
1982 			int line = lexp->sh->inlineno- (lexp->token==NL);
1983 			unsigned long r;
1984 			r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->current,'t',0,"");
1985 			sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line);
1986 		}
1987 #endif /* SHOPT_KIA */
1988 		if(sh_lex(lexp))
1989 			sh_syntax(lexp);
1990 		if(num&TEST_PATTERN)
1991 		{
1992 			if(lexp->arg->argflag&(ARG_EXP|ARG_MAC))
1993 				num &= ~TEST_PATTERN;
1994 		}
1995 		t = getnode(tstnod);
1996 		t->lst.lsttyp = TTST|TTEST|TBINARY|(num<<TSHIFT);
1997 		t->lst.lstlef = (Shnode_t*)arg;
1998 		t->lst.lstrit = (Shnode_t*)lexp->arg;
1999 		t->tst.tstline =  lexp->sh->inlineno;
2000 #if SHOPT_KIA
2001 		if(lexp->kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT))
2002 		{
2003 			int line = lexp->sh->inlineno-(lexp->token==NL);
2004 			unsigned long r;
2005 			r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->current,'t',0,"");
2006 			sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line);
2007 		}
2008 #endif /* SHOPT_KIA */
2009 		break;
2010 	    default:
2011 		return(0);
2012 	}
2013 	skipnl(lexp,0);
2014 	return(t);
2015 }
2016 
2017 #if SHOPT_KIA
2018 /*
2019  * return an entity checksum
2020  * The entity is created if it doesn't exist
2021  */
2022 unsigned long kiaentity(Lex_t *lexp,const char *name,int len,int type,int first,int last,unsigned long parent, int pkind, int width, const char *attr)
2023 {
2024 	Stk_t	*stkp = lexp->sh->stk;
2025 	Namval_t *np;
2026 	long offset = stktell(stkp);
2027 	sfputc(stkp,type);
2028 	if(len>0)
2029 		sfwrite(stkp,name,len);
2030 	else
2031 	{
2032 		if(type=='p')
2033 			sfputr(stkp,path_basename(name),0);
2034 		else
2035 			sfputr(stkp,name,0);
2036 	}
2037 	np = nv_search(stakptr(offset),lexp->entity_tree,NV_ADD);
2038 	stkseek(stkp,offset);
2039 	np->nvalue.i = pkind;
2040 	nv_setsize(np,width);
2041 	if(!nv_isattr(np,NV_TAGGED) && first>=0)
2042 	{
2043 		nv_onattr(np,NV_TAGGED);
2044 		if(!pkind)
2045 			pkind = '0';
2046 		if(len>0)
2047 			sfprintf(lexp->kiafile,"%..64d;%c;%.*s;%d;%d;%..64d;%..64d;%c;%d;%s\n",np->hash,type,len,name,first,last,parent,lexp->fscript,pkind,width,attr);
2048 		else
2049 			sfprintf(lexp->kiafile,"%..64d;%c;%s;%d;%d;%..64d;%..64d;%c;%d;%s\n",np->hash,type,name,first,last,parent,lexp->fscript,pkind,width,attr);
2050 	}
2051 	return(np->hash);
2052 }
2053 
2054 static void kia_add(register Namval_t *np, void *data)
2055 {
2056 	char *name = nv_name(np);
2057 	Lex_t	*lp = (Lex_t*)data;
2058 	NOT_USED(data);
2059 	kiaentity(lp,name+1,-1,*name,0,-1,(*name=='p'?lp->unknown:lp->script),np->nvalue.i,nv_size(np),"");
2060 }
2061 
2062 int kiaclose(Lex_t *lexp)
2063 {
2064 	register off_t off1,off2;
2065 	register int n;
2066 	if(lexp->kiafile)
2067 	{
2068 		unsigned long r = kiaentity(lexp,lexp->scriptname,-1,'p',-1,lexp->sh->inlineno-1,0,'s',0,"");
2069 		kiaentity(lexp,lexp->scriptname,-1,'p',1,lexp->sh->inlineno-1,r,'s',0,"");
2070 		kiaentity(lexp,lexp->scriptname,-1,'f',1,lexp->sh->inlineno-1,r,'s',0,"");
2071 		nv_scan(lexp->entity_tree,kia_add,(void*)lexp,NV_TAGGED,0);
2072 		off1 = sfseek(lexp->kiafile,(off_t)0,SEEK_END);
2073 		sfseek(lexp->kiatmp,(off_t)0,SEEK_SET);
2074 		sfmove(lexp->kiatmp,lexp->kiafile,SF_UNBOUND,-1);
2075 		off2 = sfseek(lexp->kiafile,(off_t)0,SEEK_END);
2076 #ifdef SF_BUFCONST
2077 		if(off2==off1)
2078 			n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%lld;%d\nDIRECTORY;",(Sflong_t)lexp->kiabegin,(size_t)(off1-lexp->kiabegin));
2079 		else
2080 			n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%lld;%d\nRELATIONSHIP;%lld;%d\nDIRECTORY;",(Sflong_t)lexp->kiabegin,(size_t)(off1-lexp->kiabegin),(Sflong_t)off1,(size_t)(off2-off1));
2081 		if(off2 >= INT_MAX)
2082 			off2 = -(n+12);
2083 		sfprintf(lexp->kiafile,"%010.10lld;%010d\n",(Sflong_t)off2+10, n+12);
2084 #else
2085 		if(off2==off1)
2086 			n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%d;%d\nDIRECTORY;",lexp->kiabegin,off1-lexp->kiabegin);
2087 		else
2088 			n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%d;%d\nRELATIONSHIP;%d;%d\nDIRECTORY;",lexp->kiabegin,off1-lexp->kiabegin,off1,off2-off1);
2089 		sfprintf(lexp->kiafile,"%010d;%010d\n",off2+10, n+12);
2090 #endif
2091 	}
2092 	return(sfclose(lexp->kiafile));
2093 }
2094 #endif /* SHOPT_KIA */
2095