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