14887Schin /***********************************************************************
24887Schin * *
34887Schin * This software is part of the ast package *
4*12068SRoger.Faulkner@Oracle.COM * Copyright (c) 1982-2010 AT&T Intellectual Property *
54887Schin * and is licensed under the *
64887Schin * Common Public License, Version 1.0 *
78462SApril.Chin@Sun.COM * by AT&T Intellectual Property *
84887Schin * *
94887Schin * A copy of the License is available at *
104887Schin * http://www.opensource.org/licenses/cpl1.0.txt *
114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
124887Schin * *
134887Schin * Information and Software Systems Research *
144887Schin * AT&T Research *
154887Schin * Florham Park NJ *
164887Schin * *
174887Schin * David Korn <dgk@research.att.com> *
184887Schin * *
194887Schin ***********************************************************************/
204887Schin #pragma prototyped
214887Schin /*
224887Schin * UNIX shell
234887Schin *
244887Schin * S. R. Bourne
254887Schin * Rewritten by David Korn
264887Schin * AT&T Labs
274887Schin *
284887Schin * This is the parser for a shell language
294887Schin */
304887Schin
314887Schin #if KSHELL
324887Schin #include "defs.h"
334887Schin #else
344887Schin #include <shell.h>
3510898Sroland.mainz@nrubsig.org #include <ctype.h>
364887Schin #endif
374887Schin #include <fcin.h>
384887Schin #include <error.h>
394887Schin #include "shlex.h"
404887Schin #include "history.h"
414887Schin #include "builtins.h"
424887Schin #include "test.h"
434887Schin #include "history.h"
444887Schin
454887Schin #define HERE_MEM 1024 /* size of here-docs kept in memory */
464887Schin
474887Schin #define hash nvlink.hl._hash
484887Schin
494887Schin /* These routines are local to this module */
504887Schin
518462SApril.Chin@Sun.COM static Shnode_t *makeparent(Lex_t*, int, Shnode_t*);
528462SApril.Chin@Sun.COM static Shnode_t *makelist(Lex_t*, int, Shnode_t*, Shnode_t*);
534887Schin static struct argnod *qscan(struct comnod*, int);
548462SApril.Chin@Sun.COM static struct ionod *inout(Lex_t*,struct ionod*, int);
558462SApril.Chin@Sun.COM static Shnode_t *sh_cmd(Lex_t*,int,int);
568462SApril.Chin@Sun.COM static Shnode_t *term(Lex_t*,int);
578462SApril.Chin@Sun.COM static Shnode_t *list(Lex_t*,int);
588462SApril.Chin@Sun.COM static struct regnod *syncase(Lex_t*,int);
598462SApril.Chin@Sun.COM static Shnode_t *item(Lex_t*,int);
608462SApril.Chin@Sun.COM static Shnode_t *simple(Lex_t*,int, struct ionod*);
618462SApril.Chin@Sun.COM static int skipnl(Lex_t*,int);
628462SApril.Chin@Sun.COM static Shnode_t *test_expr(Lex_t*,int);
638462SApril.Chin@Sun.COM static Shnode_t *test_and(Lex_t*);
648462SApril.Chin@Sun.COM static Shnode_t *test_or(Lex_t*);
658462SApril.Chin@Sun.COM static Shnode_t *test_primary(Lex_t*);
664887Schin
678462SApril.Chin@Sun.COM #define sh_getlineno(lp) (lp->lastline)
684887Schin
694887Schin #ifndef NIL
704887Schin # define NIL(type) ((type)0)
714887Schin #endif /* NIL */
724887Schin #define CNTL(x) ((x)&037)
734887Schin
744887Schin
754887Schin #if !KSHELL
764887Schin static struct stdata
774887Schin {
784887Schin struct slnod *staklist;
794887Schin int cmdline;
804887Schin } st;
814887Schin #endif
824887Schin
838462SApril.Chin@Sun.COM static int opt_get;
844887Schin static int loop_level;
854887Schin static struct argnod *label_list;
864887Schin static struct argnod *label_last;
874887Schin
884887Schin #define getnode(type) ((Shnode_t*)stakalloc(sizeof(struct type)))
894887Schin
904887Schin #if SHOPT_KIA
914887Schin #include "path.h"
924887Schin /*
934887Schin * write out entities for each item in the list
944887Schin * type=='V' for variable assignment lists
954887Schin * Otherwise type is determined by the command */
writedefs(Lex_t * lexp,struct argnod * arglist,int line,int type,struct argnod * cmd)968462SApril.Chin@Sun.COM static unsigned long writedefs(Lex_t *lexp,struct argnod *arglist, int line, int type, struct argnod *cmd)
974887Schin {
984887Schin register struct argnod *argp = arglist;
994887Schin register char *cp;
1004887Schin register int n,eline;
1014887Schin int width=0;
1024887Schin unsigned long r=0;
1034887Schin static char atbuff[20];
1044887Schin int justify=0;
1054887Schin char *attribute = atbuff;
1068462SApril.Chin@Sun.COM unsigned long parent=lexp->script;
1074887Schin if(type==0)
1084887Schin {
1098462SApril.Chin@Sun.COM parent = lexp->current;
1104887Schin type = 'v';
1114887Schin switch(*argp->argval)
1124887Schin {
1134887Schin case 'a':
1144887Schin type='p';
1154887Schin justify = 'a';
1164887Schin break;
1174887Schin case 'e':
1184887Schin *attribute++ = 'x';
1194887Schin break;
1204887Schin case 'r':
1214887Schin *attribute++ = 'r';
1224887Schin break;
1234887Schin case 'l':
1244887Schin break;
1254887Schin }
1264887Schin while(argp = argp->argnxt.ap)
1274887Schin {
1284887Schin if((n= *(cp=argp->argval))!='-' && n!='+')
1294887Schin break;
1304887Schin if(cp[1]==n)
1314887Schin break;
1324887Schin while((n= *++cp))
1334887Schin {
1344887Schin if(isdigit(n))
1354887Schin width = 10*width + n-'0';
1364887Schin else if(n=='L' || n=='R' || n =='Z')
1374887Schin justify=n;
1384887Schin else
1394887Schin *attribute++ = n;
1404887Schin }
1414887Schin }
1424887Schin }
1434887Schin else if(cmd)
1448462SApril.Chin@Sun.COM parent=kiaentity(lexp,sh_argstr(cmd),-1,'p',-1,-1,lexp->unknown,'b',0,"");
1454887Schin *attribute = 0;
1464887Schin while(argp)
1474887Schin {
1484887Schin if((cp=strchr(argp->argval,'='))||(cp=strchr(argp->argval,'?')))
1494887Schin n = cp-argp->argval;
1504887Schin else
1514887Schin n = strlen(argp->argval);
1528462SApril.Chin@Sun.COM eline = lexp->sh->inlineno-(lexp->token==NL);
1538462SApril.Chin@Sun.COM r=kiaentity(lexp,argp->argval,n,type,line,eline,parent,justify,width,atbuff);
1548462SApril.Chin@Sun.COM sfprintf(lexp->kiatmp,"p;%..64d;v;%..64d;%d;%d;s;\n",lexp->current,r,line,eline);
1554887Schin argp = argp->argnxt.ap;
1564887Schin }
1574887Schin return(r);
1584887Schin }
1594887Schin #endif /* SHOPT_KIA */
1608462SApril.Chin@Sun.COM
typeset_order(const char * str,int line)1618462SApril.Chin@Sun.COM static void typeset_order(const char *str,int line)
1628462SApril.Chin@Sun.COM {
1638462SApril.Chin@Sun.COM register int c,n=0;
1648462SApril.Chin@Sun.COM unsigned const char *cp=(unsigned char*)str;
1658462SApril.Chin@Sun.COM static unsigned char *table;
1668462SApril.Chin@Sun.COM if(*cp!='+' && *cp!='-')
1678462SApril.Chin@Sun.COM return;
1688462SApril.Chin@Sun.COM if(!table)
1698462SApril.Chin@Sun.COM {
1708462SApril.Chin@Sun.COM table = calloc(1,256);
1718462SApril.Chin@Sun.COM for(cp=(unsigned char*)"bflmnprstuxACHS";c = *cp; cp++)
1728462SApril.Chin@Sun.COM table[c] = 1;
1738462SApril.Chin@Sun.COM for(cp=(unsigned char*)"aiEFLRXhTZ";c = *cp; cp++)
1748462SApril.Chin@Sun.COM table[c] = 2;
1758462SApril.Chin@Sun.COM for(c='0'; c <='9'; c++)
1768462SApril.Chin@Sun.COM table[c] = 3;
1778462SApril.Chin@Sun.COM }
1788462SApril.Chin@Sun.COM for(cp=(unsigned char*)str; c= *cp++; n=table[c])
1798462SApril.Chin@Sun.COM {
1808462SApril.Chin@Sun.COM if(table[c] < n)
1818462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_warn(0),e_lextypeset,line,str);
1828462SApril.Chin@Sun.COM }
1838462SApril.Chin@Sun.COM }
1848462SApril.Chin@Sun.COM
1858462SApril.Chin@Sun.COM /*
1868462SApril.Chin@Sun.COM * add type definitions when compiling with -n
1878462SApril.Chin@Sun.COM */
check_typedef(struct comnod * tp)1888462SApril.Chin@Sun.COM static void check_typedef(struct comnod *tp)
1898462SApril.Chin@Sun.COM {
1908462SApril.Chin@Sun.COM char *cp=0;
1918462SApril.Chin@Sun.COM if(tp->comtyp&COMSCAN)
1928462SApril.Chin@Sun.COM {
1938462SApril.Chin@Sun.COM struct argnod *ap = tp->comarg;
1948462SApril.Chin@Sun.COM while(ap = ap->argnxt.ap)
1958462SApril.Chin@Sun.COM {
1968462SApril.Chin@Sun.COM if(!(ap->argflag&ARG_RAW) || memcmp(ap->argval,"--",2))
1978462SApril.Chin@Sun.COM break;
1988462SApril.Chin@Sun.COM if(sh_isoption(SH_NOEXEC))
1998462SApril.Chin@Sun.COM typeset_order(ap->argval,tp->comline);
2008462SApril.Chin@Sun.COM if(memcmp(ap->argval,"-T",2)==0)
2018462SApril.Chin@Sun.COM {
2028462SApril.Chin@Sun.COM if(ap->argval[2])
2038462SApril.Chin@Sun.COM cp = ap->argval+2;
2048462SApril.Chin@Sun.COM else if((ap->argnxt.ap)->argflag&ARG_RAW)
2058462SApril.Chin@Sun.COM cp = (ap->argnxt.ap)->argval;
2068462SApril.Chin@Sun.COM if(cp)
2078462SApril.Chin@Sun.COM break;
2088462SApril.Chin@Sun.COM }
2098462SApril.Chin@Sun.COM }
2108462SApril.Chin@Sun.COM }
2118462SApril.Chin@Sun.COM else
2128462SApril.Chin@Sun.COM {
2138462SApril.Chin@Sun.COM struct dolnod *dp = (struct dolnod*)tp->comarg;
2148462SApril.Chin@Sun.COM char **argv = dp->dolval + dp->dolbot+1;
2158462SApril.Chin@Sun.COM while((cp= *argv++) && memcmp(cp,"--",2))
2168462SApril.Chin@Sun.COM {
2178462SApril.Chin@Sun.COM if(sh_isoption(SH_NOEXEC))
2188462SApril.Chin@Sun.COM typeset_order(cp,tp->comline);
2198462SApril.Chin@Sun.COM if(memcmp(cp,"-T",2)==0)
2208462SApril.Chin@Sun.COM {
2218462SApril.Chin@Sun.COM if(cp[2])
2228462SApril.Chin@Sun.COM cp = cp+2;
2238462SApril.Chin@Sun.COM else
2248462SApril.Chin@Sun.COM cp = *argv;
2258462SApril.Chin@Sun.COM break;
2268462SApril.Chin@Sun.COM }
2278462SApril.Chin@Sun.COM }
2288462SApril.Chin@Sun.COM }
2298462SApril.Chin@Sun.COM if(cp)
2308462SApril.Chin@Sun.COM {
2318462SApril.Chin@Sun.COM Namval_t *mp=(Namval_t*)tp->comnamp ,*bp;
2328462SApril.Chin@Sun.COM bp = sh_addbuiltin(cp,mp->nvalue.bfp, (void*)0);
2338462SApril.Chin@Sun.COM nv_onattr(bp,nv_isattr(mp,NV_PUBLIC));
2348462SApril.Chin@Sun.COM }
2358462SApril.Chin@Sun.COM }
2368462SApril.Chin@Sun.COM
2374887Schin /*
2384887Schin * Make a parent node for fork() or io-redirection
2394887Schin */
makeparent(Lex_t * lp,int flag,Shnode_t * child)2408462SApril.Chin@Sun.COM static Shnode_t *makeparent(Lex_t *lp, int flag, Shnode_t *child)
2414887Schin {
2424887Schin register Shnode_t *par = getnode(forknod);
2434887Schin par->fork.forktyp = flag;
2444887Schin par->fork.forktre = child;
2454887Schin par->fork.forkio = 0;
2468462SApril.Chin@Sun.COM par->fork.forkline = sh_getlineno(lp)-1;
2474887Schin return(par);
2484887Schin }
2494887Schin
paramsub(const char * str)250*12068SRoger.Faulkner@Oracle.COM static int paramsub(const char *str)
251*12068SRoger.Faulkner@Oracle.COM {
252*12068SRoger.Faulkner@Oracle.COM register int c,sub=0,lit=0;
253*12068SRoger.Faulkner@Oracle.COM while(c= *str++)
254*12068SRoger.Faulkner@Oracle.COM {
255*12068SRoger.Faulkner@Oracle.COM if(c=='$' && !lit)
256*12068SRoger.Faulkner@Oracle.COM {
257*12068SRoger.Faulkner@Oracle.COM if(*str=='(')
258*12068SRoger.Faulkner@Oracle.COM return(0);
259*12068SRoger.Faulkner@Oracle.COM if(sub)
260*12068SRoger.Faulkner@Oracle.COM continue;
261*12068SRoger.Faulkner@Oracle.COM if(*str=='{')
262*12068SRoger.Faulkner@Oracle.COM str++;
263*12068SRoger.Faulkner@Oracle.COM if(!isdigit(*str) && strchr("?#@*!$ ",*str)==0)
264*12068SRoger.Faulkner@Oracle.COM return(1);
265*12068SRoger.Faulkner@Oracle.COM }
266*12068SRoger.Faulkner@Oracle.COM else if(c=='`')
267*12068SRoger.Faulkner@Oracle.COM return(0);
268*12068SRoger.Faulkner@Oracle.COM else if(c=='[' && !lit)
269*12068SRoger.Faulkner@Oracle.COM sub++;
270*12068SRoger.Faulkner@Oracle.COM else if(c==']' && !lit)
271*12068SRoger.Faulkner@Oracle.COM sub--;
272*12068SRoger.Faulkner@Oracle.COM else if(c=='\'')
273*12068SRoger.Faulkner@Oracle.COM lit = !lit;
274*12068SRoger.Faulkner@Oracle.COM }
275*12068SRoger.Faulkner@Oracle.COM return(0);
276*12068SRoger.Faulkner@Oracle.COM }
277*12068SRoger.Faulkner@Oracle.COM
getanode(Lex_t * lp,struct argnod * ap)2788462SApril.Chin@Sun.COM static Shnode_t *getanode(Lex_t *lp, struct argnod *ap)
2794887Schin {
2804887Schin register Shnode_t *t = getnode(arithnod);
2814887Schin t->ar.artyp = TARITH;
2828462SApril.Chin@Sun.COM t->ar.arline = sh_getlineno(lp);
2834887Schin t->ar.arexpr = ap;
2844887Schin if(ap->argflag&ARG_RAW)
2854887Schin t->ar.arcomp = sh_arithcomp(ap->argval);
2864887Schin else
287*12068SRoger.Faulkner@Oracle.COM {
288*12068SRoger.Faulkner@Oracle.COM if(sh_isoption(SH_NOEXEC) && (ap->argflag&ARG_MAC) && paramsub(ap->argval))
289*12068SRoger.Faulkner@Oracle.COM errormsg(SH_DICT,ERROR_warn(0),"%d: parameter substitution requires unnecessary string to number conversion",lp->sh->inlineno-(lp->token=='\n'));
2904887Schin t->ar.arcomp = 0;
291*12068SRoger.Faulkner@Oracle.COM }
2924887Schin return(t);
2934887Schin }
2944887Schin
2954887Schin /*
2964887Schin * Make a node corresponding to a command list
2974887Schin */
makelist(Lex_t * lexp,int type,Shnode_t * l,Shnode_t * r)2988462SApril.Chin@Sun.COM static Shnode_t *makelist(Lex_t *lexp, int type, Shnode_t *l, Shnode_t *r)
2994887Schin {
3004887Schin register Shnode_t *t;
3014887Schin if(!l || !r)
3028462SApril.Chin@Sun.COM sh_syntax(lexp);
3034887Schin else
3044887Schin {
3054887Schin if((type&COMMSK) == TTST)
3064887Schin t = getnode(tstnod);
3074887Schin else
3084887Schin t = getnode(lstnod);
3094887Schin t->lst.lsttyp = type;
3104887Schin t->lst.lstlef = l;
3114887Schin t->lst.lstrit = r;
3124887Schin }
3134887Schin return(t);
3144887Schin }
3154887Schin
3164887Schin /*
3174887Schin * entry to shell parser
3184887Schin * Flag can be the union of SH_EOF|SH_NL
3194887Schin */
3204887Schin
sh_parse(Shell_t * shp,Sfio_t * iop,int flag)3214887Schin void *sh_parse(Shell_t *shp, Sfio_t *iop, int flag)
3224887Schin {
3234887Schin register Shnode_t *t;
3248462SApril.Chin@Sun.COM Lex_t *lexp = (Lex_t*)shp->lex_context;
3254887Schin Fcin_t sav_input;
3268462SApril.Chin@Sun.COM struct argnod *sav_arg = lexp->arg;
3274887Schin int sav_prompt = shp->nextprompt;
32810898Sroland.mainz@nrubsig.org if(shp->binscript && (sffileno(iop)==shp->infd || (flag&SH_FUNEVAL)))
3298462SApril.Chin@Sun.COM return((void*)sh_trestore(shp,iop));
3304887Schin fcsave(&sav_input);
3314887Schin shp->st.staklist = 0;
3328462SApril.Chin@Sun.COM lexp->heredoc = 0;
3338462SApril.Chin@Sun.COM lexp->inlineno = shp->inlineno;
3348462SApril.Chin@Sun.COM lexp->firstline = shp->st.firstline;
3354887Schin shp->nextprompt = 1;
3364887Schin loop_level = 0;
3374887Schin label_list = label_last = 0;
3384887Schin if(sh_isoption(SH_INTERACTIVE))
3394887Schin sh_onstate(SH_INTERACTIVE);
3404887Schin if(sh_isoption(SH_VERBOSE))
3414887Schin sh_onstate(SH_VERBOSE);
3428462SApril.Chin@Sun.COM sh_lexopen(lexp,shp,0);
3434887Schin if(fcfopen(iop) < 0)
3444887Schin return(NIL(void*));
3454887Schin if(fcfile())
3464887Schin {
3474887Schin char *cp = fcfirst();
3484887Schin if( cp[0]==CNTL('k') && cp[1]==CNTL('s') && cp[2]==CNTL('h') && cp[3]==0)
3494887Schin {
3504887Schin int version;
3514887Schin fcseek(4);
3524887Schin fcgetc(version);
3534887Schin fcclose();
3544887Schin fcrestore(&sav_input);
3558462SApril.Chin@Sun.COM lexp->arg = sav_arg;
3564887Schin if(version > 3)
3574887Schin errormsg(SH_DICT,ERROR_exit(1),e_lexversion);
35810898Sroland.mainz@nrubsig.org if(sffileno(iop)==shp->infd || (flag&SH_FUNEVAL))
3594887Schin shp->binscript = 1;
3604887Schin sfgetc(iop);
3618462SApril.Chin@Sun.COM return((void*)sh_trestore(shp,iop));
3624887Schin }
3634887Schin }
36410898Sroland.mainz@nrubsig.org flag &= ~SH_FUNEVAL;
3654887Schin if((flag&SH_NL) && (shp->inlineno=error_info.line+shp->st.firstline)==0)
3664887Schin shp->inlineno=1;
3674887Schin #if KSHELL
3684887Schin shp->nextprompt = 2;
3694887Schin #endif
3708462SApril.Chin@Sun.COM t = sh_cmd(lexp,(flag&SH_EOF)?EOFSYM:'\n',SH_SEMI|SH_EMPTY|(flag&SH_NL));
3714887Schin fcclose();
3724887Schin fcrestore(&sav_input);
3738462SApril.Chin@Sun.COM lexp->arg = sav_arg;
3744887Schin /* unstack any completed alias expansions */
3754887Schin if((sfset(iop,0,0)&SF_STRING) && !sfreserve(iop,0,-1))
3764887Schin {
3774887Schin Sfio_t *sp = sfstack(iop,NULL);
3784887Schin if(sp)
3794887Schin sfclose(sp);
3804887Schin }
3814887Schin shp->nextprompt = sav_prompt;
3824887Schin if(flag&SH_NL)
3834887Schin {
3848462SApril.Chin@Sun.COM shp->st.firstline = lexp->firstline;
3858462SApril.Chin@Sun.COM shp->inlineno = lexp->inlineno;
3864887Schin }
3878462SApril.Chin@Sun.COM stkseek(shp->stk,0);
3884887Schin return((void*)t);
3894887Schin }
3904887Schin
3914887Schin /*
3924887Schin * This routine parses up the matching right parenthesis and returns
3934887Schin * the parse tree
3944887Schin */
sh_dolparen(Lex_t * lp)3958462SApril.Chin@Sun.COM Shnode_t *sh_dolparen(Lex_t* lp)
3964887Schin {
3974887Schin register Shnode_t *t=0;
3984887Schin Sfio_t *sp = fcfile();
3998462SApril.Chin@Sun.COM int line = lp->sh->inlineno;
4008462SApril.Chin@Sun.COM lp->sh->inlineno = error_info.line+lp->sh->st.firstline;
4018462SApril.Chin@Sun.COM sh_lexopen(lp,lp->sh,1);
4028462SApril.Chin@Sun.COM lp->comsub = 1;
4038462SApril.Chin@Sun.COM switch(sh_lex(lp))
4044887Schin {
4054887Schin /* ((...)) arithmetic expression */
4064887Schin case EXPRSYM:
4078462SApril.Chin@Sun.COM t = getanode(lp,lp->arg);
4084887Schin break;
4094887Schin case LPAREN:
4108462SApril.Chin@Sun.COM t = sh_cmd(lp,RPAREN,SH_NL|SH_EMPTY);
4118462SApril.Chin@Sun.COM break;
4128462SApril.Chin@Sun.COM case LBRACE:
4138462SApril.Chin@Sun.COM t = sh_cmd(lp,RBRACE,SH_NL|SH_EMPTY);
4144887Schin break;
4154887Schin }
4168462SApril.Chin@Sun.COM lp->comsub = 0;
4174887Schin if(!sp && (sp=fcfile()))
4184887Schin {
4194887Schin /*
4204887Schin * This code handles the case where string has been converted
4214887Schin * to a file by an alias setup
4224887Schin */
4234887Schin register int c;
4244887Schin char *cp;
4254887Schin if(fcgetc(c) > 0)
4264887Schin fcseek(-1);
4274887Schin cp = fcseek(0);
4284887Schin fcclose();
4294887Schin fcsopen(cp);
4304887Schin sfclose(sp);
4314887Schin }
4328462SApril.Chin@Sun.COM lp->sh->inlineno = line;
4334887Schin return(t);
4344887Schin }
4354887Schin
4364887Schin /*
4374887Schin * remove temporary files and stacks
4384887Schin */
4394887Schin
sh_freeup(Shell_t * shp)4408462SApril.Chin@Sun.COM void sh_freeup(Shell_t *shp)
4414887Schin {
4428462SApril.Chin@Sun.COM if(shp->st.staklist)
4438462SApril.Chin@Sun.COM sh_funstaks(shp->st.staklist,-1);
4448462SApril.Chin@Sun.COM shp->st.staklist = 0;
4454887Schin }
4464887Schin
4474887Schin /*
4484887Schin * increase reference count for each stack in function list when flag>0
4494887Schin * decrease reference count for each stack in function list when flag<=0
4504887Schin * stack is freed when reference count is zero
4514887Schin */
4524887Schin
sh_funstaks(register struct slnod * slp,int flag)4534887Schin void sh_funstaks(register struct slnod *slp,int flag)
4544887Schin {
4554887Schin register struct slnod *slpold;
4564887Schin while(slpold=slp)
4574887Schin {
4584887Schin if(slp->slchild)
4594887Schin sh_funstaks(slp->slchild,flag);
4604887Schin slp = slp->slnext;
4614887Schin if(flag<=0)
4624887Schin stakdelete(slpold->slptr);
4634887Schin else
4644887Schin staklink(slpold->slptr);
4654887Schin }
4664887Schin }
4674887Schin /*
4684887Schin * cmd
4694887Schin * empty
4704887Schin * list
4714887Schin * list & [ cmd ]
4724887Schin * list [ ; cmd ]
4734887Schin */
4744887Schin
sh_cmd(Lex_t * lexp,register int sym,int flag)4758462SApril.Chin@Sun.COM static Shnode_t *sh_cmd(Lex_t *lexp, register int sym, int flag)
4764887Schin {
4774887Schin register Shnode_t *left, *right;
4784887Schin register int type = FINT|FAMP;
4794887Schin if(sym==NL)
4808462SApril.Chin@Sun.COM lexp->lasttok = 0;
4818462SApril.Chin@Sun.COM left = list(lexp,flag);
4828462SApril.Chin@Sun.COM if(lexp->token==NL)
4834887Schin {
4844887Schin if(flag&SH_NL)
4858462SApril.Chin@Sun.COM lexp->token=';';
4864887Schin }
4874887Schin else if(!left && !(flag&SH_EMPTY))
4888462SApril.Chin@Sun.COM sh_syntax(lexp);
4898462SApril.Chin@Sun.COM switch(lexp->token)
4904887Schin {
4914887Schin case COOPSYM: /* set up a cooperating process */
4924887Schin type |= (FPIN|FPOU|FPCL|FCOOP);
4934887Schin /* FALL THRU */
4944887Schin case '&':
4954887Schin if(left)
4964887Schin {
4974887Schin /* (...)& -> {...;} & */
4984887Schin if(left->tre.tretyp==TPAR)
4994887Schin left = left->par.partre;
5008462SApril.Chin@Sun.COM left = makeparent(lexp,TFORK|type, left);
5014887Schin }
5024887Schin /* FALL THRU */
5034887Schin case ';':
5044887Schin if(!left)
5058462SApril.Chin@Sun.COM sh_syntax(lexp);
5068462SApril.Chin@Sun.COM if(right=sh_cmd(lexp,sym,flag|SH_EMPTY))
5078462SApril.Chin@Sun.COM left=makelist(lexp,TLST, left, right);
5084887Schin break;
5094887Schin case EOFSYM:
5104887Schin if(sym==NL)
5114887Schin break;
5124887Schin default:
5138462SApril.Chin@Sun.COM if(sym && sym!=lexp->token)
5144887Schin {
5158462SApril.Chin@Sun.COM if(sym!=ELSESYM || (lexp->token!=ELIFSYM && lexp->token!=FISYM))
5168462SApril.Chin@Sun.COM sh_syntax(lexp);
5174887Schin }
5184887Schin }
5194887Schin return(left);
5204887Schin }
5214887Schin
5224887Schin /*
5234887Schin * list
5244887Schin * term
5254887Schin * list && term
5264887Schin * list || term
5274887Schin * unfortunately, these are equal precedence
5284887Schin */
list(Lex_t * lexp,register int flag)5298462SApril.Chin@Sun.COM static Shnode_t *list(Lex_t *lexp, register int flag)
5304887Schin {
5318462SApril.Chin@Sun.COM register Shnode_t *t = term(lexp,flag);
5324887Schin register int token;
5338462SApril.Chin@Sun.COM while(t && ((token=lexp->token)==ANDFSYM || token==ORFSYM))
5348462SApril.Chin@Sun.COM t = makelist(lexp,(token==ANDFSYM?TAND:TORF), t, term(lexp,SH_NL|SH_SEMI));
5354887Schin return(t);
5364887Schin }
5374887Schin
5384887Schin /*
5394887Schin * term
5404887Schin * item
5414887Schin * item | term
5424887Schin */
term(Lex_t * lexp,register int flag)5438462SApril.Chin@Sun.COM static Shnode_t *term(Lex_t *lexp,register int flag)
5444887Schin {
5454887Schin register Shnode_t *t;
5464887Schin register int token;
5474887Schin if(flag&SH_NL)
5488462SApril.Chin@Sun.COM token = skipnl(lexp,flag);
5494887Schin else
5508462SApril.Chin@Sun.COM token = sh_lex(lexp);
5514887Schin /* check to see if pipeline is to be timed */
5524887Schin if(token==TIMESYM || token==NOTSYM)
5534887Schin {
5544887Schin t = getnode(parnod);
5554887Schin t->par.partyp=TTIME;
5568462SApril.Chin@Sun.COM if(lexp->token==NOTSYM)
5574887Schin t->par.partyp |= COMSCAN;
5588462SApril.Chin@Sun.COM t->par.partre = term(lexp,0);
5594887Schin }
5608462SApril.Chin@Sun.COM else if((t=item(lexp,SH_NL|SH_EMPTY|(flag&SH_SEMI))) && lexp->token=='|')
5614887Schin {
5624887Schin register Shnode_t *tt;
5634887Schin int showme = t->tre.tretyp&FSHOWME;
5648462SApril.Chin@Sun.COM t = makeparent(lexp,TFORK|FPOU,t);
5658462SApril.Chin@Sun.COM if(tt=term(lexp,SH_NL))
5664887Schin {
5674887Schin switch(tt->tre.tretyp&COMMSK)
5684887Schin {
5694887Schin case TFORK:
5704887Schin tt->tre.tretyp |= FPIN|FPCL;
5714887Schin break;
5724887Schin case TFIL:
5734887Schin tt->lst.lstlef->tre.tretyp |= FPIN|FPCL;
5744887Schin break;
5754887Schin default:
5768462SApril.Chin@Sun.COM tt= makeparent(lexp,TSETIO|FPIN|FPCL,tt);
5774887Schin }
5788462SApril.Chin@Sun.COM t=makelist(lexp,TFIL,t,tt);
5794887Schin t->tre.tretyp |= showme;
5804887Schin }
5818462SApril.Chin@Sun.COM else if(lexp->token)
5828462SApril.Chin@Sun.COM sh_syntax(lexp);
5834887Schin }
5844887Schin return(t);
5854887Schin }
5864887Schin
5874887Schin /*
5884887Schin * case statement
5894887Schin */
syncase(Lex_t * lexp,register int esym)5908462SApril.Chin@Sun.COM static struct regnod* syncase(Lex_t *lexp,register int esym)
5914887Schin {
5928462SApril.Chin@Sun.COM register int tok = skipnl(lexp,0);
5934887Schin register struct regnod *r;
5944887Schin if(tok==esym)
5954887Schin return(NIL(struct regnod*));
5964887Schin r = (struct regnod*)stakalloc(sizeof(struct regnod));
5974887Schin r->regptr=0;
5984887Schin r->regflag=0;
5994887Schin if(tok==LPAREN)
6008462SApril.Chin@Sun.COM skipnl(lexp,0);
6014887Schin while(1)
6024887Schin {
6038462SApril.Chin@Sun.COM if(!lexp->arg)
6048462SApril.Chin@Sun.COM sh_syntax(lexp);
6058462SApril.Chin@Sun.COM lexp->arg->argnxt.ap=r->regptr;
6068462SApril.Chin@Sun.COM r->regptr = lexp->arg;
6078462SApril.Chin@Sun.COM if((tok=sh_lex(lexp))==RPAREN)
6084887Schin break;
6094887Schin else if(tok=='|')
6108462SApril.Chin@Sun.COM sh_lex(lexp);
6114887Schin else
6128462SApril.Chin@Sun.COM sh_syntax(lexp);
6134887Schin }
6148462SApril.Chin@Sun.COM r->regcom=sh_cmd(lexp,0,SH_NL|SH_EMPTY|SH_SEMI);
6158462SApril.Chin@Sun.COM if((tok=lexp->token)==BREAKCASESYM)
6168462SApril.Chin@Sun.COM r->regnxt=syncase(lexp,esym);
6174887Schin else if(tok==FALLTHRUSYM)
6184887Schin {
6194887Schin r->regflag++;
6208462SApril.Chin@Sun.COM r->regnxt=syncase(lexp,esym);
6214887Schin }
6224887Schin else
6234887Schin {
6244887Schin if(tok!=esym && tok!=EOFSYM)
6258462SApril.Chin@Sun.COM sh_syntax(lexp);
6264887Schin r->regnxt=0;
6274887Schin }
6288462SApril.Chin@Sun.COM if(lexp->token==EOFSYM)
6294887Schin return(NIL(struct regnod*));
6304887Schin return(r);
6314887Schin }
6324887Schin
6334887Schin /*
6344887Schin * This routine creates the parse tree for the arithmetic for
6354887Schin * When called, shlex.arg contains the string inside ((...))
6364887Schin * When the first argument is missing, a while node is returned
6374887Schin * Otherise a list containing an arithmetic command and a while
6384887Schin * is returned.
6394887Schin */
arithfor(Lex_t * lexp,register Shnode_t * tf)6408462SApril.Chin@Sun.COM static Shnode_t *arithfor(Lex_t *lexp,register Shnode_t *tf)
6414887Schin {
6424887Schin register Shnode_t *t, *tw = tf;
6434887Schin register int offset;
6444887Schin register struct argnod *argp;
6454887Schin register int n;
6468462SApril.Chin@Sun.COM Stk_t *stkp = lexp->sh->stk;
6478462SApril.Chin@Sun.COM int argflag = lexp->arg->argflag;
6484887Schin /* save current input */
6494887Schin Fcin_t sav_input;
6504887Schin fcsave(&sav_input);
6518462SApril.Chin@Sun.COM fcsopen(lexp->arg->argval);
6524887Schin /* split ((...)) into three expressions */
6534887Schin for(n=0; ; n++)
6544887Schin {
6554887Schin register int c;
6568462SApril.Chin@Sun.COM argp = (struct argnod*)stkseek(stkp,ARGVAL);
6574887Schin argp->argnxt.ap = 0;
6584887Schin argp->argchn.cp = 0;
6594887Schin argp->argflag = argflag;
6604887Schin if(n==2)
6614887Schin break;
6624887Schin /* copy up to ; onto the stack */
6638462SApril.Chin@Sun.COM sh_lexskip(lexp,';',1,ST_NESTED);
6648462SApril.Chin@Sun.COM offset = stktell(stkp)-1;
6654887Schin if((c=fcpeek(-1))!=';')
6664887Schin break;
6674887Schin /* remove trailing white space */
6688462SApril.Chin@Sun.COM while(offset>ARGVAL && ((c= *stkptr(stkp,offset-1)),isspace(c)))
6694887Schin offset--;
6704887Schin /* check for empty initialization expression */
6714887Schin if(offset==ARGVAL && n==0)
6724887Schin continue;
6738462SApril.Chin@Sun.COM stkseek(stkp,offset);
6744887Schin /* check for empty condition and treat as while((1)) */
6754887Schin if(offset==ARGVAL)
6768462SApril.Chin@Sun.COM sfputc(stkp,'1');
6778462SApril.Chin@Sun.COM argp = (struct argnod*)stkfreeze(stkp,1);
6788462SApril.Chin@Sun.COM t = getanode(lexp,argp);
6794887Schin if(n==0)
6808462SApril.Chin@Sun.COM tf = makelist(lexp,TLST,t,tw);
6814887Schin else
6824887Schin tw->wh.whtre = t;
6834887Schin }
6844887Schin while((offset=fcpeek(0)) && isspace(offset))
6854887Schin fcseek(1);
6864887Schin stakputs(fcseek(0));
6874887Schin argp = (struct argnod*)stakfreeze(1);
6884887Schin fcrestore(&sav_input);
6894887Schin if(n<2)
6904887Schin {
6918462SApril.Chin@Sun.COM lexp->token = RPAREN|SYMREP;
6928462SApril.Chin@Sun.COM sh_syntax(lexp);
6934887Schin }
6944887Schin /* check whether the increment is present */
6954887Schin if(*argp->argval)
6964887Schin {
6978462SApril.Chin@Sun.COM t = getanode(lexp,argp);
6984887Schin tw->wh.whinc = (struct arithnod*)t;
6994887Schin }
7004887Schin else
7014887Schin tw->wh.whinc = 0;
7028462SApril.Chin@Sun.COM sh_lexopen(lexp, lexp->sh,1);
7038462SApril.Chin@Sun.COM if((n=sh_lex(lexp))==NL)
7048462SApril.Chin@Sun.COM n = skipnl(lexp,0);
7054887Schin else if(n==';')
7068462SApril.Chin@Sun.COM n = sh_lex(lexp);
7074887Schin if(n!=DOSYM && n!=LBRACE)
7088462SApril.Chin@Sun.COM sh_syntax(lexp);
7098462SApril.Chin@Sun.COM tw->wh.dotre = sh_cmd(lexp,n==DOSYM?DONESYM:RBRACE,SH_NL);
7104887Schin tw->wh.whtyp = TWH;
7114887Schin return(tf);
7124887Schin
7134887Schin }
7144887Schin
funct(Lex_t * lexp)7158462SApril.Chin@Sun.COM static Shnode_t *funct(Lex_t *lexp)
7164887Schin {
7178462SApril.Chin@Sun.COM Shell_t *shp = lexp->sh;
7184887Schin register Shnode_t *t;
7194887Schin register int flag;
7204887Schin struct slnod *volatile slp=0;
7214887Schin Stak_t *savstak;
7224887Schin Sfoff_t first, last;
7238462SApril.Chin@Sun.COM struct functnod *volatile fp;
7244887Schin Sfio_t *iop;
7254887Schin #if SHOPT_KIA
7268462SApril.Chin@Sun.COM unsigned long current = lexp->current;
7274887Schin #endif /* SHOPT_KIA */
7284887Schin int jmpval, saveloop=loop_level;
7294887Schin struct argnod *savelabel = label_last;
7304887Schin struct checkpt buff;
7318462SApril.Chin@Sun.COM int save_optget = opt_get;
7328462SApril.Chin@Sun.COM void *in_mktype = shp->mktype;
7338462SApril.Chin@Sun.COM shp->mktype = 0;
7348462SApril.Chin@Sun.COM opt_get = 0;
7354887Schin t = getnode(functnod);
7368462SApril.Chin@Sun.COM t->funct.functline = shp->inlineno;
7374887Schin t->funct.functtyp=TFUN;
7384887Schin t->funct.functargs = 0;
7398462SApril.Chin@Sun.COM if(!(flag = (lexp->token==FUNCTSYM)))
7404887Schin t->funct.functtyp |= FPOSIX;
7418462SApril.Chin@Sun.COM else if(sh_lex(lexp))
7428462SApril.Chin@Sun.COM sh_syntax(lexp);
7434887Schin if(!(iop=fcfile()))
7444887Schin {
7454887Schin iop = sfopen(NIL(Sfio_t*),fcseek(0),"s");
7464887Schin fcclose();
7474887Schin fcfopen(iop);
7484887Schin }
7494887Schin t->funct.functloc = first = fctell();
7508462SApril.Chin@Sun.COM if(!shp->st.filename || sffileno(iop)<0)
7514887Schin {
7524887Schin if(fcfill() >= 0)
7534887Schin fcseek(-1);
75410898Sroland.mainz@nrubsig.org if(sh_isstate(SH_HISTORY) && shp->hist_ptr)
7558462SApril.Chin@Sun.COM t->funct.functloc = sfseek(shp->hist_ptr->histfp,(off_t)0,SEEK_CUR);
7564887Schin else
7574887Schin {
7584887Schin /* copy source to temporary file */
7594887Schin t->funct.functloc = 0;
7608462SApril.Chin@Sun.COM if(lexp->sh->heredocs)
7618462SApril.Chin@Sun.COM t->funct.functloc = sfseek(lexp->sh->heredocs,(Sfoff_t)0, SEEK_END);
7624887Schin else
7638462SApril.Chin@Sun.COM lexp->sh->heredocs = sftmp(HERE_MEM);
7648462SApril.Chin@Sun.COM lexp->sh->funlog = lexp->sh->heredocs;
7654887Schin t->funct.functtyp |= FPIN;
7664887Schin }
7674887Schin }
7688462SApril.Chin@Sun.COM t->funct.functnam= (char*)lexp->arg->argval;
7694887Schin #if SHOPT_KIA
7708462SApril.Chin@Sun.COM if(lexp->kiafile)
7718462SApril.Chin@Sun.COM lexp->current = kiaentity(lexp,t->funct.functnam,-1,'p',-1,-1,lexp->script,'p',0,"");
7724887Schin #endif /* SHOPT_KIA */
7734887Schin if(flag)
7744887Schin {
7758462SApril.Chin@Sun.COM lexp->token = sh_lex(lexp);
7764887Schin #if SHOPT_BASH
7778462SApril.Chin@Sun.COM if(lexp->token == LPAREN)
7784887Schin {
7798462SApril.Chin@Sun.COM if((lexp->token = sh_lex(lexp)) == RPAREN)
7804887Schin t->funct.functtyp |= FPOSIX;
7814887Schin else
7828462SApril.Chin@Sun.COM sh_syntax(lexp);
7834887Schin }
7844887Schin #endif
7854887Schin }
7864887Schin if(t->funct.functtyp&FPOSIX)
7878462SApril.Chin@Sun.COM skipnl(lexp,0);
7884887Schin else
7894887Schin {
7908462SApril.Chin@Sun.COM if(lexp->token==0)
7918462SApril.Chin@Sun.COM t->funct.functargs = (struct comnod*)simple(lexp,SH_NOIO|SH_FUNDEF,NIL(struct ionod*));
7928462SApril.Chin@Sun.COM while(lexp->token==NL)
7938462SApril.Chin@Sun.COM lexp->token = sh_lex(lexp);
7944887Schin }
7958462SApril.Chin@Sun.COM if((flag && lexp->token!=LBRACE) || lexp->token==EOFSYM)
7968462SApril.Chin@Sun.COM sh_syntax(lexp);
7974887Schin sh_pushcontext(&buff,1);
7984887Schin jmpval = sigsetjmp(buff.buff,0);
7994887Schin if(jmpval == 0)
8004887Schin {
8014887Schin /* create a new stak frame to compile the command */
8024887Schin savstak = stakcreate(STAK_SMALL);
8034887Schin savstak = stakinstall(savstak, 0);
8044887Schin slp = (struct slnod*)stakalloc(sizeof(struct slnod)+sizeof(struct functnod));
8054887Schin slp->slchild = 0;
8068462SApril.Chin@Sun.COM slp->slnext = shp->st.staklist;
8078462SApril.Chin@Sun.COM shp->st.staklist = 0;
8084887Schin t->funct.functstak = (struct slnod*)slp;
8094887Schin /*
8104887Schin * store the pathname of function definition file on stack
8114887Schin * in name field of fake for node
8124887Schin */
8134887Schin fp = (struct functnod*)(slp+1);
8144887Schin fp->functtyp = TFUN|FAMP;
8154887Schin fp->functnam = 0;
8164887Schin fp->functline = t->funct.functline;
8178462SApril.Chin@Sun.COM if(shp->st.filename)
8188462SApril.Chin@Sun.COM fp->functnam = stakcopy(shp->st.filename);
8194887Schin loop_level = 0;
8204887Schin label_last = label_list;
8218462SApril.Chin@Sun.COM if(!flag && lexp->token==0)
8224887Schin {
8234887Schin /* copy current word token to current stak frame */
8244887Schin struct argnod *ap;
8258462SApril.Chin@Sun.COM flag = ARGVAL + strlen(lexp->arg->argval);
8264887Schin ap = (struct argnod*)stakalloc(flag);
8278462SApril.Chin@Sun.COM memcpy(ap,lexp->arg,flag);
8288462SApril.Chin@Sun.COM lexp->arg = ap;
8294887Schin }
8308462SApril.Chin@Sun.COM t->funct.functtre = item(lexp,SH_NOIO);
8314887Schin }
832*12068SRoger.Faulkner@Oracle.COM else if(shp->shcomp)
833*12068SRoger.Faulkner@Oracle.COM exit(1);
8344887Schin sh_popcontext(&buff);
8354887Schin loop_level = saveloop;
8364887Schin label_last = savelabel;
8374887Schin /* restore the old stack */
8384887Schin if(slp)
8394887Schin {
8404887Schin slp->slptr = stakinstall(savstak,0);
8418462SApril.Chin@Sun.COM slp->slchild = shp->st.staklist;
8424887Schin }
8434887Schin #if SHOPT_KIA
8448462SApril.Chin@Sun.COM lexp->current = current;
8454887Schin #endif /* SHOPT_KIA */
8464887Schin if(jmpval)
8474887Schin {
8484887Schin if(slp && slp->slptr)
8494887Schin {
8508462SApril.Chin@Sun.COM shp->st.staklist = slp->slnext;
8514887Schin stakdelete(slp->slptr);
8524887Schin }
8538462SApril.Chin@Sun.COM siglongjmp(*shp->jmplist,jmpval);
8544887Schin }
8558462SApril.Chin@Sun.COM shp->st.staklist = (struct slnod*)slp;
8564887Schin last = fctell();
8574887Schin fp->functline = (last-first);
8584887Schin fp->functtre = t;
8598462SApril.Chin@Sun.COM shp->mktype = in_mktype;
8608462SApril.Chin@Sun.COM if(lexp->sh->funlog)
8614887Schin {
8624887Schin if(fcfill()>0)
8634887Schin fcseek(-1);
8648462SApril.Chin@Sun.COM lexp->sh->funlog = 0;
8654887Schin }
8664887Schin #if SHOPT_KIA
8678462SApril.Chin@Sun.COM if(lexp->kiafile)
8688462SApril.Chin@Sun.COM kiaentity(lexp,t->funct.functnam,-1,'p',t->funct.functline,shp->inlineno-1,lexp->current,'p',0,"");
8694887Schin #endif /* SHOPT_KIA */
8708462SApril.Chin@Sun.COM t->funct.functtyp |= opt_get;
8718462SApril.Chin@Sun.COM opt_get = save_optget;
8724887Schin return(t);
8734887Schin }
8744887Schin
8754887Schin /*
8764887Schin * Compound assignment
8774887Schin */
assign(Lex_t * lexp,register struct argnod * ap,int tdef)8788462SApril.Chin@Sun.COM static struct argnod *assign(Lex_t *lexp, register struct argnod *ap, int tdef)
8794887Schin {
8804887Schin register int n;
8814887Schin register Shnode_t *t, **tp;
8824887Schin register struct comnod *ac;
8838462SApril.Chin@Sun.COM Stk_t *stkp = lexp->sh->stk;
8844887Schin int array=0;
8854887Schin Namval_t *np;
8864887Schin n = strlen(ap->argval)-1;
8874887Schin if(ap->argval[n]!='=')
8888462SApril.Chin@Sun.COM sh_syntax(lexp);
8894887Schin if(ap->argval[n-1]=='+')
8904887Schin {
8914887Schin ap->argval[n--]=0;
8924887Schin array = ARG_APPEND;
8934887Schin }
8944887Schin /* shift right */
8954887Schin while(n > 0)
8964887Schin {
8974887Schin ap->argval[n] = ap->argval[n-1];
8984887Schin n--;
8994887Schin }
9004887Schin *ap->argval=0;
9014887Schin t = getnode(fornod);
9024887Schin t->for_.fornam = (char*)(ap->argval+1);
9038462SApril.Chin@Sun.COM t->for_.fortyp = sh_getlineno(lexp);
9044887Schin tp = &t->for_.fortre;
9054887Schin ap->argchn.ap = (struct argnod*)t;
9064887Schin ap->argflag &= ARG_QUOTED;
9074887Schin ap->argflag |= array;
9088462SApril.Chin@Sun.COM lexp->assignok = SH_ASSIGN;
9098462SApril.Chin@Sun.COM lexp->aliasok = 1;
9104887Schin array=0;
9118462SApril.Chin@Sun.COM if((n=skipnl(lexp,0))==RPAREN || n==LPAREN)
9124887Schin {
9134887Schin int index= 0;
9144887Schin struct argnod **settail;
9154887Schin ac = (struct comnod*)getnode(comnod);
9164887Schin settail= &ac->comset;
9174887Schin memset((void*)ac,0,sizeof(*ac));
9188462SApril.Chin@Sun.COM ac->comline = sh_getlineno(lexp);
9194887Schin while(n==LPAREN)
9204887Schin {
9214887Schin struct argnod *ap;
9228462SApril.Chin@Sun.COM ap = (struct argnod*)stkseek(stkp,ARGVAL);
9234887Schin ap->argflag= ARG_ASSIGN;
9248462SApril.Chin@Sun.COM sfprintf(stkp,"[%d]=",index++);
9258462SApril.Chin@Sun.COM ap = (struct argnod*)stkfreeze(stkp,1);
9264887Schin ap->argnxt.ap = 0;
9278462SApril.Chin@Sun.COM ap = assign(lexp,ap,0);
9284887Schin ap->argflag |= ARG_MESSAGE;
9294887Schin *settail = ap;
9304887Schin settail = &(ap->argnxt.ap);
9318462SApril.Chin@Sun.COM while((n = skipnl(lexp,0))==0)
9328462SApril.Chin@Sun.COM {
9338462SApril.Chin@Sun.COM ap = (struct argnod*)stkseek(stkp,ARGVAL);
9348462SApril.Chin@Sun.COM ap->argflag= ARG_ASSIGN;
9358462SApril.Chin@Sun.COM sfprintf(stkp,"[%d]=",index++);
9368462SApril.Chin@Sun.COM stakputs(lexp->arg->argval);
9378462SApril.Chin@Sun.COM ap = (struct argnod*)stkfreeze(stkp,1);
9388462SApril.Chin@Sun.COM ap->argnxt.ap = 0;
9398462SApril.Chin@Sun.COM ap->argflag = lexp->arg->argflag;
9408462SApril.Chin@Sun.COM *settail = ap;
9418462SApril.Chin@Sun.COM settail = &(ap->argnxt.ap);
9428462SApril.Chin@Sun.COM }
9434887Schin }
9444887Schin }
9458462SApril.Chin@Sun.COM else if(n && n!=FUNCTSYM)
9468462SApril.Chin@Sun.COM sh_syntax(lexp);
9478462SApril.Chin@Sun.COM else 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)))
9488462SApril.Chin@Sun.COM {
9494887Schin array=SH_ARRAY;
9508462SApril.Chin@Sun.COM if(fcgetc(n)==LPAREN)
9518462SApril.Chin@Sun.COM {
9528462SApril.Chin@Sun.COM int c;
9538462SApril.Chin@Sun.COM if(fcgetc(c)==RPAREN)
9548462SApril.Chin@Sun.COM {
9558462SApril.Chin@Sun.COM lexp->token = SYMRES;
9568462SApril.Chin@Sun.COM array = 0;
9578462SApril.Chin@Sun.COM }
9588462SApril.Chin@Sun.COM else
9598462SApril.Chin@Sun.COM fcseek(-2);
9608462SApril.Chin@Sun.COM }
9618462SApril.Chin@Sun.COM else if(n>0)
9628462SApril.Chin@Sun.COM fcseek(-1);
9638462SApril.Chin@Sun.COM if(array && tdef)
9648462SApril.Chin@Sun.COM sh_syntax(lexp);
9658462SApril.Chin@Sun.COM }
9664887Schin while(1)
9674887Schin {
9688462SApril.Chin@Sun.COM if((n=lexp->token)==RPAREN)
9694887Schin break;
9704887Schin if(n==FUNCTSYM || n==SYMRES)
9718462SApril.Chin@Sun.COM ac = (struct comnod*)funct(lexp);
9724887Schin else
9738462SApril.Chin@Sun.COM ac = (struct comnod*)simple(lexp,SH_NOIO|SH_ASSIGN|array,NIL(struct ionod*));
9748462SApril.Chin@Sun.COM if((n=lexp->token)==RPAREN)
9754887Schin break;
9764887Schin if(n!=NL && n!=';')
9778462SApril.Chin@Sun.COM sh_syntax(lexp);
9788462SApril.Chin@Sun.COM lexp->assignok = SH_ASSIGN;
9798462SApril.Chin@Sun.COM if((n=skipnl(lexp,0)) || array)
9804887Schin {
9814887Schin if(n==RPAREN)
9824887Schin break;
9834887Schin if(array || n!=FUNCTSYM)
9848462SApril.Chin@Sun.COM sh_syntax(lexp);
9854887Schin }
9868462SApril.Chin@Sun.COM 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)))
9874887Schin {
9888462SApril.Chin@Sun.COM struct argnod *arg = lexp->arg;
9894887Schin if(n!=0)
9908462SApril.Chin@Sun.COM sh_syntax(lexp);
9914887Schin /* check for sys5 style function */
9928462SApril.Chin@Sun.COM if(sh_lex(lexp)!=LPAREN || sh_lex(lexp)!=RPAREN)
9934887Schin {
9948462SApril.Chin@Sun.COM lexp->arg = arg;
9958462SApril.Chin@Sun.COM lexp->token = 0;
9968462SApril.Chin@Sun.COM sh_syntax(lexp);
9974887Schin }
9988462SApril.Chin@Sun.COM lexp->arg = arg;
9998462SApril.Chin@Sun.COM lexp->token = SYMRES;
10004887Schin }
10018462SApril.Chin@Sun.COM t = makelist(lexp,TLST,(Shnode_t*)ac,t);
10024887Schin *tp = t;
10034887Schin tp = &t->lst.lstrit;
10044887Schin }
10054887Schin *tp = (Shnode_t*)ac;
10068462SApril.Chin@Sun.COM lexp->assignok = 0;
10074887Schin return(ap);
10084887Schin }
10094887Schin
10104887Schin /*
10114887Schin * item
10124887Schin *
10134887Schin * ( cmd ) [ < in ] [ > out ]
10144887Schin * word word* [ < in ] [ > out ]
10154887Schin * if ... then ... else ... fi
10164887Schin * for ... while ... do ... done
10174887Schin * case ... in ... esac
10184887Schin * begin ... end
10194887Schin */
10204887Schin
item(Lex_t * lexp,int flag)10218462SApril.Chin@Sun.COM static Shnode_t *item(Lex_t *lexp,int flag)
10224887Schin {
10234887Schin register Shnode_t *t;
10244887Schin register struct ionod *io;
10258462SApril.Chin@Sun.COM register int tok = (lexp->token&0xff);
10268462SApril.Chin@Sun.COM int savwdval = lexp->lasttok;
10278462SApril.Chin@Sun.COM int savline = lexp->lastline;
10288462SApril.Chin@Sun.COM int showme=0, comsub;
10298462SApril.Chin@Sun.COM if(!(flag&SH_NOIO) && (tok=='<' || tok=='>' || lexp->token==IOVNAME))
10308462SApril.Chin@Sun.COM io=inout(lexp,NIL(struct ionod*),1);
10314887Schin else
10324887Schin io=0;
10338462SApril.Chin@Sun.COM if((tok=lexp->token) && tok!=EOFSYM && tok!=FUNCTSYM)
10344887Schin {
10358462SApril.Chin@Sun.COM lexp->lastline = sh_getlineno(lexp);
10368462SApril.Chin@Sun.COM lexp->lasttok = lexp->token;
10374887Schin }
10384887Schin switch(tok)
10394887Schin {
10404887Schin /* [[ ... ]] test expression */
10414887Schin case BTESTSYM:
10428462SApril.Chin@Sun.COM t = test_expr(lexp,ETESTSYM);
10434887Schin t->tre.tretyp &= ~TTEST;
10444887Schin break;
10454887Schin /* ((...)) arithmetic expression */
10464887Schin case EXPRSYM:
10478462SApril.Chin@Sun.COM t = getanode(lexp,lexp->arg);
10488462SApril.Chin@Sun.COM sh_lex(lexp);
10494887Schin goto done;
10504887Schin
10514887Schin /* case statement */
10524887Schin case CASESYM:
10534887Schin {
10548462SApril.Chin@Sun.COM int savetok = lexp->lasttok;
10558462SApril.Chin@Sun.COM int saveline = lexp->lastline;
10564887Schin t = getnode(swnod);
10578462SApril.Chin@Sun.COM if(sh_lex(lexp))
10588462SApril.Chin@Sun.COM sh_syntax(lexp);
10598462SApril.Chin@Sun.COM t->sw.swarg=lexp->arg;
10604887Schin t->sw.swtyp=TSW;
10614887Schin t->sw.swio = 0;
10624887Schin t->sw.swtyp |= FLINENO;
10638462SApril.Chin@Sun.COM t->sw.swline = lexp->sh->inlineno;
10648462SApril.Chin@Sun.COM if((tok=skipnl(lexp,0))!=INSYM && tok!=LBRACE)
10658462SApril.Chin@Sun.COM sh_syntax(lexp);
10668462SApril.Chin@Sun.COM if(!(t->sw.swlst=syncase(lexp,tok==INSYM?ESACSYM:RBRACE)) && lexp->token==EOFSYM)
10674887Schin {
10688462SApril.Chin@Sun.COM lexp->lasttok = savetok;
10698462SApril.Chin@Sun.COM lexp->lastline = saveline;
10708462SApril.Chin@Sun.COM sh_syntax(lexp);
10714887Schin }
10724887Schin break;
10734887Schin }
10744887Schin
10754887Schin /* if statement */
10764887Schin case IFSYM:
10774887Schin {
10784887Schin register Shnode_t *tt;
10794887Schin t = getnode(ifnod);
10804887Schin t->if_.iftyp=TIF;
10818462SApril.Chin@Sun.COM t->if_.iftre=sh_cmd(lexp,THENSYM,SH_NL);
10828462SApril.Chin@Sun.COM t->if_.thtre=sh_cmd(lexp,ELSESYM,SH_NL|SH_SEMI);
10838462SApril.Chin@Sun.COM tok = lexp->token;
10848462SApril.Chin@Sun.COM t->if_.eltre=(tok==ELSESYM?sh_cmd(lexp,FISYM,SH_NL|SH_SEMI):
10858462SApril.Chin@Sun.COM (tok==ELIFSYM?(lexp->token=IFSYM, tt=item(lexp,SH_NOIO)):0));
10864887Schin if(tok==ELIFSYM)
10874887Schin {
10884887Schin if(!tt || tt->tre.tretyp!=TSETIO)
10894887Schin goto done;
10904887Schin t->if_.eltre = tt->fork.forktre;
10914887Schin tt->fork.forktre = t;
10924887Schin t = tt;
10934887Schin goto done;
10944887Schin }
10954887Schin break;
10964887Schin }
10974887Schin
10984887Schin /* for and select statement */
10994887Schin case FORSYM:
11004887Schin case SELECTSYM:
11014887Schin {
11024887Schin t = getnode(fornod);
11038462SApril.Chin@Sun.COM t->for_.fortyp=(lexp->token==FORSYM?TFOR:TSELECT);
11044887Schin t->for_.forlst=0;
11058462SApril.Chin@Sun.COM t->for_.forline = lexp->sh->inlineno;
11068462SApril.Chin@Sun.COM if(sh_lex(lexp))
11074887Schin {
11088462SApril.Chin@Sun.COM if(lexp->token!=EXPRSYM || t->for_.fortyp!=TFOR)
11098462SApril.Chin@Sun.COM sh_syntax(lexp);
11104887Schin /* arithmetic for */
11118462SApril.Chin@Sun.COM t = arithfor(lexp,t);
11124887Schin break;
11134887Schin }
11148462SApril.Chin@Sun.COM t->for_.fornam=(char*) lexp->arg->argval;
11154887Schin t->for_.fortyp |= FLINENO;
11164887Schin #if SHOPT_KIA
11178462SApril.Chin@Sun.COM if(lexp->kiafile)
11188462SApril.Chin@Sun.COM writedefs(lexp,lexp->arg,lexp->sh->inlineno,'v',NIL(struct argnod*));
11194887Schin #endif /* SHOPT_KIA */
11208462SApril.Chin@Sun.COM while((tok=sh_lex(lexp))==NL);
11214887Schin if(tok==INSYM)
11224887Schin {
11238462SApril.Chin@Sun.COM if(sh_lex(lexp))
11244887Schin {
11258462SApril.Chin@Sun.COM if(lexp->token != NL && lexp->token !=';')
11268462SApril.Chin@Sun.COM sh_syntax(lexp);
11274887Schin /* some Linux scripts assume this */
11284887Schin if(sh_isoption(SH_NOEXEC))
11298462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_warn(0),e_lexemptyfor,lexp->sh->inlineno-(lexp->token=='\n'));
11304887Schin t->for_.forlst = (struct comnod*)getnode(comnod);
11314887Schin (t->for_.forlst)->comarg = 0;
11324887Schin (t->for_.forlst)->comset = 0;
11334887Schin (t->for_.forlst)->comnamp = 0;
11344887Schin (t->for_.forlst)->comnamq = 0;
11354887Schin (t->for_.forlst)->comstate = 0;
11364887Schin (t->for_.forlst)->comio = 0;
11374887Schin (t->for_.forlst)->comtyp = 0;
11384887Schin }
11394887Schin else
11408462SApril.Chin@Sun.COM t->for_.forlst=(struct comnod*)simple(lexp,SH_NOIO,NIL(struct ionod*));
11418462SApril.Chin@Sun.COM if(lexp->token != NL && lexp->token !=';')
11428462SApril.Chin@Sun.COM sh_syntax(lexp);
11438462SApril.Chin@Sun.COM tok = skipnl(lexp,0);
11444887Schin }
11454887Schin /* 'for i;do cmd' is valid syntax */
11464887Schin else if(tok==';')
11478462SApril.Chin@Sun.COM tok=sh_lex(lexp);
11484887Schin if(tok!=DOSYM && tok!=LBRACE)
11498462SApril.Chin@Sun.COM sh_syntax(lexp);
11504887Schin loop_level++;
11518462SApril.Chin@Sun.COM t->for_.fortre=sh_cmd(lexp,tok==DOSYM?DONESYM:RBRACE,SH_NL|SH_SEMI);
11524887Schin if(--loop_level==0)
11534887Schin label_last = label_list;
11544887Schin break;
11554887Schin }
11564887Schin
11574887Schin /* This is the code for parsing function definitions */
11584887Schin case FUNCTSYM:
11598462SApril.Chin@Sun.COM return(funct(lexp));
11604887Schin
11614887Schin #if SHOPT_NAMESPACE
11624887Schin case NSPACESYM:
11634887Schin t = getnode(fornod);
11644887Schin t->for_.fortyp=TNSPACE;
11654887Schin t->for_.forlst=0;
11668462SApril.Chin@Sun.COM if(sh_lex(lexp))
11678462SApril.Chin@Sun.COM sh_syntax(lexp);
11688462SApril.Chin@Sun.COM t->for_.fornam=(char*) lexp->arg->argval;
11698462SApril.Chin@Sun.COM while((tok=sh_lex(lexp))==NL);
11704887Schin if(tok!=LBRACE)
11718462SApril.Chin@Sun.COM sh_syntax(lexp);
11728462SApril.Chin@Sun.COM t->for_.fortre = sh_cmd(lexp,RBRACE,SH_NL);
11734887Schin break;
11744887Schin #endif /* SHOPT_NAMESPACE */
11754887Schin
11764887Schin /* while and until */
11774887Schin case WHILESYM:
11784887Schin case UNTILSYM:
11794887Schin t = getnode(whnod);
11808462SApril.Chin@Sun.COM t->wh.whtyp=(lexp->token==WHILESYM ? TWH : TUN);
11814887Schin loop_level++;
11828462SApril.Chin@Sun.COM t->wh.whtre = sh_cmd(lexp,DOSYM,SH_NL);
11838462SApril.Chin@Sun.COM t->wh.dotre = sh_cmd(lexp,DONESYM,SH_NL|SH_SEMI);
11844887Schin if(--loop_level==0)
11854887Schin label_last = label_list;
11864887Schin t->wh.whinc = 0;
11874887Schin break;
11884887Schin
11894887Schin case LABLSYM:
11904887Schin {
11914887Schin register struct argnod *argp = label_list;
11924887Schin while(argp)
11934887Schin {
11948462SApril.Chin@Sun.COM if(strcmp(argp->argval,lexp->arg->argval)==0)
11958462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax3,lexp->sh->inlineno,argp->argval);
11964887Schin argp = argp->argnxt.ap;
11974887Schin }
11988462SApril.Chin@Sun.COM lexp->arg->argnxt.ap = label_list;
11998462SApril.Chin@Sun.COM label_list = lexp->arg;
12008462SApril.Chin@Sun.COM label_list->argchn.len = sh_getlineno(lexp);
12014887Schin label_list->argflag = loop_level;
12028462SApril.Chin@Sun.COM skipnl(lexp,flag);
12038462SApril.Chin@Sun.COM if(!(t = item(lexp,SH_NL)))
12048462SApril.Chin@Sun.COM sh_syntax(lexp);
12054887Schin tok = (t->tre.tretyp&(COMSCAN|COMSCAN-1));
12064887Schin if(sh_isoption(SH_NOEXEC) && tok!=TWH && tok!=TUN && tok!=TFOR && tok!=TSELECT)
12074887Schin errormsg(SH_DICT,ERROR_warn(0),e_lexlabignore,label_list->argchn.len,label_list->argval);
12084887Schin return(t);
12094887Schin }
12104887Schin
12114887Schin /* command group with {...} */
12124887Schin case LBRACE:
12138462SApril.Chin@Sun.COM comsub = lexp->comsub;
12148462SApril.Chin@Sun.COM lexp->comsub = 0;
121510898Sroland.mainz@nrubsig.org t = sh_cmd(lexp,RBRACE,SH_NL|SH_SEMI);
12168462SApril.Chin@Sun.COM lexp->comsub = comsub;
12174887Schin break;
12184887Schin
12194887Schin case LPAREN:
12204887Schin t = getnode(parnod);
122110898Sroland.mainz@nrubsig.org t->par.partre=sh_cmd(lexp,RPAREN,SH_NL|SH_SEMI);
12224887Schin t->par.partyp=TPAR;
12234887Schin break;
12244887Schin
12254887Schin default:
12264887Schin if(io==0)
12274887Schin return(0);
12284887Schin
12294887Schin case ';':
12304887Schin if(io==0)
12314887Schin {
12324887Schin if(!(flag&SH_SEMI))
12334887Schin return(0);
12348462SApril.Chin@Sun.COM if(sh_lex(lexp)==';')
12358462SApril.Chin@Sun.COM sh_syntax(lexp);
12364887Schin showme = FSHOWME;
12374887Schin }
12384887Schin /* simple command */
12394887Schin case 0:
12408462SApril.Chin@Sun.COM t = (Shnode_t*)simple(lexp,flag,io);
12418462SApril.Chin@Sun.COM if(t->com.comarg && lexp->intypeset && (lexp->sh->shcomp || sh_isoption(SH_NOEXEC) || sh.dot_depth))
12428462SApril.Chin@Sun.COM check_typedef(&t->com);
12438462SApril.Chin@Sun.COM lexp->intypeset = 0;
12448462SApril.Chin@Sun.COM lexp->inexec = 0;
12454887Schin t->tre.tretyp |= showme;
12464887Schin return(t);
12474887Schin }
12488462SApril.Chin@Sun.COM sh_lex(lexp);
12498462SApril.Chin@Sun.COM if(io=inout(lexp,io,0))
12504887Schin {
12514887Schin if((tok=t->tre.tretyp&COMMSK) != TFORK)
12524887Schin tok = TSETIO;
12538462SApril.Chin@Sun.COM t=makeparent(lexp,tok,t);
12544887Schin t->tre.treio=io;
12554887Schin }
12564887Schin done:
12578462SApril.Chin@Sun.COM lexp->lasttok = savwdval;
12588462SApril.Chin@Sun.COM lexp->lastline = savline;
12594887Schin return(t);
12604887Schin }
12614887Schin
process_sub(Lex_t * lexp,int tok)126210898Sroland.mainz@nrubsig.org static struct argnod *process_sub(Lex_t *lexp,int tok)
126310898Sroland.mainz@nrubsig.org {
126410898Sroland.mainz@nrubsig.org struct argnod *argp;
126510898Sroland.mainz@nrubsig.org Shnode_t *t;
126610898Sroland.mainz@nrubsig.org int mode = (tok==OPROCSYM);
126710898Sroland.mainz@nrubsig.org t = sh_cmd(lexp,RPAREN,SH_NL);
126810898Sroland.mainz@nrubsig.org argp = (struct argnod*)stkalloc(lexp->sh->stk,sizeof(struct argnod));
126910898Sroland.mainz@nrubsig.org *argp->argval = 0;
127010898Sroland.mainz@nrubsig.org argp->argchn.ap = (struct argnod*)makeparent(lexp,mode?TFORK|FPIN|FAMP|FPCL:TFORK|FPOU,t);
127110898Sroland.mainz@nrubsig.org argp->argflag = (ARG_EXP|mode);
127210898Sroland.mainz@nrubsig.org return(argp);
127310898Sroland.mainz@nrubsig.org }
127410898Sroland.mainz@nrubsig.org
127510898Sroland.mainz@nrubsig.org
12764887Schin /*
12774887Schin * This is for a simple command, for list, or compound assignment
12784887Schin */
simple(Lex_t * lexp,int flag,struct ionod * io)12798462SApril.Chin@Sun.COM static Shnode_t *simple(Lex_t *lexp,int flag, struct ionod *io)
12804887Schin {
12814887Schin register struct comnod *t;
12824887Schin register struct argnod *argp;
12834887Schin register int tok;
12848462SApril.Chin@Sun.COM Stk_t *stkp = lexp->sh->stk;
12854887Schin struct argnod **argtail;
12864887Schin struct argnod **settail;
12878462SApril.Chin@Sun.COM int cmdarg=0;
12888462SApril.Chin@Sun.COM int argno = 0, argmax=0;
12894887Schin int assignment = 0;
12904887Schin int key_on = (!(flag&SH_NOIO) && sh_isoption(SH_KEYWORD));
12914887Schin int associative=0;
12928462SApril.Chin@Sun.COM if((argp=lexp->arg) && (argp->argflag&ARG_ASSIGN) && argp->argval[0]=='[')
12934887Schin {
12944887Schin flag |= SH_ARRAY;
12954887Schin associative = 1;
12964887Schin }
12974887Schin t = (struct comnod*)getnode(comnod);
12984887Schin t->comio=io; /*initial io chain*/
12994887Schin /* set command line number for error messages */
13008462SApril.Chin@Sun.COM t->comline = sh_getlineno(lexp);
13014887Schin argtail = &(t->comarg);
13024887Schin t->comset = 0;
13034887Schin t->comnamp = 0;
13044887Schin t->comnamq = 0;
13054887Schin t->comstate = 0;
13064887Schin settail = &(t->comset);
13078462SApril.Chin@Sun.COM while(lexp->token==0)
13084887Schin {
13098462SApril.Chin@Sun.COM argp = lexp->arg;
13104887Schin if(*argp->argval==LBRACE && (flag&SH_FUNDEF) && argp->argval[1]==0)
13114887Schin {
13128462SApril.Chin@Sun.COM lexp->token = LBRACE;
13134887Schin break;
13144887Schin }
13154887Schin if(associative && argp->argval[0]!='[')
13168462SApril.Chin@Sun.COM sh_syntax(lexp);
13174887Schin /* check for assignment argument */
13184887Schin if((argp->argflag&ARG_ASSIGN) && assignment!=2)
13194887Schin {
13204887Schin *settail = argp;
13214887Schin settail = &(argp->argnxt.ap);
13228462SApril.Chin@Sun.COM lexp->assignok = (flag&SH_ASSIGN)?SH_ASSIGN:1;
13234887Schin if(assignment)
13244887Schin {
13254887Schin struct argnod *ap=argp;
13264887Schin char *last, *cp;
13274887Schin if(assignment==1)
13284887Schin {
13294887Schin last = strchr(argp->argval,'=');
133010898Sroland.mainz@nrubsig.org if(last && (last[-1]==']'|| (last[-1]=='+' && last[-2]==']')) && (cp=strchr(argp->argval,'[')) && (cp < last))
13314887Schin last = cp;
13328462SApril.Chin@Sun.COM stkseek(stkp,ARGVAL);
13338462SApril.Chin@Sun.COM sfwrite(stkp,argp->argval,last-argp->argval);
13348462SApril.Chin@Sun.COM ap=(struct argnod*)stkfreeze(stkp,1);
13354887Schin ap->argflag = ARG_RAW;
13364887Schin ap->argchn.ap = 0;
13374887Schin }
13384887Schin *argtail = ap;
13394887Schin argtail = &(ap->argnxt.ap);
13404887Schin if(argno>=0)
13414887Schin argno++;
13424887Schin }
13434887Schin else /* alias substitutions allowed */
13448462SApril.Chin@Sun.COM lexp->aliasok = 1;
13454887Schin }
13464887Schin else
13474887Schin {
13484887Schin if(!(argp->argflag&ARG_RAW))
13498462SApril.Chin@Sun.COM {
13508462SApril.Chin@Sun.COM if(argno>0)
13518462SApril.Chin@Sun.COM argmax = argno;
13524887Schin argno = -1;
13538462SApril.Chin@Sun.COM }
13548462SApril.Chin@Sun.COM if(argno>=0 && argno++==cmdarg && !(flag&SH_ARRAY) && *argp->argval!='/')
13554887Schin {
13564887Schin /* check for builtin command */
13578462SApril.Chin@Sun.COM Namval_t *np=nv_bfsearch(argp->argval,lexp->sh->fun_tree, (Namval_t**)&t->comnamq,(char**)0);
13588462SApril.Chin@Sun.COM if(cmdarg==0)
13598462SApril.Chin@Sun.COM t->comnamp = (void*)np;
13608462SApril.Chin@Sun.COM if(np && is_abuiltin(np))
13614887Schin {
13628462SApril.Chin@Sun.COM if(nv_isattr(np,BLT_DCL))
13638462SApril.Chin@Sun.COM {
13648462SApril.Chin@Sun.COM assignment = 1+(*argp->argval=='a');
13658462SApril.Chin@Sun.COM if(np==SYSTYPESET)
13668462SApril.Chin@Sun.COM lexp->intypeset = 1;
13678462SApril.Chin@Sun.COM key_on = 1;
13688462SApril.Chin@Sun.COM }
13698462SApril.Chin@Sun.COM else if(np==SYSCOMMAND)
13708462SApril.Chin@Sun.COM cmdarg++;
13718462SApril.Chin@Sun.COM else if(np==SYSEXEC)
13728462SApril.Chin@Sun.COM lexp->inexec = 1;
13738462SApril.Chin@Sun.COM else if(np->nvalue.bfp==b_getopts)
13748462SApril.Chin@Sun.COM opt_get |= FOPTGET;
13754887Schin }
13764887Schin }
13774887Schin *argtail = argp;
13784887Schin argtail = &(argp->argnxt.ap);
13798462SApril.Chin@Sun.COM if(!(lexp->assignok=key_on) && !(flag&SH_NOIO) && sh_isoption(SH_NOEXEC))
13808462SApril.Chin@Sun.COM lexp->assignok = SH_COMPASSIGN;
13818462SApril.Chin@Sun.COM lexp->aliasok = 0;
13824887Schin }
13834887Schin retry:
13848462SApril.Chin@Sun.COM tok = sh_lex(lexp);
13858462SApril.Chin@Sun.COM if(tok==LABLSYM && (flag&SH_ASSIGN))
13868462SApril.Chin@Sun.COM lexp->token = tok = 0;
13874887Schin #if SHOPT_DEVFD
13884887Schin if((tok==IPROCSYM || tok==OPROCSYM))
13894887Schin {
139010898Sroland.mainz@nrubsig.org argp = process_sub(lexp,tok);
13918462SApril.Chin@Sun.COM argmax = 0;
13924887Schin argno = -1;
13934887Schin *argtail = argp;
13944887Schin argtail = &(argp->argnxt.ap);
13954887Schin goto retry;
13964887Schin }
13974887Schin #endif /* SHOPT_DEVFD */
13984887Schin if(tok==LPAREN)
13994887Schin {
14004887Schin if(argp->argflag&ARG_ASSIGN)
14014887Schin {
14028462SApril.Chin@Sun.COM int intypeset = lexp->intypeset;
14038462SApril.Chin@Sun.COM int tdef = 0;
14048462SApril.Chin@Sun.COM lexp->intypeset = 0;
14058462SApril.Chin@Sun.COM if(t->comnamp==SYSTYPESET && t->comarg->argnxt.ap && strcmp(t->comarg->argnxt.ap->argval,"-T")==0)
14068462SApril.Chin@Sun.COM tdef = 1;
14078462SApril.Chin@Sun.COM argp = assign(lexp,argp,tdef);
14088462SApril.Chin@Sun.COM lexp->intypeset = intypeset;
14094887Schin if(associative)
14108462SApril.Chin@Sun.COM lexp->assignok |= SH_ASSIGN;
14114887Schin goto retry;
14124887Schin }
14134887Schin else if(argno==1 && !t->comset)
14144887Schin {
14154887Schin /* SVR2 style function */
14168462SApril.Chin@Sun.COM if(sh_lex(lexp) == RPAREN)
14174887Schin {
14188462SApril.Chin@Sun.COM lexp->arg = argp;
14198462SApril.Chin@Sun.COM return(funct(lexp));
14204887Schin }
14218462SApril.Chin@Sun.COM lexp->token = LPAREN;
14224887Schin }
14234887Schin }
14244887Schin else if(flag&SH_ASSIGN)
14254887Schin {
14264887Schin if(tok==RPAREN)
14274887Schin break;
14284887Schin else if(tok==NL && (flag&SH_ARRAY))
14298462SApril.Chin@Sun.COM {
14308462SApril.Chin@Sun.COM lexp->comp_assign = 2;
14314887Schin goto retry;
14328462SApril.Chin@Sun.COM }
14338462SApril.Chin@Sun.COM
14344887Schin }
14354887Schin if(!(flag&SH_NOIO))
14364887Schin {
14374887Schin if(io)
14384887Schin {
14394887Schin while(io->ionxt)
14404887Schin io = io->ionxt;
14418462SApril.Chin@Sun.COM io->ionxt = inout(lexp,(struct ionod*)0,0);
14424887Schin }
14434887Schin else
14448462SApril.Chin@Sun.COM t->comio = io = inout(lexp,(struct ionod*)0,0);
14454887Schin }
14464887Schin }
14474887Schin *argtail = 0;
14488462SApril.Chin@Sun.COM if(argno>0)
14498462SApril.Chin@Sun.COM argmax = argno;
1450*12068SRoger.Faulkner@Oracle.COM t->comtyp = TCOM;
14514887Schin #if SHOPT_KIA
14528462SApril.Chin@Sun.COM if(lexp->kiafile && !(flag&SH_NOIO))
14534887Schin {
14544887Schin register Namval_t *np=(Namval_t*)t->comnamp;
14554887Schin unsigned long r=0;
14564887Schin int line = t->comline;
14574887Schin argp = t->comarg;
14584887Schin if(np)
14598462SApril.Chin@Sun.COM r = kiaentity(lexp,nv_name(np),-1,'p',-1,0,lexp->unknown,'b',0,"");
14604887Schin else if(argp)
14618462SApril.Chin@Sun.COM r = kiaentity(lexp,sh_argstr(argp),-1,'p',-1,0,lexp->unknown,'c',0,"");
14624887Schin if(r>0)
14638462SApril.Chin@Sun.COM sfprintf(lexp->kiatmp,"p;%..64d;p;%..64d;%d;%d;c;\n",lexp->current,r,line,line);
14644887Schin if(t->comset && argno==0)
14658462SApril.Chin@Sun.COM writedefs(lexp,t->comset,line,'v',t->comarg);
14664887Schin else if(np && nv_isattr(np,BLT_DCL))
14678462SApril.Chin@Sun.COM writedefs(lexp,argp,line,0,NIL(struct argnod*));
14684887Schin else if(argp && strcmp(argp->argval,"read")==0)
14698462SApril.Chin@Sun.COM writedefs(lexp,argp,line,0,NIL(struct argnod*));
14704887Schin #if 0
14714887Schin else if(argp && strcmp(argp->argval,"unset")==0)
14728462SApril.Chin@Sun.COM writedefs(lexp,argp,line,'u',NIL(struct argnod*));
14734887Schin #endif
14744887Schin else if(argp && *argp->argval=='.' && argp->argval[1]==0 && (argp=argp->argnxt.ap))
14754887Schin {
14768462SApril.Chin@Sun.COM r = kiaentity(lexp,sh_argstr(argp),-1,'p',0,0,lexp->script,'d',0,"");
14778462SApril.Chin@Sun.COM sfprintf(lexp->kiatmp,"p;%..64d;p;%..64d;%d;%d;d;\n",lexp->current,r,line,line);
14784887Schin }
14794887Schin }
14804887Schin #endif /* SHOPT_KIA */
14814887Schin if(t->comnamp && (argp=t->comarg->argnxt.ap))
14824887Schin {
14834887Schin Namval_t *np=(Namval_t*)t->comnamp;
14844887Schin if((np==SYSBREAK || np==SYSCONT) && (argp->argflag&ARG_RAW) && !isdigit(*argp->argval))
14854887Schin {
14864887Schin register char *cp = argp->argval;
14874887Schin /* convert break/continue labels to numbers */
14884887Schin tok = 0;
14894887Schin for(argp=label_list;argp!=label_last;argp=argp->argnxt.ap)
14904887Schin {
14914887Schin if(strcmp(cp,argp->argval))
14924887Schin continue;
14934887Schin tok = loop_level-argp->argflag;
14944887Schin if(tok>=1)
14954887Schin {
14964887Schin argp = t->comarg->argnxt.ap;
14974887Schin if(tok>9)
14984887Schin {
14994887Schin argp->argval[1] = '0'+tok%10;
15004887Schin argp->argval[2] = 0;
15014887Schin tok /= 10;
15024887Schin }
15034887Schin else
15044887Schin argp->argval[1] = 0;
15054887Schin *argp->argval = '0'+tok;
15064887Schin }
15074887Schin break;
15084887Schin }
15094887Schin if(sh_isoption(SH_NOEXEC) && tok==0)
15108462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_warn(0),e_lexlabunknown,lexp->sh->inlineno-(lexp->token=='\n'),cp);
15114887Schin }
15124887Schin else if(sh_isoption(SH_NOEXEC) && np==SYSSET && ((tok= *argp->argval)=='-'||tok=='+') &&
15134887Schin (argp->argval[1]==0||strchr(argp->argval,'k')))
15148462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete5,lexp->sh->inlineno-(lexp->token=='\n'),argp->argval);
15154887Schin }
15164887Schin /* expand argument list if possible */
15174887Schin if(argno>0)
15184887Schin t->comarg = qscan(t,argno);
15194887Schin else if(t->comarg)
15204887Schin t->comtyp |= COMSCAN;
15218462SApril.Chin@Sun.COM lexp->aliasok = 0;
15224887Schin return((Shnode_t*)t);
15234887Schin }
15244887Schin
15254887Schin /*
15264887Schin * skip past newlines but issue prompt if interactive
15274887Schin */
skipnl(Lex_t * lexp,int flag)15288462SApril.Chin@Sun.COM static int skipnl(Lex_t *lexp,int flag)
15294887Schin {
15304887Schin register int token;
15318462SApril.Chin@Sun.COM while((token=sh_lex(lexp))==NL);
15324887Schin if(token==';' && !(flag&SH_SEMI))
15338462SApril.Chin@Sun.COM sh_syntax(lexp);
15344887Schin return(token);
15354887Schin }
15364887Schin
15374887Schin /*
15384887Schin * check for and process and i/o redirections
15394887Schin * if flag>0 then an alias can be in the next word
15404887Schin * if flag<0 only one redirection will be processed
15414887Schin */
inout(Lex_t * lexp,struct ionod * lastio,int flag)15428462SApril.Chin@Sun.COM static struct ionod *inout(Lex_t *lexp,struct ionod *lastio,int flag)
15434887Schin {
15448462SApril.Chin@Sun.COM register int iof = lexp->digits, token=lexp->token;
15454887Schin register struct ionod *iop;
15468462SApril.Chin@Sun.COM Stk_t *stkp = lexp->sh->stk;
15474887Schin char *iovname=0;
15484887Schin register int errout=0;
15494887Schin if(token==IOVNAME)
15504887Schin {
15518462SApril.Chin@Sun.COM iovname=lexp->arg->argval+1;
15528462SApril.Chin@Sun.COM token= sh_lex(lexp);
15534887Schin iof = 0;
15544887Schin }
15554887Schin switch(token&0xff)
15564887Schin {
15574887Schin case '<':
15584887Schin if(token==IODOCSYM)
15594887Schin iof |= (IODOC|IORAW);
15604887Schin else if(token==IOMOV0SYM)
15614887Schin iof |= IOMOV;
156210898Sroland.mainz@nrubsig.org else if(token==IORDWRSYMT)
156310898Sroland.mainz@nrubsig.org iof |= IORDW|IOREWRITE;
15644887Schin else if(token==IORDWRSYM)
15654887Schin iof |= IORDW;
15664887Schin else if((token&SYMSHARP) == SYMSHARP)
15674887Schin {
15684887Schin int n;
15694887Schin iof |= IOLSEEK;
15704887Schin if(fcgetc(n)=='#')
15714887Schin iof |= IOCOPY;
15724887Schin else if(n>0)
15734887Schin fcseek(-1);
15744887Schin }
15754887Schin break;
15764887Schin
15774887Schin case '>':
15784887Schin if(iof<0)
15794887Schin {
15804887Schin errout = 1;
15814887Schin iof = 1;
15824887Schin }
15834887Schin iof |= IOPUT;
15844887Schin if(token==IOAPPSYM)
15854887Schin iof |= IOAPP;
15864887Schin else if(token==IOMOV1SYM)
15874887Schin iof |= IOMOV;
15884887Schin else if(token==IOCLOBSYM)
15894887Schin iof |= IOCLOB;
15904887Schin else if((token&SYMSHARP) == SYMSHARP)
15914887Schin iof |= IOLSEEK;
15928462SApril.Chin@Sun.COM else if((token&SYMSEMI) == SYMSEMI)
15938462SApril.Chin@Sun.COM iof |= IOREWRITE;
15944887Schin break;
15954887Schin
15964887Schin default:
15974887Schin return(lastio);
15984887Schin }
15998462SApril.Chin@Sun.COM lexp->digits=0;
16008462SApril.Chin@Sun.COM iop=(struct ionod*) stkalloc(stkp,sizeof(struct ionod));
16014887Schin iop->iodelim = 0;
16028462SApril.Chin@Sun.COM if(token=sh_lex(lexp))
16034887Schin {
16048462SApril.Chin@Sun.COM if(token==RPAREN && (iof&IOLSEEK) && lexp->comsub)
16054887Schin {
16068462SApril.Chin@Sun.COM lexp->arg = (struct argnod*)stkalloc(stkp,sizeof(struct argnod)+3);
16078462SApril.Chin@Sun.COM strcpy(lexp->arg->argval,"CUR");
16088462SApril.Chin@Sun.COM lexp->arg->argflag = ARG_RAW;
16094887Schin iof |= IOARITH;
16104887Schin fcseek(-1);
16114887Schin }
16124887Schin else if(token==EXPRSYM && (iof&IOLSEEK))
16134887Schin iof |= IOARITH;
161410898Sroland.mainz@nrubsig.org else if(((token==IPROCSYM && !(iof&IOPUT)) || (token==OPROCSYM && (iof&IOPUT))) && !(iof&(IOLSEEK|IOREWRITE|IOMOV|IODOC)))
161510898Sroland.mainz@nrubsig.org {
161610898Sroland.mainz@nrubsig.org lexp->arg = process_sub(lexp,token);
161710898Sroland.mainz@nrubsig.org iof |= IOPROCSUB;
161810898Sroland.mainz@nrubsig.org }
16194887Schin else
16208462SApril.Chin@Sun.COM sh_syntax(lexp);
16214887Schin }
162210898Sroland.mainz@nrubsig.org if( (iof&IOPROCSUB) && !(iof&IOLSEEK))
162310898Sroland.mainz@nrubsig.org iop->ioname= (char*)lexp->arg->argchn.ap;
162410898Sroland.mainz@nrubsig.org else
162510898Sroland.mainz@nrubsig.org iop->ioname=lexp->arg->argval;
16264887Schin iop->iovname = iovname;
16274887Schin if(iof&IODOC)
16284887Schin {
16298462SApril.Chin@Sun.COM if(lexp->digits==2)
16304887Schin {
16314887Schin iof |= IOSTRG;
16328462SApril.Chin@Sun.COM if(!(lexp->arg->argflag&ARG_RAW))
16334887Schin iof &= ~IORAW;
16344887Schin }
16354887Schin else
16364887Schin {
16378462SApril.Chin@Sun.COM if(!lexp->sh->heredocs)
16388462SApril.Chin@Sun.COM lexp->sh->heredocs = sftmp(HERE_MEM);
16398462SApril.Chin@Sun.COM iop->iolst=lexp->heredoc;
16408462SApril.Chin@Sun.COM lexp->heredoc=iop;
16418462SApril.Chin@Sun.COM if(lexp->arg->argflag&ARG_QUOTED)
16424887Schin iof |= IOQUOTE;
16438462SApril.Chin@Sun.COM if(lexp->digits==3)
16444887Schin iof |= IOLSEEK;
16458462SApril.Chin@Sun.COM if(lexp->digits)
16464887Schin iof |= IOSTRIP;
16474887Schin }
16484887Schin }
16494887Schin else
16504887Schin {
16514887Schin iop->iolst = 0;
16528462SApril.Chin@Sun.COM if(lexp->arg->argflag&ARG_RAW)
16534887Schin iof |= IORAW;
16544887Schin }
16554887Schin iop->iofile=iof;
16564887Schin if(flag>0)
16574887Schin /* allow alias substitutions and parameter assignments */
16588462SApril.Chin@Sun.COM lexp->aliasok = lexp->assignok = 1;
16594887Schin #if SHOPT_KIA
16608462SApril.Chin@Sun.COM if(lexp->kiafile)
16614887Schin {
16628462SApril.Chin@Sun.COM int n = lexp->sh->inlineno-(lexp->token=='\n');
16634887Schin if(!(iof&IOMOV))
16644887Schin {
16658462SApril.Chin@Sun.COM unsigned long r=kiaentity(lexp,(iof&IORAW)?sh_fmtq(iop->ioname):iop->ioname,-1,'f',0,0,lexp->script,'f',0,"");
16668462SApril.Chin@Sun.COM 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);
16674887Schin }
16684887Schin }
16694887Schin #endif /* SHOPT_KIA */
16704887Schin if(flag>=0)
16714887Schin {
16724887Schin struct ionod *ioq=iop;
16738462SApril.Chin@Sun.COM sh_lex(lexp);
16744887Schin if(errout)
16754887Schin {
16764887Schin /* redirect standard output to standard error */
16778462SApril.Chin@Sun.COM ioq = (struct ionod*)stkalloc(stkp,sizeof(struct ionod));
167810898Sroland.mainz@nrubsig.org memset(ioq,0,sizeof(*ioq));
16794887Schin ioq->ioname = "1";
16804887Schin ioq->iolst = 0;
16814887Schin ioq->iodelim = 0;
16824887Schin ioq->iofile = IORAW|IOPUT|IOMOV|2;
16834887Schin iop->ionxt=ioq;
16844887Schin }
16858462SApril.Chin@Sun.COM ioq->ionxt=inout(lexp,lastio,flag);
16864887Schin }
16874887Schin else
16884887Schin iop->ionxt=0;
16894887Schin return(iop);
16904887Schin }
16914887Schin
16924887Schin /*
16934887Schin * convert argument chain to argument list when no special arguments
16944887Schin */
16954887Schin
qscan(struct comnod * ac,int argn)16964887Schin static struct argnod *qscan(struct comnod *ac,int argn)
16974887Schin {
16984887Schin register char **cp;
16994887Schin register struct argnod *ap;
17004887Schin register struct dolnod* dp;
17014887Schin register int special=0;
17024887Schin /* special hack for test -t compatibility */
17034887Schin if((Namval_t*)ac->comnamp==SYSTEST)
17044887Schin special = 2;
17054887Schin else if(*(ac->comarg->argval)=='[' && ac->comarg->argval[1]==0)
17064887Schin special = 3;
17074887Schin if(special)
17084887Schin {
17094887Schin ap = ac->comarg->argnxt.ap;
17104887Schin if(argn==(special+1) && ap->argval[1]==0 && *ap->argval=='!')
17114887Schin ap = ap->argnxt.ap;
17124887Schin else if(argn!=special)
17134887Schin special=0;
17144887Schin }
17154887Schin if(special)
17164887Schin {
17174887Schin const char *message;
17184887Schin if(strcmp(ap->argval,"-t"))
17194887Schin {
17204887Schin message = "line %d: Invariant test";
17214887Schin special=0;
17224887Schin }
17234887Schin else
17244887Schin {
17254887Schin message = "line %d: -t requires argument";
17264887Schin argn++;
17274887Schin }
17284887Schin if(sh_isoption(SH_NOEXEC))
17294887Schin errormsg(SH_DICT,ERROR_warn(0),message,ac->comline);
17304887Schin }
17314887Schin /* leave space for an extra argument at the front */
17324887Schin dp = (struct dolnod*)stakalloc((unsigned)sizeof(struct dolnod) + ARG_SPARE*sizeof(char*) + argn*sizeof(char*));
17334887Schin cp = dp->dolval+ARG_SPARE;
17344887Schin dp->dolnum = argn;
17354887Schin dp->dolbot = ARG_SPARE;
17364887Schin ap = ac->comarg;
17374887Schin while(ap)
17384887Schin {
17394887Schin *cp++ = ap->argval;
17404887Schin ap = ap->argnxt.ap;
17414887Schin }
17424887Schin if(special==3)
17434887Schin {
17444887Schin cp[0] = cp[-1];
17454887Schin cp[-1] = "1";
17464887Schin cp++;
17474887Schin }
17484887Schin else if(special)
17494887Schin *cp++ = "1";
17504887Schin *cp = 0;
17514887Schin return((struct argnod*)dp);
17524887Schin }
17534887Schin
test_expr(Lex_t * lp,int sym)17548462SApril.Chin@Sun.COM static Shnode_t *test_expr(Lex_t *lp,int sym)
17554887Schin {
17568462SApril.Chin@Sun.COM register Shnode_t *t = test_or(lp);
17578462SApril.Chin@Sun.COM if(lp->token!=sym)
17588462SApril.Chin@Sun.COM sh_syntax(lp);
17594887Schin return(t);
17604887Schin }
17614887Schin
test_or(Lex_t * lp)17628462SApril.Chin@Sun.COM static Shnode_t *test_or(Lex_t *lp)
17634887Schin {
17648462SApril.Chin@Sun.COM register Shnode_t *t = test_and(lp);
17658462SApril.Chin@Sun.COM while(lp->token==ORFSYM)
17668462SApril.Chin@Sun.COM t = makelist(lp,TORF|TTEST,t,test_and(lp));
17674887Schin return(t);
17684887Schin }
17694887Schin
test_and(Lex_t * lp)17708462SApril.Chin@Sun.COM static Shnode_t *test_and(Lex_t *lp)
17714887Schin {
17728462SApril.Chin@Sun.COM register Shnode_t *t = test_primary(lp);
17738462SApril.Chin@Sun.COM while(lp->token==ANDFSYM)
17748462SApril.Chin@Sun.COM t = makelist(lp,TAND|TTEST,t,test_primary(lp));
17754887Schin return(t);
17764887Schin }
17774887Schin
17784887Schin /*
17794887Schin * convert =~ into == ~(E)
17804887Schin */
ere_match(void)17814887Schin static void ere_match(void)
17824887Schin {
17834887Schin Sfio_t *base, *iop = sfopen((Sfio_t*)0," ~(E)","s");
17844887Schin register int c;
17854887Schin while( fcgetc(c),(c==' ' || c=='\t'));
17864887Schin if(c)
17874887Schin fcseek(-1);
17884887Schin if(!(base=fcfile()))
17894887Schin base = sfopen(NIL(Sfio_t*),fcseek(0),"s");
17904887Schin fcclose();
17914887Schin sfstack(base,iop);
17924887Schin fcfopen(base);
17934887Schin }
17944887Schin
test_primary(Lex_t * lexp)17958462SApril.Chin@Sun.COM static Shnode_t *test_primary(Lex_t *lexp)
17964887Schin {
17974887Schin register struct argnod *arg;
17984887Schin register Shnode_t *t;
17994887Schin register int num,token;
18008462SApril.Chin@Sun.COM token = skipnl(lexp,0);
18018462SApril.Chin@Sun.COM num = lexp->digits;
18024887Schin switch(token)
18034887Schin {
18044887Schin case '(':
18058462SApril.Chin@Sun.COM t = test_expr(lexp,')');
18068462SApril.Chin@Sun.COM t = makelist(lexp,TTST|TTEST|TPAREN ,t, (Shnode_t*)pointerof(lexp->sh->inlineno));
18074887Schin break;
18084887Schin case '!':
18098462SApril.Chin@Sun.COM if(!(t = test_primary(lexp)))
18108462SApril.Chin@Sun.COM sh_syntax(lexp);
18114887Schin t->tre.tretyp |= TNEGATE;
18124887Schin return(t);
18134887Schin case TESTUNOP:
18148462SApril.Chin@Sun.COM if(sh_lex(lexp))
18158462SApril.Chin@Sun.COM sh_syntax(lexp);
18164887Schin #if SHOPT_KIA
18178462SApril.Chin@Sun.COM if(lexp->kiafile && !strchr("sntzoOG",num))
18184887Schin {
18198462SApril.Chin@Sun.COM int line = lexp->sh->inlineno- (lexp->token==NL);
18204887Schin unsigned long r;
18218462SApril.Chin@Sun.COM r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->script,'t',0,"");
18228462SApril.Chin@Sun.COM sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line);
18234887Schin }
18244887Schin #endif /* SHOPT_KIA */
18258462SApril.Chin@Sun.COM t = makelist(lexp,TTST|TTEST|TUNARY|(num<<TSHIFT),
18268462SApril.Chin@Sun.COM (Shnode_t*)lexp->arg,(Shnode_t*)lexp->arg);
18278462SApril.Chin@Sun.COM t->tst.tstline = lexp->sh->inlineno;
18284887Schin break;
18294887Schin /* binary test operators */
18304887Schin case 0:
18318462SApril.Chin@Sun.COM arg = lexp->arg;
18328462SApril.Chin@Sun.COM if((token=sh_lex(lexp))==TESTBINOP)
18334887Schin {
18348462SApril.Chin@Sun.COM num = lexp->digits;
18354887Schin if(num==TEST_REP)
18364887Schin {
18374887Schin ere_match();
18384887Schin num = TEST_PEQ;
18394887Schin }
18404887Schin }
18414887Schin else if(token=='<')
18424887Schin num = TEST_SLT;
18434887Schin else if(token=='>')
18444887Schin num = TEST_SGT;
18454887Schin else if(token==ANDFSYM||token==ORFSYM||token==ETESTSYM||token==RPAREN)
18464887Schin {
18478462SApril.Chin@Sun.COM t = makelist(lexp,TTST|TTEST|TUNARY|('n'<<TSHIFT),
18484887Schin (Shnode_t*)arg,(Shnode_t*)arg);
18498462SApril.Chin@Sun.COM t->tst.tstline = lexp->sh->inlineno;
18504887Schin return(t);
18514887Schin }
18524887Schin else
18538462SApril.Chin@Sun.COM sh_syntax(lexp);
18544887Schin #if SHOPT_KIA
18558462SApril.Chin@Sun.COM if(lexp->kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT))
18564887Schin {
18578462SApril.Chin@Sun.COM int line = lexp->sh->inlineno- (lexp->token==NL);
18584887Schin unsigned long r;
18598462SApril.Chin@Sun.COM r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->current,'t',0,"");
18608462SApril.Chin@Sun.COM sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line);
18614887Schin }
18624887Schin #endif /* SHOPT_KIA */
18638462SApril.Chin@Sun.COM if(sh_lex(lexp))
18648462SApril.Chin@Sun.COM sh_syntax(lexp);
18654887Schin if(num&TEST_PATTERN)
18664887Schin {
18678462SApril.Chin@Sun.COM if(lexp->arg->argflag&(ARG_EXP|ARG_MAC))
18684887Schin num &= ~TEST_PATTERN;
18694887Schin }
18704887Schin t = getnode(tstnod);
18714887Schin t->lst.lsttyp = TTST|TTEST|TBINARY|(num<<TSHIFT);
18724887Schin t->lst.lstlef = (Shnode_t*)arg;
18738462SApril.Chin@Sun.COM t->lst.lstrit = (Shnode_t*)lexp->arg;
18748462SApril.Chin@Sun.COM t->tst.tstline = lexp->sh->inlineno;
18754887Schin #if SHOPT_KIA
18768462SApril.Chin@Sun.COM if(lexp->kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT))
18774887Schin {
18788462SApril.Chin@Sun.COM int line = lexp->sh->inlineno-(lexp->token==NL);
18794887Schin unsigned long r;
18808462SApril.Chin@Sun.COM r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->current,'t',0,"");
18818462SApril.Chin@Sun.COM sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line);
18824887Schin }
18834887Schin #endif /* SHOPT_KIA */
18844887Schin break;
18854887Schin default:
18864887Schin return(0);
18874887Schin }
18888462SApril.Chin@Sun.COM skipnl(lexp,0);
18894887Schin return(t);
18904887Schin }
18914887Schin
18924887Schin #if SHOPT_KIA
18934887Schin /*
18944887Schin * return an entity checksum
18954887Schin * The entity is created if it doesn't exist
18964887Schin */
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)18978462SApril.Chin@Sun.COM 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)
18984887Schin {
18998462SApril.Chin@Sun.COM Stk_t *stkp = lexp->sh->stk;
19004887Schin Namval_t *np;
19018462SApril.Chin@Sun.COM long offset = stktell(stkp);
19028462SApril.Chin@Sun.COM sfputc(stkp,type);
19034887Schin if(len>0)
19048462SApril.Chin@Sun.COM sfwrite(stkp,name,len);
19054887Schin else
19064887Schin {
19074887Schin if(type=='p')
19088462SApril.Chin@Sun.COM sfputr(stkp,path_basename(name),0);
19094887Schin else
19108462SApril.Chin@Sun.COM sfputr(stkp,name,0);
19114887Schin }
19128462SApril.Chin@Sun.COM np = nv_search(stakptr(offset),lexp->entity_tree,NV_ADD);
19138462SApril.Chin@Sun.COM stkseek(stkp,offset);
19144887Schin np->nvalue.i = pkind;
19154887Schin nv_setsize(np,width);
19164887Schin if(!nv_isattr(np,NV_TAGGED) && first>=0)
19174887Schin {
19184887Schin nv_onattr(np,NV_TAGGED);
19194887Schin if(!pkind)
19204887Schin pkind = '0';
19214887Schin if(len>0)
19228462SApril.Chin@Sun.COM 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);
19234887Schin else
19248462SApril.Chin@Sun.COM 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);
19254887Schin }
19264887Schin return(np->hash);
19274887Schin }
19284887Schin
kia_add(register Namval_t * np,void * data)19294887Schin static void kia_add(register Namval_t *np, void *data)
19304887Schin {
19314887Schin char *name = nv_name(np);
19328462SApril.Chin@Sun.COM Lex_t *lp = (Lex_t*)data;
19334887Schin NOT_USED(data);
19348462SApril.Chin@Sun.COM kiaentity(lp,name+1,-1,*name,0,-1,(*name=='p'?lp->unknown:lp->script),np->nvalue.i,nv_size(np),"");
19354887Schin }
19364887Schin
kiaclose(Lex_t * lexp)19378462SApril.Chin@Sun.COM int kiaclose(Lex_t *lexp)
19384887Schin {
19394887Schin register off_t off1,off2;
19404887Schin register int n;
19418462SApril.Chin@Sun.COM if(lexp->kiafile)
19424887Schin {
19438462SApril.Chin@Sun.COM unsigned long r = kiaentity(lexp,lexp->scriptname,-1,'p',-1,lexp->sh->inlineno-1,0,'s',0,"");
19448462SApril.Chin@Sun.COM kiaentity(lexp,lexp->scriptname,-1,'p',1,lexp->sh->inlineno-1,r,'s',0,"");
19458462SApril.Chin@Sun.COM kiaentity(lexp,lexp->scriptname,-1,'f',1,lexp->sh->inlineno-1,r,'s',0,"");
19468462SApril.Chin@Sun.COM nv_scan(lexp->entity_tree,kia_add,(void*)lexp,NV_TAGGED,0);
19478462SApril.Chin@Sun.COM off1 = sfseek(lexp->kiafile,(off_t)0,SEEK_END);
19488462SApril.Chin@Sun.COM sfseek(lexp->kiatmp,(off_t)0,SEEK_SET);
19498462SApril.Chin@Sun.COM sfmove(lexp->kiatmp,lexp->kiafile,SF_UNBOUND,-1);
19508462SApril.Chin@Sun.COM off2 = sfseek(lexp->kiafile,(off_t)0,SEEK_END);
19514887Schin #ifdef SF_BUFCONST
19524887Schin if(off2==off1)
19538462SApril.Chin@Sun.COM n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%lld;%d\nDIRECTORY;",(Sflong_t)lexp->kiabegin,(size_t)(off1-lexp->kiabegin));
19544887Schin else
19558462SApril.Chin@Sun.COM 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));
19564887Schin if(off2 >= INT_MAX)
19574887Schin off2 = -(n+12);
19588462SApril.Chin@Sun.COM sfprintf(lexp->kiafile,"%010.10lld;%010d\n",(Sflong_t)off2+10, n+12);
19594887Schin #else
19604887Schin if(off2==off1)
19618462SApril.Chin@Sun.COM n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%d;%d\nDIRECTORY;",lexp->kiabegin,off1-lexp->kiabegin);
19624887Schin else
19638462SApril.Chin@Sun.COM n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%d;%d\nRELATIONSHIP;%d;%d\nDIRECTORY;",lexp->kiabegin,off1-lexp->kiabegin,off1,off2-off1);
19648462SApril.Chin@Sun.COM sfprintf(lexp->kiafile,"%010d;%010d\n",off2+10, n+12);
19654887Schin #endif
19664887Schin }
19678462SApril.Chin@Sun.COM return(sfclose(lexp->kiafile));
19684887Schin }
19694887Schin #endif /* SHOPT_KIA */
1970