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 */ 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 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 */ 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 */ 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 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 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 */ 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 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 */ 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 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 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 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 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 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 */ 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 */ 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 */ 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 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 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 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 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 */ 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 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 */ 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 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 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