14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*10898Sroland.mainz@nrubsig.org * Copyright (c) 1982-2009 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> 35*10898Sroland.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 2508462SApril.Chin@Sun.COM static Shnode_t *getanode(Lex_t *lp, struct argnod *ap) 2514887Schin { 2524887Schin register Shnode_t *t = getnode(arithnod); 2534887Schin t->ar.artyp = TARITH; 2548462SApril.Chin@Sun.COM t->ar.arline = sh_getlineno(lp); 2554887Schin t->ar.arexpr = ap; 2564887Schin if(ap->argflag&ARG_RAW) 2574887Schin t->ar.arcomp = sh_arithcomp(ap->argval); 2584887Schin else 2594887Schin t->ar.arcomp = 0; 2604887Schin return(t); 2614887Schin } 2624887Schin 2634887Schin /* 2644887Schin * Make a node corresponding to a command list 2654887Schin */ 2668462SApril.Chin@Sun.COM static Shnode_t *makelist(Lex_t *lexp, int type, Shnode_t *l, Shnode_t *r) 2674887Schin { 2684887Schin register Shnode_t *t; 2694887Schin if(!l || !r) 2708462SApril.Chin@Sun.COM sh_syntax(lexp); 2714887Schin else 2724887Schin { 2734887Schin if((type&COMMSK) == TTST) 2744887Schin t = getnode(tstnod); 2754887Schin else 2764887Schin t = getnode(lstnod); 2774887Schin t->lst.lsttyp = type; 2784887Schin t->lst.lstlef = l; 2794887Schin t->lst.lstrit = r; 2804887Schin } 2814887Schin return(t); 2824887Schin } 2834887Schin 2844887Schin /* 2854887Schin * entry to shell parser 2864887Schin * Flag can be the union of SH_EOF|SH_NL 2874887Schin */ 2884887Schin 2894887Schin void *sh_parse(Shell_t *shp, Sfio_t *iop, int flag) 2904887Schin { 2914887Schin register Shnode_t *t; 2928462SApril.Chin@Sun.COM Lex_t *lexp = (Lex_t*)shp->lex_context; 2934887Schin Fcin_t sav_input; 2948462SApril.Chin@Sun.COM struct argnod *sav_arg = lexp->arg; 2954887Schin int sav_prompt = shp->nextprompt; 296*10898Sroland.mainz@nrubsig.org if(shp->binscript && (sffileno(iop)==shp->infd || (flag&SH_FUNEVAL))) 2978462SApril.Chin@Sun.COM return((void*)sh_trestore(shp,iop)); 2984887Schin fcsave(&sav_input); 2994887Schin shp->st.staklist = 0; 3008462SApril.Chin@Sun.COM lexp->heredoc = 0; 3018462SApril.Chin@Sun.COM lexp->inlineno = shp->inlineno; 3028462SApril.Chin@Sun.COM lexp->firstline = shp->st.firstline; 3034887Schin shp->nextprompt = 1; 3044887Schin loop_level = 0; 3054887Schin label_list = label_last = 0; 3064887Schin if(sh_isoption(SH_INTERACTIVE)) 3074887Schin sh_onstate(SH_INTERACTIVE); 3084887Schin if(sh_isoption(SH_VERBOSE)) 3094887Schin sh_onstate(SH_VERBOSE); 3108462SApril.Chin@Sun.COM sh_lexopen(lexp,shp,0); 3114887Schin if(fcfopen(iop) < 0) 3124887Schin return(NIL(void*)); 3134887Schin if(fcfile()) 3144887Schin { 3154887Schin char *cp = fcfirst(); 3164887Schin if( cp[0]==CNTL('k') && cp[1]==CNTL('s') && cp[2]==CNTL('h') && cp[3]==0) 3174887Schin { 3184887Schin int version; 3194887Schin fcseek(4); 3204887Schin fcgetc(version); 3214887Schin fcclose(); 3224887Schin fcrestore(&sav_input); 3238462SApril.Chin@Sun.COM lexp->arg = sav_arg; 3244887Schin if(version > 3) 3254887Schin errormsg(SH_DICT,ERROR_exit(1),e_lexversion); 326*10898Sroland.mainz@nrubsig.org if(sffileno(iop)==shp->infd || (flag&SH_FUNEVAL)) 3274887Schin shp->binscript = 1; 3284887Schin sfgetc(iop); 3298462SApril.Chin@Sun.COM return((void*)sh_trestore(shp,iop)); 3304887Schin } 3314887Schin } 332*10898Sroland.mainz@nrubsig.org flag &= ~SH_FUNEVAL; 3334887Schin if((flag&SH_NL) && (shp->inlineno=error_info.line+shp->st.firstline)==0) 3344887Schin shp->inlineno=1; 3354887Schin #if KSHELL 3364887Schin shp->nextprompt = 2; 3374887Schin #endif 3388462SApril.Chin@Sun.COM t = sh_cmd(lexp,(flag&SH_EOF)?EOFSYM:'\n',SH_SEMI|SH_EMPTY|(flag&SH_NL)); 3394887Schin fcclose(); 3404887Schin fcrestore(&sav_input); 3418462SApril.Chin@Sun.COM lexp->arg = sav_arg; 3424887Schin /* unstack any completed alias expansions */ 3434887Schin if((sfset(iop,0,0)&SF_STRING) && !sfreserve(iop,0,-1)) 3444887Schin { 3454887Schin Sfio_t *sp = sfstack(iop,NULL); 3464887Schin if(sp) 3474887Schin sfclose(sp); 3484887Schin } 3494887Schin shp->nextprompt = sav_prompt; 3504887Schin if(flag&SH_NL) 3514887Schin { 3528462SApril.Chin@Sun.COM shp->st.firstline = lexp->firstline; 3538462SApril.Chin@Sun.COM shp->inlineno = lexp->inlineno; 3544887Schin } 3558462SApril.Chin@Sun.COM stkseek(shp->stk,0); 3564887Schin return((void*)t); 3574887Schin } 3584887Schin 3594887Schin /* 3604887Schin * This routine parses up the matching right parenthesis and returns 3614887Schin * the parse tree 3624887Schin */ 3638462SApril.Chin@Sun.COM Shnode_t *sh_dolparen(Lex_t* lp) 3644887Schin { 3654887Schin register Shnode_t *t=0; 3664887Schin Sfio_t *sp = fcfile(); 3678462SApril.Chin@Sun.COM int line = lp->sh->inlineno; 3688462SApril.Chin@Sun.COM lp->sh->inlineno = error_info.line+lp->sh->st.firstline; 3698462SApril.Chin@Sun.COM sh_lexopen(lp,lp->sh,1); 3708462SApril.Chin@Sun.COM lp->comsub = 1; 3718462SApril.Chin@Sun.COM switch(sh_lex(lp)) 3724887Schin { 3734887Schin /* ((...)) arithmetic expression */ 3744887Schin case EXPRSYM: 3758462SApril.Chin@Sun.COM t = getanode(lp,lp->arg); 3764887Schin break; 3774887Schin case LPAREN: 3788462SApril.Chin@Sun.COM t = sh_cmd(lp,RPAREN,SH_NL|SH_EMPTY); 3798462SApril.Chin@Sun.COM break; 3808462SApril.Chin@Sun.COM case LBRACE: 3818462SApril.Chin@Sun.COM t = sh_cmd(lp,RBRACE,SH_NL|SH_EMPTY); 3824887Schin break; 3834887Schin } 3848462SApril.Chin@Sun.COM lp->comsub = 0; 3854887Schin if(!sp && (sp=fcfile())) 3864887Schin { 3874887Schin /* 3884887Schin * This code handles the case where string has been converted 3894887Schin * to a file by an alias setup 3904887Schin */ 3914887Schin register int c; 3924887Schin char *cp; 3934887Schin if(fcgetc(c) > 0) 3944887Schin fcseek(-1); 3954887Schin cp = fcseek(0); 3964887Schin fcclose(); 3974887Schin fcsopen(cp); 3984887Schin sfclose(sp); 3994887Schin } 4008462SApril.Chin@Sun.COM lp->sh->inlineno = line; 4014887Schin return(t); 4024887Schin } 4034887Schin 4044887Schin /* 4054887Schin * remove temporary files and stacks 4064887Schin */ 4074887Schin 4088462SApril.Chin@Sun.COM void sh_freeup(Shell_t *shp) 4094887Schin { 4108462SApril.Chin@Sun.COM if(shp->st.staklist) 4118462SApril.Chin@Sun.COM sh_funstaks(shp->st.staklist,-1); 4128462SApril.Chin@Sun.COM shp->st.staklist = 0; 4134887Schin } 4144887Schin 4154887Schin /* 4164887Schin * increase reference count for each stack in function list when flag>0 4174887Schin * decrease reference count for each stack in function list when flag<=0 4184887Schin * stack is freed when reference count is zero 4194887Schin */ 4204887Schin 4214887Schin void sh_funstaks(register struct slnod *slp,int flag) 4224887Schin { 4234887Schin register struct slnod *slpold; 4244887Schin while(slpold=slp) 4254887Schin { 4264887Schin if(slp->slchild) 4274887Schin sh_funstaks(slp->slchild,flag); 4284887Schin slp = slp->slnext; 4294887Schin if(flag<=0) 4304887Schin stakdelete(slpold->slptr); 4314887Schin else 4324887Schin staklink(slpold->slptr); 4334887Schin } 4344887Schin } 4354887Schin /* 4364887Schin * cmd 4374887Schin * empty 4384887Schin * list 4394887Schin * list & [ cmd ] 4404887Schin * list [ ; cmd ] 4414887Schin */ 4424887Schin 4438462SApril.Chin@Sun.COM static Shnode_t *sh_cmd(Lex_t *lexp, register int sym, int flag) 4444887Schin { 4454887Schin register Shnode_t *left, *right; 4464887Schin register int type = FINT|FAMP; 4474887Schin if(sym==NL) 4488462SApril.Chin@Sun.COM lexp->lasttok = 0; 4498462SApril.Chin@Sun.COM left = list(lexp,flag); 4508462SApril.Chin@Sun.COM if(lexp->token==NL) 4514887Schin { 4524887Schin if(flag&SH_NL) 4538462SApril.Chin@Sun.COM lexp->token=';'; 4544887Schin } 4554887Schin else if(!left && !(flag&SH_EMPTY)) 4568462SApril.Chin@Sun.COM sh_syntax(lexp); 4578462SApril.Chin@Sun.COM switch(lexp->token) 4584887Schin { 4594887Schin case COOPSYM: /* set up a cooperating process */ 4604887Schin type |= (FPIN|FPOU|FPCL|FCOOP); 4614887Schin /* FALL THRU */ 4624887Schin case '&': 4634887Schin if(left) 4644887Schin { 4654887Schin /* (...)& -> {...;} & */ 4664887Schin if(left->tre.tretyp==TPAR) 4674887Schin left = left->par.partre; 4688462SApril.Chin@Sun.COM left = makeparent(lexp,TFORK|type, left); 4694887Schin } 4704887Schin /* FALL THRU */ 4714887Schin case ';': 4724887Schin if(!left) 4738462SApril.Chin@Sun.COM sh_syntax(lexp); 4748462SApril.Chin@Sun.COM if(right=sh_cmd(lexp,sym,flag|SH_EMPTY)) 4758462SApril.Chin@Sun.COM left=makelist(lexp,TLST, left, right); 4764887Schin break; 4774887Schin case EOFSYM: 4784887Schin if(sym==NL) 4794887Schin break; 4804887Schin default: 4818462SApril.Chin@Sun.COM if(sym && sym!=lexp->token) 4824887Schin { 4838462SApril.Chin@Sun.COM if(sym!=ELSESYM || (lexp->token!=ELIFSYM && lexp->token!=FISYM)) 4848462SApril.Chin@Sun.COM sh_syntax(lexp); 4854887Schin } 4864887Schin } 4874887Schin return(left); 4884887Schin } 4894887Schin 4904887Schin /* 4914887Schin * list 4924887Schin * term 4934887Schin * list && term 4944887Schin * list || term 4954887Schin * unfortunately, these are equal precedence 4964887Schin */ 4978462SApril.Chin@Sun.COM static Shnode_t *list(Lex_t *lexp, register int flag) 4984887Schin { 4998462SApril.Chin@Sun.COM register Shnode_t *t = term(lexp,flag); 5004887Schin register int token; 5018462SApril.Chin@Sun.COM while(t && ((token=lexp->token)==ANDFSYM || token==ORFSYM)) 5028462SApril.Chin@Sun.COM t = makelist(lexp,(token==ANDFSYM?TAND:TORF), t, term(lexp,SH_NL|SH_SEMI)); 5034887Schin return(t); 5044887Schin } 5054887Schin 5064887Schin /* 5074887Schin * term 5084887Schin * item 5094887Schin * item | term 5104887Schin */ 5118462SApril.Chin@Sun.COM static Shnode_t *term(Lex_t *lexp,register int flag) 5124887Schin { 5134887Schin register Shnode_t *t; 5144887Schin register int token; 5154887Schin if(flag&SH_NL) 5168462SApril.Chin@Sun.COM token = skipnl(lexp,flag); 5174887Schin else 5188462SApril.Chin@Sun.COM token = sh_lex(lexp); 5194887Schin /* check to see if pipeline is to be timed */ 5204887Schin if(token==TIMESYM || token==NOTSYM) 5214887Schin { 5224887Schin t = getnode(parnod); 5234887Schin t->par.partyp=TTIME; 5248462SApril.Chin@Sun.COM if(lexp->token==NOTSYM) 5254887Schin t->par.partyp |= COMSCAN; 5268462SApril.Chin@Sun.COM t->par.partre = term(lexp,0); 5274887Schin } 5288462SApril.Chin@Sun.COM else if((t=item(lexp,SH_NL|SH_EMPTY|(flag&SH_SEMI))) && lexp->token=='|') 5294887Schin { 5304887Schin register Shnode_t *tt; 5314887Schin int showme = t->tre.tretyp&FSHOWME; 5328462SApril.Chin@Sun.COM t = makeparent(lexp,TFORK|FPOU,t); 5338462SApril.Chin@Sun.COM if(tt=term(lexp,SH_NL)) 5344887Schin { 5354887Schin switch(tt->tre.tretyp&COMMSK) 5364887Schin { 5374887Schin case TFORK: 5384887Schin tt->tre.tretyp |= FPIN|FPCL; 5394887Schin break; 5404887Schin case TFIL: 5414887Schin tt->lst.lstlef->tre.tretyp |= FPIN|FPCL; 5424887Schin break; 5434887Schin default: 5448462SApril.Chin@Sun.COM tt= makeparent(lexp,TSETIO|FPIN|FPCL,tt); 5454887Schin } 5468462SApril.Chin@Sun.COM t=makelist(lexp,TFIL,t,tt); 5474887Schin t->tre.tretyp |= showme; 5484887Schin } 5498462SApril.Chin@Sun.COM else if(lexp->token) 5508462SApril.Chin@Sun.COM sh_syntax(lexp); 5514887Schin } 5524887Schin return(t); 5534887Schin } 5544887Schin 5554887Schin /* 5564887Schin * case statement 5574887Schin */ 5588462SApril.Chin@Sun.COM static struct regnod* syncase(Lex_t *lexp,register int esym) 5594887Schin { 5608462SApril.Chin@Sun.COM register int tok = skipnl(lexp,0); 5614887Schin register struct regnod *r; 5624887Schin if(tok==esym) 5634887Schin return(NIL(struct regnod*)); 5644887Schin r = (struct regnod*)stakalloc(sizeof(struct regnod)); 5654887Schin r->regptr=0; 5664887Schin r->regflag=0; 5674887Schin if(tok==LPAREN) 5688462SApril.Chin@Sun.COM skipnl(lexp,0); 5694887Schin while(1) 5704887Schin { 5718462SApril.Chin@Sun.COM if(!lexp->arg) 5728462SApril.Chin@Sun.COM sh_syntax(lexp); 5738462SApril.Chin@Sun.COM lexp->arg->argnxt.ap=r->regptr; 5748462SApril.Chin@Sun.COM r->regptr = lexp->arg; 5758462SApril.Chin@Sun.COM if((tok=sh_lex(lexp))==RPAREN) 5764887Schin break; 5774887Schin else if(tok=='|') 5788462SApril.Chin@Sun.COM sh_lex(lexp); 5794887Schin else 5808462SApril.Chin@Sun.COM sh_syntax(lexp); 5814887Schin } 5828462SApril.Chin@Sun.COM r->regcom=sh_cmd(lexp,0,SH_NL|SH_EMPTY|SH_SEMI); 5838462SApril.Chin@Sun.COM if((tok=lexp->token)==BREAKCASESYM) 5848462SApril.Chin@Sun.COM r->regnxt=syncase(lexp,esym); 5854887Schin else if(tok==FALLTHRUSYM) 5864887Schin { 5874887Schin r->regflag++; 5888462SApril.Chin@Sun.COM r->regnxt=syncase(lexp,esym); 5894887Schin } 5904887Schin else 5914887Schin { 5924887Schin if(tok!=esym && tok!=EOFSYM) 5938462SApril.Chin@Sun.COM sh_syntax(lexp); 5944887Schin r->regnxt=0; 5954887Schin } 5968462SApril.Chin@Sun.COM if(lexp->token==EOFSYM) 5974887Schin return(NIL(struct regnod*)); 5984887Schin return(r); 5994887Schin } 6004887Schin 6014887Schin /* 6024887Schin * This routine creates the parse tree for the arithmetic for 6034887Schin * When called, shlex.arg contains the string inside ((...)) 6044887Schin * When the first argument is missing, a while node is returned 6054887Schin * Otherise a list containing an arithmetic command and a while 6064887Schin * is returned. 6074887Schin */ 6088462SApril.Chin@Sun.COM static Shnode_t *arithfor(Lex_t *lexp,register Shnode_t *tf) 6094887Schin { 6104887Schin register Shnode_t *t, *tw = tf; 6114887Schin register int offset; 6124887Schin register struct argnod *argp; 6134887Schin register int n; 6148462SApril.Chin@Sun.COM Stk_t *stkp = lexp->sh->stk; 6158462SApril.Chin@Sun.COM int argflag = lexp->arg->argflag; 6164887Schin /* save current input */ 6174887Schin Fcin_t sav_input; 6184887Schin fcsave(&sav_input); 6198462SApril.Chin@Sun.COM fcsopen(lexp->arg->argval); 6204887Schin /* split ((...)) into three expressions */ 6214887Schin for(n=0; ; n++) 6224887Schin { 6234887Schin register int c; 6248462SApril.Chin@Sun.COM argp = (struct argnod*)stkseek(stkp,ARGVAL); 6254887Schin argp->argnxt.ap = 0; 6264887Schin argp->argchn.cp = 0; 6274887Schin argp->argflag = argflag; 6284887Schin if(n==2) 6294887Schin break; 6304887Schin /* copy up to ; onto the stack */ 6318462SApril.Chin@Sun.COM sh_lexskip(lexp,';',1,ST_NESTED); 6328462SApril.Chin@Sun.COM offset = stktell(stkp)-1; 6334887Schin if((c=fcpeek(-1))!=';') 6344887Schin break; 6354887Schin /* remove trailing white space */ 6368462SApril.Chin@Sun.COM while(offset>ARGVAL && ((c= *stkptr(stkp,offset-1)),isspace(c))) 6374887Schin offset--; 6384887Schin /* check for empty initialization expression */ 6394887Schin if(offset==ARGVAL && n==0) 6404887Schin continue; 6418462SApril.Chin@Sun.COM stkseek(stkp,offset); 6424887Schin /* check for empty condition and treat as while((1)) */ 6434887Schin if(offset==ARGVAL) 6448462SApril.Chin@Sun.COM sfputc(stkp,'1'); 6458462SApril.Chin@Sun.COM argp = (struct argnod*)stkfreeze(stkp,1); 6468462SApril.Chin@Sun.COM t = getanode(lexp,argp); 6474887Schin if(n==0) 6488462SApril.Chin@Sun.COM tf = makelist(lexp,TLST,t,tw); 6494887Schin else 6504887Schin tw->wh.whtre = t; 6514887Schin } 6524887Schin while((offset=fcpeek(0)) && isspace(offset)) 6534887Schin fcseek(1); 6544887Schin stakputs(fcseek(0)); 6554887Schin argp = (struct argnod*)stakfreeze(1); 6564887Schin fcrestore(&sav_input); 6574887Schin if(n<2) 6584887Schin { 6598462SApril.Chin@Sun.COM lexp->token = RPAREN|SYMREP; 6608462SApril.Chin@Sun.COM sh_syntax(lexp); 6614887Schin } 6624887Schin /* check whether the increment is present */ 6634887Schin if(*argp->argval) 6644887Schin { 6658462SApril.Chin@Sun.COM t = getanode(lexp,argp); 6664887Schin tw->wh.whinc = (struct arithnod*)t; 6674887Schin } 6684887Schin else 6694887Schin tw->wh.whinc = 0; 6708462SApril.Chin@Sun.COM sh_lexopen(lexp, lexp->sh,1); 6718462SApril.Chin@Sun.COM if((n=sh_lex(lexp))==NL) 6728462SApril.Chin@Sun.COM n = skipnl(lexp,0); 6734887Schin else if(n==';') 6748462SApril.Chin@Sun.COM n = sh_lex(lexp); 6754887Schin if(n!=DOSYM && n!=LBRACE) 6768462SApril.Chin@Sun.COM sh_syntax(lexp); 6778462SApril.Chin@Sun.COM tw->wh.dotre = sh_cmd(lexp,n==DOSYM?DONESYM:RBRACE,SH_NL); 6784887Schin tw->wh.whtyp = TWH; 6794887Schin return(tf); 6804887Schin 6814887Schin } 6824887Schin 6838462SApril.Chin@Sun.COM static Shnode_t *funct(Lex_t *lexp) 6844887Schin { 6858462SApril.Chin@Sun.COM Shell_t *shp = lexp->sh; 6864887Schin register Shnode_t *t; 6874887Schin register int flag; 6884887Schin struct slnod *volatile slp=0; 6894887Schin Stak_t *savstak; 6904887Schin Sfoff_t first, last; 6918462SApril.Chin@Sun.COM struct functnod *volatile fp; 6924887Schin Sfio_t *iop; 6934887Schin #if SHOPT_KIA 6948462SApril.Chin@Sun.COM unsigned long current = lexp->current; 6954887Schin #endif /* SHOPT_KIA */ 6964887Schin int jmpval, saveloop=loop_level; 6974887Schin struct argnod *savelabel = label_last; 6984887Schin struct checkpt buff; 6998462SApril.Chin@Sun.COM int save_optget = opt_get; 7008462SApril.Chin@Sun.COM void *in_mktype = shp->mktype; 7018462SApril.Chin@Sun.COM shp->mktype = 0; 7028462SApril.Chin@Sun.COM opt_get = 0; 7034887Schin t = getnode(functnod); 7048462SApril.Chin@Sun.COM t->funct.functline = shp->inlineno; 7054887Schin t->funct.functtyp=TFUN; 7064887Schin t->funct.functargs = 0; 7078462SApril.Chin@Sun.COM if(!(flag = (lexp->token==FUNCTSYM))) 7084887Schin t->funct.functtyp |= FPOSIX; 7098462SApril.Chin@Sun.COM else if(sh_lex(lexp)) 7108462SApril.Chin@Sun.COM sh_syntax(lexp); 7114887Schin if(!(iop=fcfile())) 7124887Schin { 7134887Schin iop = sfopen(NIL(Sfio_t*),fcseek(0),"s"); 7144887Schin fcclose(); 7154887Schin fcfopen(iop); 7164887Schin } 7174887Schin t->funct.functloc = first = fctell(); 7188462SApril.Chin@Sun.COM if(!shp->st.filename || sffileno(iop)<0) 7194887Schin { 7204887Schin if(fcfill() >= 0) 7214887Schin fcseek(-1); 722*10898Sroland.mainz@nrubsig.org if(sh_isstate(SH_HISTORY) && shp->hist_ptr) 7238462SApril.Chin@Sun.COM t->funct.functloc = sfseek(shp->hist_ptr->histfp,(off_t)0,SEEK_CUR); 7244887Schin else 7254887Schin { 7264887Schin /* copy source to temporary file */ 7274887Schin t->funct.functloc = 0; 7288462SApril.Chin@Sun.COM if(lexp->sh->heredocs) 7298462SApril.Chin@Sun.COM t->funct.functloc = sfseek(lexp->sh->heredocs,(Sfoff_t)0, SEEK_END); 7304887Schin else 7318462SApril.Chin@Sun.COM lexp->sh->heredocs = sftmp(HERE_MEM); 7328462SApril.Chin@Sun.COM lexp->sh->funlog = lexp->sh->heredocs; 7334887Schin t->funct.functtyp |= FPIN; 7344887Schin } 7354887Schin } 7368462SApril.Chin@Sun.COM t->funct.functnam= (char*)lexp->arg->argval; 7374887Schin #if SHOPT_KIA 7388462SApril.Chin@Sun.COM if(lexp->kiafile) 7398462SApril.Chin@Sun.COM lexp->current = kiaentity(lexp,t->funct.functnam,-1,'p',-1,-1,lexp->script,'p',0,""); 7404887Schin #endif /* SHOPT_KIA */ 7414887Schin if(flag) 7424887Schin { 7438462SApril.Chin@Sun.COM lexp->token = sh_lex(lexp); 7444887Schin #if SHOPT_BASH 7458462SApril.Chin@Sun.COM if(lexp->token == LPAREN) 7464887Schin { 7478462SApril.Chin@Sun.COM if((lexp->token = sh_lex(lexp)) == RPAREN) 7484887Schin t->funct.functtyp |= FPOSIX; 7494887Schin else 7508462SApril.Chin@Sun.COM sh_syntax(lexp); 7514887Schin } 7524887Schin #endif 7534887Schin } 7544887Schin if(t->funct.functtyp&FPOSIX) 7558462SApril.Chin@Sun.COM skipnl(lexp,0); 7564887Schin else 7574887Schin { 7588462SApril.Chin@Sun.COM if(lexp->token==0) 7598462SApril.Chin@Sun.COM t->funct.functargs = (struct comnod*)simple(lexp,SH_NOIO|SH_FUNDEF,NIL(struct ionod*)); 7608462SApril.Chin@Sun.COM while(lexp->token==NL) 7618462SApril.Chin@Sun.COM lexp->token = sh_lex(lexp); 7624887Schin } 7638462SApril.Chin@Sun.COM if((flag && lexp->token!=LBRACE) || lexp->token==EOFSYM) 7648462SApril.Chin@Sun.COM sh_syntax(lexp); 7654887Schin sh_pushcontext(&buff,1); 7664887Schin jmpval = sigsetjmp(buff.buff,0); 7674887Schin if(jmpval == 0) 7684887Schin { 7694887Schin /* create a new stak frame to compile the command */ 7704887Schin savstak = stakcreate(STAK_SMALL); 7714887Schin savstak = stakinstall(savstak, 0); 7724887Schin slp = (struct slnod*)stakalloc(sizeof(struct slnod)+sizeof(struct functnod)); 7734887Schin slp->slchild = 0; 7748462SApril.Chin@Sun.COM slp->slnext = shp->st.staklist; 7758462SApril.Chin@Sun.COM shp->st.staklist = 0; 7764887Schin t->funct.functstak = (struct slnod*)slp; 7774887Schin /* 7784887Schin * store the pathname of function definition file on stack 7794887Schin * in name field of fake for node 7804887Schin */ 7814887Schin fp = (struct functnod*)(slp+1); 7824887Schin fp->functtyp = TFUN|FAMP; 7834887Schin fp->functnam = 0; 7844887Schin fp->functline = t->funct.functline; 7858462SApril.Chin@Sun.COM if(shp->st.filename) 7868462SApril.Chin@Sun.COM fp->functnam = stakcopy(shp->st.filename); 7874887Schin loop_level = 0; 7884887Schin label_last = label_list; 7898462SApril.Chin@Sun.COM if(!flag && lexp->token==0) 7904887Schin { 7914887Schin /* copy current word token to current stak frame */ 7924887Schin struct argnod *ap; 7938462SApril.Chin@Sun.COM flag = ARGVAL + strlen(lexp->arg->argval); 7944887Schin ap = (struct argnod*)stakalloc(flag); 7958462SApril.Chin@Sun.COM memcpy(ap,lexp->arg,flag); 7968462SApril.Chin@Sun.COM lexp->arg = ap; 7974887Schin } 7988462SApril.Chin@Sun.COM t->funct.functtre = item(lexp,SH_NOIO); 7994887Schin } 8004887Schin sh_popcontext(&buff); 8014887Schin loop_level = saveloop; 8024887Schin label_last = savelabel; 8034887Schin /* restore the old stack */ 8044887Schin if(slp) 8054887Schin { 8064887Schin slp->slptr = stakinstall(savstak,0); 8078462SApril.Chin@Sun.COM slp->slchild = shp->st.staklist; 8084887Schin } 8094887Schin #if SHOPT_KIA 8108462SApril.Chin@Sun.COM lexp->current = current; 8114887Schin #endif /* SHOPT_KIA */ 8124887Schin if(jmpval) 8134887Schin { 8144887Schin if(slp && slp->slptr) 8154887Schin { 8168462SApril.Chin@Sun.COM shp->st.staklist = slp->slnext; 8174887Schin stakdelete(slp->slptr); 8184887Schin } 8198462SApril.Chin@Sun.COM siglongjmp(*shp->jmplist,jmpval); 8204887Schin } 8218462SApril.Chin@Sun.COM shp->st.staklist = (struct slnod*)slp; 8224887Schin last = fctell(); 8234887Schin fp->functline = (last-first); 8244887Schin fp->functtre = t; 8258462SApril.Chin@Sun.COM shp->mktype = in_mktype; 8268462SApril.Chin@Sun.COM if(lexp->sh->funlog) 8274887Schin { 8284887Schin if(fcfill()>0) 8294887Schin fcseek(-1); 8308462SApril.Chin@Sun.COM lexp->sh->funlog = 0; 8314887Schin } 8324887Schin #if SHOPT_KIA 8338462SApril.Chin@Sun.COM if(lexp->kiafile) 8348462SApril.Chin@Sun.COM kiaentity(lexp,t->funct.functnam,-1,'p',t->funct.functline,shp->inlineno-1,lexp->current,'p',0,""); 8354887Schin #endif /* SHOPT_KIA */ 8368462SApril.Chin@Sun.COM t->funct.functtyp |= opt_get; 8378462SApril.Chin@Sun.COM opt_get = save_optget; 8384887Schin return(t); 8394887Schin } 8404887Schin 8414887Schin /* 8424887Schin * Compound assignment 8434887Schin */ 8448462SApril.Chin@Sun.COM static struct argnod *assign(Lex_t *lexp, register struct argnod *ap, int tdef) 8454887Schin { 8464887Schin register int n; 8474887Schin register Shnode_t *t, **tp; 8484887Schin register struct comnod *ac; 8498462SApril.Chin@Sun.COM Stk_t *stkp = lexp->sh->stk; 8504887Schin int array=0; 8514887Schin Namval_t *np; 8524887Schin n = strlen(ap->argval)-1; 8534887Schin if(ap->argval[n]!='=') 8548462SApril.Chin@Sun.COM sh_syntax(lexp); 8554887Schin if(ap->argval[n-1]=='+') 8564887Schin { 8574887Schin ap->argval[n--]=0; 8584887Schin array = ARG_APPEND; 8594887Schin } 8604887Schin /* shift right */ 8614887Schin while(n > 0) 8624887Schin { 8634887Schin ap->argval[n] = ap->argval[n-1]; 8644887Schin n--; 8654887Schin } 8664887Schin *ap->argval=0; 8674887Schin t = getnode(fornod); 8684887Schin t->for_.fornam = (char*)(ap->argval+1); 8698462SApril.Chin@Sun.COM t->for_.fortyp = sh_getlineno(lexp); 8704887Schin tp = &t->for_.fortre; 8714887Schin ap->argchn.ap = (struct argnod*)t; 8724887Schin ap->argflag &= ARG_QUOTED; 8734887Schin ap->argflag |= array; 8748462SApril.Chin@Sun.COM lexp->assignok = SH_ASSIGN; 8758462SApril.Chin@Sun.COM lexp->aliasok = 1; 8764887Schin array=0; 8778462SApril.Chin@Sun.COM if((n=skipnl(lexp,0))==RPAREN || n==LPAREN) 8784887Schin { 8794887Schin int index= 0; 8804887Schin struct argnod **settail; 8814887Schin ac = (struct comnod*)getnode(comnod); 8824887Schin settail= &ac->comset; 8834887Schin memset((void*)ac,0,sizeof(*ac)); 8848462SApril.Chin@Sun.COM ac->comline = sh_getlineno(lexp); 8854887Schin while(n==LPAREN) 8864887Schin { 8874887Schin struct argnod *ap; 8888462SApril.Chin@Sun.COM ap = (struct argnod*)stkseek(stkp,ARGVAL); 8894887Schin ap->argflag= ARG_ASSIGN; 8908462SApril.Chin@Sun.COM sfprintf(stkp,"[%d]=",index++); 8918462SApril.Chin@Sun.COM ap = (struct argnod*)stkfreeze(stkp,1); 8924887Schin ap->argnxt.ap = 0; 8938462SApril.Chin@Sun.COM ap = assign(lexp,ap,0); 8944887Schin ap->argflag |= ARG_MESSAGE; 8954887Schin *settail = ap; 8964887Schin settail = &(ap->argnxt.ap); 8978462SApril.Chin@Sun.COM while((n = skipnl(lexp,0))==0) 8988462SApril.Chin@Sun.COM { 8998462SApril.Chin@Sun.COM ap = (struct argnod*)stkseek(stkp,ARGVAL); 9008462SApril.Chin@Sun.COM ap->argflag= ARG_ASSIGN; 9018462SApril.Chin@Sun.COM sfprintf(stkp,"[%d]=",index++); 9028462SApril.Chin@Sun.COM stakputs(lexp->arg->argval); 9038462SApril.Chin@Sun.COM ap = (struct argnod*)stkfreeze(stkp,1); 9048462SApril.Chin@Sun.COM ap->argnxt.ap = 0; 9058462SApril.Chin@Sun.COM ap->argflag = lexp->arg->argflag; 9068462SApril.Chin@Sun.COM *settail = ap; 9078462SApril.Chin@Sun.COM settail = &(ap->argnxt.ap); 9088462SApril.Chin@Sun.COM } 9094887Schin } 9104887Schin } 9118462SApril.Chin@Sun.COM else if(n && n!=FUNCTSYM) 9128462SApril.Chin@Sun.COM sh_syntax(lexp); 9138462SApril.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))) 9148462SApril.Chin@Sun.COM { 9154887Schin array=SH_ARRAY; 9168462SApril.Chin@Sun.COM if(fcgetc(n)==LPAREN) 9178462SApril.Chin@Sun.COM { 9188462SApril.Chin@Sun.COM int c; 9198462SApril.Chin@Sun.COM if(fcgetc(c)==RPAREN) 9208462SApril.Chin@Sun.COM { 9218462SApril.Chin@Sun.COM lexp->token = SYMRES; 9228462SApril.Chin@Sun.COM array = 0; 9238462SApril.Chin@Sun.COM } 9248462SApril.Chin@Sun.COM else 9258462SApril.Chin@Sun.COM fcseek(-2); 9268462SApril.Chin@Sun.COM } 9278462SApril.Chin@Sun.COM else if(n>0) 9288462SApril.Chin@Sun.COM fcseek(-1); 9298462SApril.Chin@Sun.COM if(array && tdef) 9308462SApril.Chin@Sun.COM sh_syntax(lexp); 9318462SApril.Chin@Sun.COM } 9324887Schin while(1) 9334887Schin { 9348462SApril.Chin@Sun.COM if((n=lexp->token)==RPAREN) 9354887Schin break; 9364887Schin if(n==FUNCTSYM || n==SYMRES) 9378462SApril.Chin@Sun.COM ac = (struct comnod*)funct(lexp); 9384887Schin else 9398462SApril.Chin@Sun.COM ac = (struct comnod*)simple(lexp,SH_NOIO|SH_ASSIGN|array,NIL(struct ionod*)); 9408462SApril.Chin@Sun.COM if((n=lexp->token)==RPAREN) 9414887Schin break; 9424887Schin if(n!=NL && n!=';') 9438462SApril.Chin@Sun.COM sh_syntax(lexp); 9448462SApril.Chin@Sun.COM lexp->assignok = SH_ASSIGN; 9458462SApril.Chin@Sun.COM if((n=skipnl(lexp,0)) || array) 9464887Schin { 9474887Schin if(n==RPAREN) 9484887Schin break; 9494887Schin if(array || n!=FUNCTSYM) 9508462SApril.Chin@Sun.COM sh_syntax(lexp); 9514887Schin } 9528462SApril.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))) 9534887Schin { 9548462SApril.Chin@Sun.COM struct argnod *arg = lexp->arg; 9554887Schin if(n!=0) 9568462SApril.Chin@Sun.COM sh_syntax(lexp); 9574887Schin /* check for sys5 style function */ 9588462SApril.Chin@Sun.COM if(sh_lex(lexp)!=LPAREN || sh_lex(lexp)!=RPAREN) 9594887Schin { 9608462SApril.Chin@Sun.COM lexp->arg = arg; 9618462SApril.Chin@Sun.COM lexp->token = 0; 9628462SApril.Chin@Sun.COM sh_syntax(lexp); 9634887Schin } 9648462SApril.Chin@Sun.COM lexp->arg = arg; 9658462SApril.Chin@Sun.COM lexp->token = SYMRES; 9664887Schin } 9678462SApril.Chin@Sun.COM t = makelist(lexp,TLST,(Shnode_t*)ac,t); 9684887Schin *tp = t; 9694887Schin tp = &t->lst.lstrit; 9704887Schin } 9714887Schin *tp = (Shnode_t*)ac; 9728462SApril.Chin@Sun.COM lexp->assignok = 0; 9734887Schin return(ap); 9744887Schin } 9754887Schin 9764887Schin /* 9774887Schin * item 9784887Schin * 9794887Schin * ( cmd ) [ < in ] [ > out ] 9804887Schin * word word* [ < in ] [ > out ] 9814887Schin * if ... then ... else ... fi 9824887Schin * for ... while ... do ... done 9834887Schin * case ... in ... esac 9844887Schin * begin ... end 9854887Schin */ 9864887Schin 9878462SApril.Chin@Sun.COM static Shnode_t *item(Lex_t *lexp,int flag) 9884887Schin { 9894887Schin register Shnode_t *t; 9904887Schin register struct ionod *io; 9918462SApril.Chin@Sun.COM register int tok = (lexp->token&0xff); 9928462SApril.Chin@Sun.COM int savwdval = lexp->lasttok; 9938462SApril.Chin@Sun.COM int savline = lexp->lastline; 9948462SApril.Chin@Sun.COM int showme=0, comsub; 9958462SApril.Chin@Sun.COM if(!(flag&SH_NOIO) && (tok=='<' || tok=='>' || lexp->token==IOVNAME)) 9968462SApril.Chin@Sun.COM io=inout(lexp,NIL(struct ionod*),1); 9974887Schin else 9984887Schin io=0; 9998462SApril.Chin@Sun.COM if((tok=lexp->token) && tok!=EOFSYM && tok!=FUNCTSYM) 10004887Schin { 10018462SApril.Chin@Sun.COM lexp->lastline = sh_getlineno(lexp); 10028462SApril.Chin@Sun.COM lexp->lasttok = lexp->token; 10034887Schin } 10044887Schin switch(tok) 10054887Schin { 10064887Schin /* [[ ... ]] test expression */ 10074887Schin case BTESTSYM: 10088462SApril.Chin@Sun.COM t = test_expr(lexp,ETESTSYM); 10094887Schin t->tre.tretyp &= ~TTEST; 10104887Schin break; 10114887Schin /* ((...)) arithmetic expression */ 10124887Schin case EXPRSYM: 10138462SApril.Chin@Sun.COM t = getanode(lexp,lexp->arg); 10148462SApril.Chin@Sun.COM sh_lex(lexp); 10154887Schin goto done; 10164887Schin 10174887Schin /* case statement */ 10184887Schin case CASESYM: 10194887Schin { 10208462SApril.Chin@Sun.COM int savetok = lexp->lasttok; 10218462SApril.Chin@Sun.COM int saveline = lexp->lastline; 10224887Schin t = getnode(swnod); 10238462SApril.Chin@Sun.COM if(sh_lex(lexp)) 10248462SApril.Chin@Sun.COM sh_syntax(lexp); 10258462SApril.Chin@Sun.COM t->sw.swarg=lexp->arg; 10264887Schin t->sw.swtyp=TSW; 10274887Schin t->sw.swio = 0; 10284887Schin t->sw.swtyp |= FLINENO; 10298462SApril.Chin@Sun.COM t->sw.swline = lexp->sh->inlineno; 10308462SApril.Chin@Sun.COM if((tok=skipnl(lexp,0))!=INSYM && tok!=LBRACE) 10318462SApril.Chin@Sun.COM sh_syntax(lexp); 10328462SApril.Chin@Sun.COM if(!(t->sw.swlst=syncase(lexp,tok==INSYM?ESACSYM:RBRACE)) && lexp->token==EOFSYM) 10334887Schin { 10348462SApril.Chin@Sun.COM lexp->lasttok = savetok; 10358462SApril.Chin@Sun.COM lexp->lastline = saveline; 10368462SApril.Chin@Sun.COM sh_syntax(lexp); 10374887Schin } 10384887Schin break; 10394887Schin } 10404887Schin 10414887Schin /* if statement */ 10424887Schin case IFSYM: 10434887Schin { 10444887Schin register Shnode_t *tt; 10454887Schin t = getnode(ifnod); 10464887Schin t->if_.iftyp=TIF; 10478462SApril.Chin@Sun.COM t->if_.iftre=sh_cmd(lexp,THENSYM,SH_NL); 10488462SApril.Chin@Sun.COM t->if_.thtre=sh_cmd(lexp,ELSESYM,SH_NL|SH_SEMI); 10498462SApril.Chin@Sun.COM tok = lexp->token; 10508462SApril.Chin@Sun.COM t->if_.eltre=(tok==ELSESYM?sh_cmd(lexp,FISYM,SH_NL|SH_SEMI): 10518462SApril.Chin@Sun.COM (tok==ELIFSYM?(lexp->token=IFSYM, tt=item(lexp,SH_NOIO)):0)); 10524887Schin if(tok==ELIFSYM) 10534887Schin { 10544887Schin if(!tt || tt->tre.tretyp!=TSETIO) 10554887Schin goto done; 10564887Schin t->if_.eltre = tt->fork.forktre; 10574887Schin tt->fork.forktre = t; 10584887Schin t = tt; 10594887Schin goto done; 10604887Schin } 10614887Schin break; 10624887Schin } 10634887Schin 10644887Schin /* for and select statement */ 10654887Schin case FORSYM: 10664887Schin case SELECTSYM: 10674887Schin { 10684887Schin t = getnode(fornod); 10698462SApril.Chin@Sun.COM t->for_.fortyp=(lexp->token==FORSYM?TFOR:TSELECT); 10704887Schin t->for_.forlst=0; 10718462SApril.Chin@Sun.COM t->for_.forline = lexp->sh->inlineno; 10728462SApril.Chin@Sun.COM if(sh_lex(lexp)) 10734887Schin { 10748462SApril.Chin@Sun.COM if(lexp->token!=EXPRSYM || t->for_.fortyp!=TFOR) 10758462SApril.Chin@Sun.COM sh_syntax(lexp); 10764887Schin /* arithmetic for */ 10778462SApril.Chin@Sun.COM t = arithfor(lexp,t); 10784887Schin break; 10794887Schin } 10808462SApril.Chin@Sun.COM t->for_.fornam=(char*) lexp->arg->argval; 10814887Schin t->for_.fortyp |= FLINENO; 10824887Schin #if SHOPT_KIA 10838462SApril.Chin@Sun.COM if(lexp->kiafile) 10848462SApril.Chin@Sun.COM writedefs(lexp,lexp->arg,lexp->sh->inlineno,'v',NIL(struct argnod*)); 10854887Schin #endif /* SHOPT_KIA */ 10868462SApril.Chin@Sun.COM while((tok=sh_lex(lexp))==NL); 10874887Schin if(tok==INSYM) 10884887Schin { 10898462SApril.Chin@Sun.COM if(sh_lex(lexp)) 10904887Schin { 10918462SApril.Chin@Sun.COM if(lexp->token != NL && lexp->token !=';') 10928462SApril.Chin@Sun.COM sh_syntax(lexp); 10934887Schin /* some Linux scripts assume this */ 10944887Schin if(sh_isoption(SH_NOEXEC)) 10958462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_warn(0),e_lexemptyfor,lexp->sh->inlineno-(lexp->token=='\n')); 10964887Schin t->for_.forlst = (struct comnod*)getnode(comnod); 10974887Schin (t->for_.forlst)->comarg = 0; 10984887Schin (t->for_.forlst)->comset = 0; 10994887Schin (t->for_.forlst)->comnamp = 0; 11004887Schin (t->for_.forlst)->comnamq = 0; 11014887Schin (t->for_.forlst)->comstate = 0; 11024887Schin (t->for_.forlst)->comio = 0; 11034887Schin (t->for_.forlst)->comtyp = 0; 11044887Schin } 11054887Schin else 11068462SApril.Chin@Sun.COM t->for_.forlst=(struct comnod*)simple(lexp,SH_NOIO,NIL(struct ionod*)); 11078462SApril.Chin@Sun.COM if(lexp->token != NL && lexp->token !=';') 11088462SApril.Chin@Sun.COM sh_syntax(lexp); 11098462SApril.Chin@Sun.COM tok = skipnl(lexp,0); 11104887Schin } 11114887Schin /* 'for i;do cmd' is valid syntax */ 11124887Schin else if(tok==';') 11138462SApril.Chin@Sun.COM tok=sh_lex(lexp); 11144887Schin if(tok!=DOSYM && tok!=LBRACE) 11158462SApril.Chin@Sun.COM sh_syntax(lexp); 11164887Schin loop_level++; 11178462SApril.Chin@Sun.COM t->for_.fortre=sh_cmd(lexp,tok==DOSYM?DONESYM:RBRACE,SH_NL|SH_SEMI); 11184887Schin if(--loop_level==0) 11194887Schin label_last = label_list; 11204887Schin break; 11214887Schin } 11224887Schin 11234887Schin /* This is the code for parsing function definitions */ 11244887Schin case FUNCTSYM: 11258462SApril.Chin@Sun.COM return(funct(lexp)); 11264887Schin 11274887Schin #if SHOPT_NAMESPACE 11284887Schin case NSPACESYM: 11294887Schin t = getnode(fornod); 11304887Schin t->for_.fortyp=TNSPACE; 11314887Schin t->for_.forlst=0; 11328462SApril.Chin@Sun.COM if(sh_lex(lexp)) 11338462SApril.Chin@Sun.COM sh_syntax(lexp); 11348462SApril.Chin@Sun.COM t->for_.fornam=(char*) lexp->arg->argval; 11358462SApril.Chin@Sun.COM while((tok=sh_lex(lexp))==NL); 11364887Schin if(tok!=LBRACE) 11378462SApril.Chin@Sun.COM sh_syntax(lexp); 11388462SApril.Chin@Sun.COM t->for_.fortre = sh_cmd(lexp,RBRACE,SH_NL); 11394887Schin break; 11404887Schin #endif /* SHOPT_NAMESPACE */ 11414887Schin 11424887Schin /* while and until */ 11434887Schin case WHILESYM: 11444887Schin case UNTILSYM: 11454887Schin t = getnode(whnod); 11468462SApril.Chin@Sun.COM t->wh.whtyp=(lexp->token==WHILESYM ? TWH : TUN); 11474887Schin loop_level++; 11488462SApril.Chin@Sun.COM t->wh.whtre = sh_cmd(lexp,DOSYM,SH_NL); 11498462SApril.Chin@Sun.COM t->wh.dotre = sh_cmd(lexp,DONESYM,SH_NL|SH_SEMI); 11504887Schin if(--loop_level==0) 11514887Schin label_last = label_list; 11524887Schin t->wh.whinc = 0; 11534887Schin break; 11544887Schin 11554887Schin case LABLSYM: 11564887Schin { 11574887Schin register struct argnod *argp = label_list; 11584887Schin while(argp) 11594887Schin { 11608462SApril.Chin@Sun.COM if(strcmp(argp->argval,lexp->arg->argval)==0) 11618462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax3,lexp->sh->inlineno,argp->argval); 11624887Schin argp = argp->argnxt.ap; 11634887Schin } 11648462SApril.Chin@Sun.COM lexp->arg->argnxt.ap = label_list; 11658462SApril.Chin@Sun.COM label_list = lexp->arg; 11668462SApril.Chin@Sun.COM label_list->argchn.len = sh_getlineno(lexp); 11674887Schin label_list->argflag = loop_level; 11688462SApril.Chin@Sun.COM skipnl(lexp,flag); 11698462SApril.Chin@Sun.COM if(!(t = item(lexp,SH_NL))) 11708462SApril.Chin@Sun.COM sh_syntax(lexp); 11714887Schin tok = (t->tre.tretyp&(COMSCAN|COMSCAN-1)); 11724887Schin if(sh_isoption(SH_NOEXEC) && tok!=TWH && tok!=TUN && tok!=TFOR && tok!=TSELECT) 11734887Schin errormsg(SH_DICT,ERROR_warn(0),e_lexlabignore,label_list->argchn.len,label_list->argval); 11744887Schin return(t); 11754887Schin } 11764887Schin 11774887Schin /* command group with {...} */ 11784887Schin case LBRACE: 11798462SApril.Chin@Sun.COM comsub = lexp->comsub; 11808462SApril.Chin@Sun.COM lexp->comsub = 0; 1181*10898Sroland.mainz@nrubsig.org t = sh_cmd(lexp,RBRACE,SH_NL|SH_SEMI); 11828462SApril.Chin@Sun.COM lexp->comsub = comsub; 11834887Schin break; 11844887Schin 11854887Schin case LPAREN: 11864887Schin t = getnode(parnod); 1187*10898Sroland.mainz@nrubsig.org t->par.partre=sh_cmd(lexp,RPAREN,SH_NL|SH_SEMI); 11884887Schin t->par.partyp=TPAR; 11894887Schin break; 11904887Schin 11914887Schin default: 11924887Schin if(io==0) 11934887Schin return(0); 11944887Schin 11954887Schin case ';': 11964887Schin if(io==0) 11974887Schin { 11984887Schin if(!(flag&SH_SEMI)) 11994887Schin return(0); 12008462SApril.Chin@Sun.COM if(sh_lex(lexp)==';') 12018462SApril.Chin@Sun.COM sh_syntax(lexp); 12024887Schin showme = FSHOWME; 12034887Schin } 12044887Schin /* simple command */ 12054887Schin case 0: 12068462SApril.Chin@Sun.COM t = (Shnode_t*)simple(lexp,flag,io); 12078462SApril.Chin@Sun.COM if(t->com.comarg && lexp->intypeset && (lexp->sh->shcomp || sh_isoption(SH_NOEXEC) || sh.dot_depth)) 12088462SApril.Chin@Sun.COM check_typedef(&t->com); 12098462SApril.Chin@Sun.COM lexp->intypeset = 0; 12108462SApril.Chin@Sun.COM lexp->inexec = 0; 12114887Schin t->tre.tretyp |= showme; 12124887Schin return(t); 12134887Schin } 12148462SApril.Chin@Sun.COM sh_lex(lexp); 12158462SApril.Chin@Sun.COM if(io=inout(lexp,io,0)) 12164887Schin { 12174887Schin if((tok=t->tre.tretyp&COMMSK) != TFORK) 12184887Schin tok = TSETIO; 12198462SApril.Chin@Sun.COM t=makeparent(lexp,tok,t); 12204887Schin t->tre.treio=io; 12214887Schin } 12224887Schin done: 12238462SApril.Chin@Sun.COM lexp->lasttok = savwdval; 12248462SApril.Chin@Sun.COM lexp->lastline = savline; 12254887Schin return(t); 12264887Schin } 12274887Schin 1228*10898Sroland.mainz@nrubsig.org static struct argnod *process_sub(Lex_t *lexp,int tok) 1229*10898Sroland.mainz@nrubsig.org { 1230*10898Sroland.mainz@nrubsig.org struct argnod *argp; 1231*10898Sroland.mainz@nrubsig.org Shnode_t *t; 1232*10898Sroland.mainz@nrubsig.org int mode = (tok==OPROCSYM); 1233*10898Sroland.mainz@nrubsig.org t = sh_cmd(lexp,RPAREN,SH_NL); 1234*10898Sroland.mainz@nrubsig.org argp = (struct argnod*)stkalloc(lexp->sh->stk,sizeof(struct argnod)); 1235*10898Sroland.mainz@nrubsig.org *argp->argval = 0; 1236*10898Sroland.mainz@nrubsig.org argp->argchn.ap = (struct argnod*)makeparent(lexp,mode?TFORK|FPIN|FAMP|FPCL:TFORK|FPOU,t); 1237*10898Sroland.mainz@nrubsig.org argp->argflag = (ARG_EXP|mode); 1238*10898Sroland.mainz@nrubsig.org return(argp); 1239*10898Sroland.mainz@nrubsig.org } 1240*10898Sroland.mainz@nrubsig.org 1241*10898Sroland.mainz@nrubsig.org 12424887Schin /* 12434887Schin * This is for a simple command, for list, or compound assignment 12444887Schin */ 12458462SApril.Chin@Sun.COM static Shnode_t *simple(Lex_t *lexp,int flag, struct ionod *io) 12464887Schin { 12474887Schin register struct comnod *t; 12484887Schin register struct argnod *argp; 12494887Schin register int tok; 12508462SApril.Chin@Sun.COM Stk_t *stkp = lexp->sh->stk; 12514887Schin struct argnod **argtail; 12524887Schin struct argnod **settail; 12538462SApril.Chin@Sun.COM int cmdarg=0; 12548462SApril.Chin@Sun.COM int argno = 0, argmax=0; 12554887Schin int assignment = 0; 12564887Schin int key_on = (!(flag&SH_NOIO) && sh_isoption(SH_KEYWORD)); 12574887Schin int associative=0; 12588462SApril.Chin@Sun.COM if((argp=lexp->arg) && (argp->argflag&ARG_ASSIGN) && argp->argval[0]=='[') 12594887Schin { 12604887Schin flag |= SH_ARRAY; 12614887Schin associative = 1; 12624887Schin } 12634887Schin t = (struct comnod*)getnode(comnod); 12644887Schin t->comio=io; /*initial io chain*/ 12654887Schin /* set command line number for error messages */ 12668462SApril.Chin@Sun.COM t->comline = sh_getlineno(lexp); 12674887Schin argtail = &(t->comarg); 12684887Schin t->comset = 0; 12694887Schin t->comnamp = 0; 12704887Schin t->comnamq = 0; 12714887Schin t->comstate = 0; 12724887Schin settail = &(t->comset); 12738462SApril.Chin@Sun.COM while(lexp->token==0) 12744887Schin { 12758462SApril.Chin@Sun.COM argp = lexp->arg; 12764887Schin if(*argp->argval==LBRACE && (flag&SH_FUNDEF) && argp->argval[1]==0) 12774887Schin { 12788462SApril.Chin@Sun.COM lexp->token = LBRACE; 12794887Schin break; 12804887Schin } 12814887Schin if(associative && argp->argval[0]!='[') 12828462SApril.Chin@Sun.COM sh_syntax(lexp); 12834887Schin /* check for assignment argument */ 12844887Schin if((argp->argflag&ARG_ASSIGN) && assignment!=2) 12854887Schin { 12864887Schin *settail = argp; 12874887Schin settail = &(argp->argnxt.ap); 12888462SApril.Chin@Sun.COM lexp->assignok = (flag&SH_ASSIGN)?SH_ASSIGN:1; 12894887Schin if(assignment) 12904887Schin { 12914887Schin struct argnod *ap=argp; 12924887Schin char *last, *cp; 12934887Schin if(assignment==1) 12944887Schin { 12954887Schin last = strchr(argp->argval,'='); 1296*10898Sroland.mainz@nrubsig.org if(last && (last[-1]==']'|| (last[-1]=='+' && last[-2]==']')) && (cp=strchr(argp->argval,'[')) && (cp < last)) 12974887Schin last = cp; 12988462SApril.Chin@Sun.COM stkseek(stkp,ARGVAL); 12998462SApril.Chin@Sun.COM sfwrite(stkp,argp->argval,last-argp->argval); 13008462SApril.Chin@Sun.COM ap=(struct argnod*)stkfreeze(stkp,1); 13014887Schin ap->argflag = ARG_RAW; 13024887Schin ap->argchn.ap = 0; 13034887Schin } 13044887Schin *argtail = ap; 13054887Schin argtail = &(ap->argnxt.ap); 13064887Schin if(argno>=0) 13074887Schin argno++; 13084887Schin } 13094887Schin else /* alias substitutions allowed */ 13108462SApril.Chin@Sun.COM lexp->aliasok = 1; 13114887Schin } 13124887Schin else 13134887Schin { 13144887Schin if(!(argp->argflag&ARG_RAW)) 13158462SApril.Chin@Sun.COM { 13168462SApril.Chin@Sun.COM if(argno>0) 13178462SApril.Chin@Sun.COM argmax = argno; 13184887Schin argno = -1; 13198462SApril.Chin@Sun.COM } 13208462SApril.Chin@Sun.COM if(argno>=0 && argno++==cmdarg && !(flag&SH_ARRAY) && *argp->argval!='/') 13214887Schin { 13224887Schin /* check for builtin command */ 13238462SApril.Chin@Sun.COM Namval_t *np=nv_bfsearch(argp->argval,lexp->sh->fun_tree, (Namval_t**)&t->comnamq,(char**)0); 13248462SApril.Chin@Sun.COM if(cmdarg==0) 13258462SApril.Chin@Sun.COM t->comnamp = (void*)np; 13268462SApril.Chin@Sun.COM if(np && is_abuiltin(np)) 13274887Schin { 13288462SApril.Chin@Sun.COM if(nv_isattr(np,BLT_DCL)) 13298462SApril.Chin@Sun.COM { 13308462SApril.Chin@Sun.COM assignment = 1+(*argp->argval=='a'); 13318462SApril.Chin@Sun.COM if(np==SYSTYPESET) 13328462SApril.Chin@Sun.COM lexp->intypeset = 1; 13338462SApril.Chin@Sun.COM key_on = 1; 13348462SApril.Chin@Sun.COM } 13358462SApril.Chin@Sun.COM else if(np==SYSCOMMAND) 13368462SApril.Chin@Sun.COM cmdarg++; 13378462SApril.Chin@Sun.COM else if(np==SYSEXEC) 13388462SApril.Chin@Sun.COM lexp->inexec = 1; 13398462SApril.Chin@Sun.COM else if(np->nvalue.bfp==b_getopts) 13408462SApril.Chin@Sun.COM opt_get |= FOPTGET; 13414887Schin } 13424887Schin } 13434887Schin *argtail = argp; 13444887Schin argtail = &(argp->argnxt.ap); 13458462SApril.Chin@Sun.COM if(!(lexp->assignok=key_on) && !(flag&SH_NOIO) && sh_isoption(SH_NOEXEC)) 13468462SApril.Chin@Sun.COM lexp->assignok = SH_COMPASSIGN; 13478462SApril.Chin@Sun.COM lexp->aliasok = 0; 13484887Schin } 13494887Schin retry: 13508462SApril.Chin@Sun.COM tok = sh_lex(lexp); 13518462SApril.Chin@Sun.COM if(tok==LABLSYM && (flag&SH_ASSIGN)) 13528462SApril.Chin@Sun.COM lexp->token = tok = 0; 13534887Schin #if SHOPT_DEVFD 13544887Schin if((tok==IPROCSYM || tok==OPROCSYM)) 13554887Schin { 1356*10898Sroland.mainz@nrubsig.org argp = process_sub(lexp,tok); 13578462SApril.Chin@Sun.COM argmax = 0; 13584887Schin argno = -1; 13594887Schin *argtail = argp; 13604887Schin argtail = &(argp->argnxt.ap); 13614887Schin goto retry; 13624887Schin } 13634887Schin #endif /* SHOPT_DEVFD */ 13644887Schin if(tok==LPAREN) 13654887Schin { 13664887Schin if(argp->argflag&ARG_ASSIGN) 13674887Schin { 13688462SApril.Chin@Sun.COM int intypeset = lexp->intypeset; 13698462SApril.Chin@Sun.COM int tdef = 0; 13708462SApril.Chin@Sun.COM lexp->intypeset = 0; 13718462SApril.Chin@Sun.COM if(t->comnamp==SYSTYPESET && t->comarg->argnxt.ap && strcmp(t->comarg->argnxt.ap->argval,"-T")==0) 13728462SApril.Chin@Sun.COM tdef = 1; 13738462SApril.Chin@Sun.COM argp = assign(lexp,argp,tdef); 13748462SApril.Chin@Sun.COM lexp->intypeset = intypeset; 13754887Schin if(associative) 13768462SApril.Chin@Sun.COM lexp->assignok |= SH_ASSIGN; 13774887Schin goto retry; 13784887Schin } 13794887Schin else if(argno==1 && !t->comset) 13804887Schin { 13814887Schin /* SVR2 style function */ 13828462SApril.Chin@Sun.COM if(sh_lex(lexp) == RPAREN) 13834887Schin { 13848462SApril.Chin@Sun.COM lexp->arg = argp; 13858462SApril.Chin@Sun.COM return(funct(lexp)); 13864887Schin } 13878462SApril.Chin@Sun.COM lexp->token = LPAREN; 13884887Schin } 13894887Schin } 13904887Schin else if(flag&SH_ASSIGN) 13914887Schin { 13924887Schin if(tok==RPAREN) 13934887Schin break; 13944887Schin else if(tok==NL && (flag&SH_ARRAY)) 13958462SApril.Chin@Sun.COM { 13968462SApril.Chin@Sun.COM lexp->comp_assign = 2; 13974887Schin goto retry; 13988462SApril.Chin@Sun.COM } 13998462SApril.Chin@Sun.COM 14004887Schin } 14014887Schin if(!(flag&SH_NOIO)) 14024887Schin { 14034887Schin if(io) 14044887Schin { 14054887Schin while(io->ionxt) 14064887Schin io = io->ionxt; 14078462SApril.Chin@Sun.COM io->ionxt = inout(lexp,(struct ionod*)0,0); 14084887Schin } 14094887Schin else 14108462SApril.Chin@Sun.COM t->comio = io = inout(lexp,(struct ionod*)0,0); 14114887Schin } 14124887Schin } 14134887Schin *argtail = 0; 14148462SApril.Chin@Sun.COM if(argno>0) 14158462SApril.Chin@Sun.COM argmax = argno; 14168462SApril.Chin@Sun.COM t->comtyp = TCOM | (argmax<<(COMBITS+2)); 14174887Schin #if SHOPT_KIA 14188462SApril.Chin@Sun.COM if(lexp->kiafile && !(flag&SH_NOIO)) 14194887Schin { 14204887Schin register Namval_t *np=(Namval_t*)t->comnamp; 14214887Schin unsigned long r=0; 14224887Schin int line = t->comline; 14234887Schin argp = t->comarg; 14244887Schin if(np) 14258462SApril.Chin@Sun.COM r = kiaentity(lexp,nv_name(np),-1,'p',-1,0,lexp->unknown,'b',0,""); 14264887Schin else if(argp) 14278462SApril.Chin@Sun.COM r = kiaentity(lexp,sh_argstr(argp),-1,'p',-1,0,lexp->unknown,'c',0,""); 14284887Schin if(r>0) 14298462SApril.Chin@Sun.COM sfprintf(lexp->kiatmp,"p;%..64d;p;%..64d;%d;%d;c;\n",lexp->current,r,line,line); 14304887Schin if(t->comset && argno==0) 14318462SApril.Chin@Sun.COM writedefs(lexp,t->comset,line,'v',t->comarg); 14324887Schin else if(np && nv_isattr(np,BLT_DCL)) 14338462SApril.Chin@Sun.COM writedefs(lexp,argp,line,0,NIL(struct argnod*)); 14344887Schin else if(argp && strcmp(argp->argval,"read")==0) 14358462SApril.Chin@Sun.COM writedefs(lexp,argp,line,0,NIL(struct argnod*)); 14364887Schin #if 0 14374887Schin else if(argp && strcmp(argp->argval,"unset")==0) 14388462SApril.Chin@Sun.COM writedefs(lexp,argp,line,'u',NIL(struct argnod*)); 14394887Schin #endif 14404887Schin else if(argp && *argp->argval=='.' && argp->argval[1]==0 && (argp=argp->argnxt.ap)) 14414887Schin { 14428462SApril.Chin@Sun.COM r = kiaentity(lexp,sh_argstr(argp),-1,'p',0,0,lexp->script,'d',0,""); 14438462SApril.Chin@Sun.COM sfprintf(lexp->kiatmp,"p;%..64d;p;%..64d;%d;%d;d;\n",lexp->current,r,line,line); 14444887Schin } 14454887Schin } 14464887Schin #endif /* SHOPT_KIA */ 14474887Schin if(t->comnamp && (argp=t->comarg->argnxt.ap)) 14484887Schin { 14494887Schin Namval_t *np=(Namval_t*)t->comnamp; 14504887Schin if((np==SYSBREAK || np==SYSCONT) && (argp->argflag&ARG_RAW) && !isdigit(*argp->argval)) 14514887Schin { 14524887Schin register char *cp = argp->argval; 14534887Schin /* convert break/continue labels to numbers */ 14544887Schin tok = 0; 14554887Schin for(argp=label_list;argp!=label_last;argp=argp->argnxt.ap) 14564887Schin { 14574887Schin if(strcmp(cp,argp->argval)) 14584887Schin continue; 14594887Schin tok = loop_level-argp->argflag; 14604887Schin if(tok>=1) 14614887Schin { 14624887Schin argp = t->comarg->argnxt.ap; 14634887Schin if(tok>9) 14644887Schin { 14654887Schin argp->argval[1] = '0'+tok%10; 14664887Schin argp->argval[2] = 0; 14674887Schin tok /= 10; 14684887Schin } 14694887Schin else 14704887Schin argp->argval[1] = 0; 14714887Schin *argp->argval = '0'+tok; 14724887Schin } 14734887Schin break; 14744887Schin } 14754887Schin if(sh_isoption(SH_NOEXEC) && tok==0) 14768462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_warn(0),e_lexlabunknown,lexp->sh->inlineno-(lexp->token=='\n'),cp); 14774887Schin } 14784887Schin else if(sh_isoption(SH_NOEXEC) && np==SYSSET && ((tok= *argp->argval)=='-'||tok=='+') && 14794887Schin (argp->argval[1]==0||strchr(argp->argval,'k'))) 14808462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete5,lexp->sh->inlineno-(lexp->token=='\n'),argp->argval); 14814887Schin } 14824887Schin /* expand argument list if possible */ 14834887Schin if(argno>0) 14844887Schin t->comarg = qscan(t,argno); 14854887Schin else if(t->comarg) 14864887Schin t->comtyp |= COMSCAN; 14878462SApril.Chin@Sun.COM lexp->aliasok = 0; 14884887Schin return((Shnode_t*)t); 14894887Schin } 14904887Schin 14914887Schin /* 14924887Schin * skip past newlines but issue prompt if interactive 14934887Schin */ 14948462SApril.Chin@Sun.COM static int skipnl(Lex_t *lexp,int flag) 14954887Schin { 14964887Schin register int token; 14978462SApril.Chin@Sun.COM while((token=sh_lex(lexp))==NL); 14984887Schin if(token==';' && !(flag&SH_SEMI)) 14998462SApril.Chin@Sun.COM sh_syntax(lexp); 15004887Schin return(token); 15014887Schin } 15024887Schin 15034887Schin /* 15044887Schin * check for and process and i/o redirections 15054887Schin * if flag>0 then an alias can be in the next word 15064887Schin * if flag<0 only one redirection will be processed 15074887Schin */ 15088462SApril.Chin@Sun.COM static struct ionod *inout(Lex_t *lexp,struct ionod *lastio,int flag) 15094887Schin { 15108462SApril.Chin@Sun.COM register int iof = lexp->digits, token=lexp->token; 15114887Schin register struct ionod *iop; 15128462SApril.Chin@Sun.COM Stk_t *stkp = lexp->sh->stk; 15134887Schin char *iovname=0; 15144887Schin register int errout=0; 15154887Schin if(token==IOVNAME) 15164887Schin { 15178462SApril.Chin@Sun.COM iovname=lexp->arg->argval+1; 15188462SApril.Chin@Sun.COM token= sh_lex(lexp); 15194887Schin iof = 0; 15204887Schin } 15214887Schin switch(token&0xff) 15224887Schin { 15234887Schin case '<': 15244887Schin if(token==IODOCSYM) 15254887Schin iof |= (IODOC|IORAW); 15264887Schin else if(token==IOMOV0SYM) 15274887Schin iof |= IOMOV; 1528*10898Sroland.mainz@nrubsig.org else if(token==IORDWRSYMT) 1529*10898Sroland.mainz@nrubsig.org iof |= IORDW|IOREWRITE; 15304887Schin else if(token==IORDWRSYM) 15314887Schin iof |= IORDW; 15324887Schin else if((token&SYMSHARP) == SYMSHARP) 15334887Schin { 15344887Schin int n; 15354887Schin iof |= IOLSEEK; 15364887Schin if(fcgetc(n)=='#') 15374887Schin iof |= IOCOPY; 15384887Schin else if(n>0) 15394887Schin fcseek(-1); 15404887Schin } 15414887Schin break; 15424887Schin 15434887Schin case '>': 15444887Schin if(iof<0) 15454887Schin { 15464887Schin errout = 1; 15474887Schin iof = 1; 15484887Schin } 15494887Schin iof |= IOPUT; 15504887Schin if(token==IOAPPSYM) 15514887Schin iof |= IOAPP; 15524887Schin else if(token==IOMOV1SYM) 15534887Schin iof |= IOMOV; 15544887Schin else if(token==IOCLOBSYM) 15554887Schin iof |= IOCLOB; 15564887Schin else if((token&SYMSHARP) == SYMSHARP) 15574887Schin iof |= IOLSEEK; 15588462SApril.Chin@Sun.COM else if((token&SYMSEMI) == SYMSEMI) 15598462SApril.Chin@Sun.COM iof |= IOREWRITE; 15604887Schin break; 15614887Schin 15624887Schin default: 15634887Schin return(lastio); 15644887Schin } 15658462SApril.Chin@Sun.COM lexp->digits=0; 15668462SApril.Chin@Sun.COM iop=(struct ionod*) stkalloc(stkp,sizeof(struct ionod)); 15674887Schin iop->iodelim = 0; 15688462SApril.Chin@Sun.COM if(token=sh_lex(lexp)) 15694887Schin { 15708462SApril.Chin@Sun.COM if(token==RPAREN && (iof&IOLSEEK) && lexp->comsub) 15714887Schin { 15728462SApril.Chin@Sun.COM lexp->arg = (struct argnod*)stkalloc(stkp,sizeof(struct argnod)+3); 15738462SApril.Chin@Sun.COM strcpy(lexp->arg->argval,"CUR"); 15748462SApril.Chin@Sun.COM lexp->arg->argflag = ARG_RAW; 15754887Schin iof |= IOARITH; 15764887Schin fcseek(-1); 15774887Schin } 15784887Schin else if(token==EXPRSYM && (iof&IOLSEEK)) 15794887Schin iof |= IOARITH; 1580*10898Sroland.mainz@nrubsig.org else if(((token==IPROCSYM && !(iof&IOPUT)) || (token==OPROCSYM && (iof&IOPUT))) && !(iof&(IOLSEEK|IOREWRITE|IOMOV|IODOC))) 1581*10898Sroland.mainz@nrubsig.org { 1582*10898Sroland.mainz@nrubsig.org lexp->arg = process_sub(lexp,token); 1583*10898Sroland.mainz@nrubsig.org iof |= IOPROCSUB; 1584*10898Sroland.mainz@nrubsig.org } 15854887Schin else 15868462SApril.Chin@Sun.COM sh_syntax(lexp); 15874887Schin } 1588*10898Sroland.mainz@nrubsig.org if( (iof&IOPROCSUB) && !(iof&IOLSEEK)) 1589*10898Sroland.mainz@nrubsig.org iop->ioname= (char*)lexp->arg->argchn.ap; 1590*10898Sroland.mainz@nrubsig.org else 1591*10898Sroland.mainz@nrubsig.org iop->ioname=lexp->arg->argval; 15924887Schin iop->iovname = iovname; 15934887Schin if(iof&IODOC) 15944887Schin { 15958462SApril.Chin@Sun.COM if(lexp->digits==2) 15964887Schin { 15974887Schin iof |= IOSTRG; 15988462SApril.Chin@Sun.COM if(!(lexp->arg->argflag&ARG_RAW)) 15994887Schin iof &= ~IORAW; 16004887Schin } 16014887Schin else 16024887Schin { 16038462SApril.Chin@Sun.COM if(!lexp->sh->heredocs) 16048462SApril.Chin@Sun.COM lexp->sh->heredocs = sftmp(HERE_MEM); 16058462SApril.Chin@Sun.COM iop->iolst=lexp->heredoc; 16068462SApril.Chin@Sun.COM lexp->heredoc=iop; 16078462SApril.Chin@Sun.COM if(lexp->arg->argflag&ARG_QUOTED) 16084887Schin iof |= IOQUOTE; 16098462SApril.Chin@Sun.COM if(lexp->digits==3) 16104887Schin iof |= IOLSEEK; 16118462SApril.Chin@Sun.COM if(lexp->digits) 16124887Schin iof |= IOSTRIP; 16134887Schin } 16144887Schin } 16154887Schin else 16164887Schin { 16174887Schin iop->iolst = 0; 16188462SApril.Chin@Sun.COM if(lexp->arg->argflag&ARG_RAW) 16194887Schin iof |= IORAW; 16204887Schin } 16214887Schin iop->iofile=iof; 16224887Schin if(flag>0) 16234887Schin /* allow alias substitutions and parameter assignments */ 16248462SApril.Chin@Sun.COM lexp->aliasok = lexp->assignok = 1; 16254887Schin #if SHOPT_KIA 16268462SApril.Chin@Sun.COM if(lexp->kiafile) 16274887Schin { 16288462SApril.Chin@Sun.COM int n = lexp->sh->inlineno-(lexp->token=='\n'); 16294887Schin if(!(iof&IOMOV)) 16304887Schin { 16318462SApril.Chin@Sun.COM unsigned long r=kiaentity(lexp,(iof&IORAW)?sh_fmtq(iop->ioname):iop->ioname,-1,'f',0,0,lexp->script,'f',0,""); 16328462SApril.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); 16334887Schin } 16344887Schin } 16354887Schin #endif /* SHOPT_KIA */ 16364887Schin if(flag>=0) 16374887Schin { 16384887Schin struct ionod *ioq=iop; 16398462SApril.Chin@Sun.COM sh_lex(lexp); 16404887Schin if(errout) 16414887Schin { 16424887Schin /* redirect standard output to standard error */ 16438462SApril.Chin@Sun.COM ioq = (struct ionod*)stkalloc(stkp,sizeof(struct ionod)); 1644*10898Sroland.mainz@nrubsig.org memset(ioq,0,sizeof(*ioq)); 16454887Schin ioq->ioname = "1"; 16464887Schin ioq->iolst = 0; 16474887Schin ioq->iodelim = 0; 16484887Schin ioq->iofile = IORAW|IOPUT|IOMOV|2; 16494887Schin iop->ionxt=ioq; 16504887Schin } 16518462SApril.Chin@Sun.COM ioq->ionxt=inout(lexp,lastio,flag); 16524887Schin } 16534887Schin else 16544887Schin iop->ionxt=0; 16554887Schin return(iop); 16564887Schin } 16574887Schin 16584887Schin /* 16594887Schin * convert argument chain to argument list when no special arguments 16604887Schin */ 16614887Schin 16624887Schin static struct argnod *qscan(struct comnod *ac,int argn) 16634887Schin { 16644887Schin register char **cp; 16654887Schin register struct argnod *ap; 16664887Schin register struct dolnod* dp; 16674887Schin register int special=0; 16684887Schin /* special hack for test -t compatibility */ 16694887Schin if((Namval_t*)ac->comnamp==SYSTEST) 16704887Schin special = 2; 16714887Schin else if(*(ac->comarg->argval)=='[' && ac->comarg->argval[1]==0) 16724887Schin special = 3; 16734887Schin if(special) 16744887Schin { 16754887Schin ap = ac->comarg->argnxt.ap; 16764887Schin if(argn==(special+1) && ap->argval[1]==0 && *ap->argval=='!') 16774887Schin ap = ap->argnxt.ap; 16784887Schin else if(argn!=special) 16794887Schin special=0; 16804887Schin } 16814887Schin if(special) 16824887Schin { 16834887Schin const char *message; 16844887Schin if(strcmp(ap->argval,"-t")) 16854887Schin { 16864887Schin message = "line %d: Invariant test"; 16874887Schin special=0; 16884887Schin } 16894887Schin else 16904887Schin { 16914887Schin message = "line %d: -t requires argument"; 16924887Schin argn++; 16934887Schin } 16944887Schin if(sh_isoption(SH_NOEXEC)) 16954887Schin errormsg(SH_DICT,ERROR_warn(0),message,ac->comline); 16964887Schin } 16974887Schin /* leave space for an extra argument at the front */ 16984887Schin dp = (struct dolnod*)stakalloc((unsigned)sizeof(struct dolnod) + ARG_SPARE*sizeof(char*) + argn*sizeof(char*)); 16994887Schin cp = dp->dolval+ARG_SPARE; 17004887Schin dp->dolnum = argn; 17014887Schin dp->dolbot = ARG_SPARE; 17024887Schin ap = ac->comarg; 17034887Schin while(ap) 17044887Schin { 17054887Schin *cp++ = ap->argval; 17064887Schin ap = ap->argnxt.ap; 17074887Schin } 17084887Schin if(special==3) 17094887Schin { 17104887Schin cp[0] = cp[-1]; 17114887Schin cp[-1] = "1"; 17124887Schin cp++; 17134887Schin } 17144887Schin else if(special) 17154887Schin *cp++ = "1"; 17164887Schin *cp = 0; 17174887Schin return((struct argnod*)dp); 17184887Schin } 17194887Schin 17208462SApril.Chin@Sun.COM static Shnode_t *test_expr(Lex_t *lp,int sym) 17214887Schin { 17228462SApril.Chin@Sun.COM register Shnode_t *t = test_or(lp); 17238462SApril.Chin@Sun.COM if(lp->token!=sym) 17248462SApril.Chin@Sun.COM sh_syntax(lp); 17254887Schin return(t); 17264887Schin } 17274887Schin 17288462SApril.Chin@Sun.COM static Shnode_t *test_or(Lex_t *lp) 17294887Schin { 17308462SApril.Chin@Sun.COM register Shnode_t *t = test_and(lp); 17318462SApril.Chin@Sun.COM while(lp->token==ORFSYM) 17328462SApril.Chin@Sun.COM t = makelist(lp,TORF|TTEST,t,test_and(lp)); 17334887Schin return(t); 17344887Schin } 17354887Schin 17368462SApril.Chin@Sun.COM static Shnode_t *test_and(Lex_t *lp) 17374887Schin { 17388462SApril.Chin@Sun.COM register Shnode_t *t = test_primary(lp); 17398462SApril.Chin@Sun.COM while(lp->token==ANDFSYM) 17408462SApril.Chin@Sun.COM t = makelist(lp,TAND|TTEST,t,test_primary(lp)); 17414887Schin return(t); 17424887Schin } 17434887Schin 17444887Schin /* 17454887Schin * convert =~ into == ~(E) 17464887Schin */ 17474887Schin static void ere_match(void) 17484887Schin { 17494887Schin Sfio_t *base, *iop = sfopen((Sfio_t*)0," ~(E)","s"); 17504887Schin register int c; 17514887Schin while( fcgetc(c),(c==' ' || c=='\t')); 17524887Schin if(c) 17534887Schin fcseek(-1); 17544887Schin if(!(base=fcfile())) 17554887Schin base = sfopen(NIL(Sfio_t*),fcseek(0),"s"); 17564887Schin fcclose(); 17574887Schin sfstack(base,iop); 17584887Schin fcfopen(base); 17594887Schin } 17604887Schin 17618462SApril.Chin@Sun.COM static Shnode_t *test_primary(Lex_t *lexp) 17624887Schin { 17634887Schin register struct argnod *arg; 17644887Schin register Shnode_t *t; 17654887Schin register int num,token; 17668462SApril.Chin@Sun.COM token = skipnl(lexp,0); 17678462SApril.Chin@Sun.COM num = lexp->digits; 17684887Schin switch(token) 17694887Schin { 17704887Schin case '(': 17718462SApril.Chin@Sun.COM t = test_expr(lexp,')'); 17728462SApril.Chin@Sun.COM t = makelist(lexp,TTST|TTEST|TPAREN ,t, (Shnode_t*)pointerof(lexp->sh->inlineno)); 17734887Schin break; 17744887Schin case '!': 17758462SApril.Chin@Sun.COM if(!(t = test_primary(lexp))) 17768462SApril.Chin@Sun.COM sh_syntax(lexp); 17774887Schin t->tre.tretyp |= TNEGATE; 17784887Schin return(t); 17794887Schin case TESTUNOP: 17808462SApril.Chin@Sun.COM if(sh_lex(lexp)) 17818462SApril.Chin@Sun.COM sh_syntax(lexp); 17824887Schin #if SHOPT_KIA 17838462SApril.Chin@Sun.COM if(lexp->kiafile && !strchr("sntzoOG",num)) 17844887Schin { 17858462SApril.Chin@Sun.COM int line = lexp->sh->inlineno- (lexp->token==NL); 17864887Schin unsigned long r; 17878462SApril.Chin@Sun.COM r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->script,'t',0,""); 17888462SApril.Chin@Sun.COM sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line); 17894887Schin } 17904887Schin #endif /* SHOPT_KIA */ 17918462SApril.Chin@Sun.COM t = makelist(lexp,TTST|TTEST|TUNARY|(num<<TSHIFT), 17928462SApril.Chin@Sun.COM (Shnode_t*)lexp->arg,(Shnode_t*)lexp->arg); 17938462SApril.Chin@Sun.COM t->tst.tstline = lexp->sh->inlineno; 17944887Schin break; 17954887Schin /* binary test operators */ 17964887Schin case 0: 17978462SApril.Chin@Sun.COM arg = lexp->arg; 17988462SApril.Chin@Sun.COM if((token=sh_lex(lexp))==TESTBINOP) 17994887Schin { 18008462SApril.Chin@Sun.COM num = lexp->digits; 18014887Schin if(num==TEST_REP) 18024887Schin { 18034887Schin ere_match(); 18044887Schin num = TEST_PEQ; 18054887Schin } 18064887Schin } 18074887Schin else if(token=='<') 18084887Schin num = TEST_SLT; 18094887Schin else if(token=='>') 18104887Schin num = TEST_SGT; 18114887Schin else if(token==ANDFSYM||token==ORFSYM||token==ETESTSYM||token==RPAREN) 18124887Schin { 18138462SApril.Chin@Sun.COM t = makelist(lexp,TTST|TTEST|TUNARY|('n'<<TSHIFT), 18144887Schin (Shnode_t*)arg,(Shnode_t*)arg); 18158462SApril.Chin@Sun.COM t->tst.tstline = lexp->sh->inlineno; 18164887Schin return(t); 18174887Schin } 18184887Schin else 18198462SApril.Chin@Sun.COM sh_syntax(lexp); 18204887Schin #if SHOPT_KIA 18218462SApril.Chin@Sun.COM if(lexp->kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT)) 18224887Schin { 18238462SApril.Chin@Sun.COM int line = lexp->sh->inlineno- (lexp->token==NL); 18244887Schin unsigned long r; 18258462SApril.Chin@Sun.COM r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->current,'t',0,""); 18268462SApril.Chin@Sun.COM sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line); 18274887Schin } 18284887Schin #endif /* SHOPT_KIA */ 18298462SApril.Chin@Sun.COM if(sh_lex(lexp)) 18308462SApril.Chin@Sun.COM sh_syntax(lexp); 18314887Schin if(num&TEST_PATTERN) 18324887Schin { 18338462SApril.Chin@Sun.COM if(lexp->arg->argflag&(ARG_EXP|ARG_MAC)) 18344887Schin num &= ~TEST_PATTERN; 18354887Schin } 18364887Schin t = getnode(tstnod); 18374887Schin t->lst.lsttyp = TTST|TTEST|TBINARY|(num<<TSHIFT); 18384887Schin t->lst.lstlef = (Shnode_t*)arg; 18398462SApril.Chin@Sun.COM t->lst.lstrit = (Shnode_t*)lexp->arg; 18408462SApril.Chin@Sun.COM t->tst.tstline = lexp->sh->inlineno; 18414887Schin #if SHOPT_KIA 18428462SApril.Chin@Sun.COM if(lexp->kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT)) 18434887Schin { 18448462SApril.Chin@Sun.COM int line = lexp->sh->inlineno-(lexp->token==NL); 18454887Schin unsigned long r; 18468462SApril.Chin@Sun.COM r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->current,'t',0,""); 18478462SApril.Chin@Sun.COM sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line); 18484887Schin } 18494887Schin #endif /* SHOPT_KIA */ 18504887Schin break; 18514887Schin default: 18524887Schin return(0); 18534887Schin } 18548462SApril.Chin@Sun.COM skipnl(lexp,0); 18554887Schin return(t); 18564887Schin } 18574887Schin 18584887Schin #if SHOPT_KIA 18594887Schin /* 18604887Schin * return an entity checksum 18614887Schin * The entity is created if it doesn't exist 18624887Schin */ 18638462SApril.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) 18644887Schin { 18658462SApril.Chin@Sun.COM Stk_t *stkp = lexp->sh->stk; 18664887Schin Namval_t *np; 18678462SApril.Chin@Sun.COM long offset = stktell(stkp); 18688462SApril.Chin@Sun.COM sfputc(stkp,type); 18694887Schin if(len>0) 18708462SApril.Chin@Sun.COM sfwrite(stkp,name,len); 18714887Schin else 18724887Schin { 18734887Schin if(type=='p') 18748462SApril.Chin@Sun.COM sfputr(stkp,path_basename(name),0); 18754887Schin else 18768462SApril.Chin@Sun.COM sfputr(stkp,name,0); 18774887Schin } 18788462SApril.Chin@Sun.COM np = nv_search(stakptr(offset),lexp->entity_tree,NV_ADD); 18798462SApril.Chin@Sun.COM stkseek(stkp,offset); 18804887Schin np->nvalue.i = pkind; 18814887Schin nv_setsize(np,width); 18824887Schin if(!nv_isattr(np,NV_TAGGED) && first>=0) 18834887Schin { 18844887Schin nv_onattr(np,NV_TAGGED); 18854887Schin if(!pkind) 18864887Schin pkind = '0'; 18874887Schin if(len>0) 18888462SApril.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); 18894887Schin else 18908462SApril.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); 18914887Schin } 18924887Schin return(np->hash); 18934887Schin } 18944887Schin 18954887Schin static void kia_add(register Namval_t *np, void *data) 18964887Schin { 18974887Schin char *name = nv_name(np); 18988462SApril.Chin@Sun.COM Lex_t *lp = (Lex_t*)data; 18994887Schin NOT_USED(data); 19008462SApril.Chin@Sun.COM kiaentity(lp,name+1,-1,*name,0,-1,(*name=='p'?lp->unknown:lp->script),np->nvalue.i,nv_size(np),""); 19014887Schin } 19024887Schin 19038462SApril.Chin@Sun.COM int kiaclose(Lex_t *lexp) 19044887Schin { 19054887Schin register off_t off1,off2; 19064887Schin register int n; 19078462SApril.Chin@Sun.COM if(lexp->kiafile) 19084887Schin { 19098462SApril.Chin@Sun.COM unsigned long r = kiaentity(lexp,lexp->scriptname,-1,'p',-1,lexp->sh->inlineno-1,0,'s',0,""); 19108462SApril.Chin@Sun.COM kiaentity(lexp,lexp->scriptname,-1,'p',1,lexp->sh->inlineno-1,r,'s',0,""); 19118462SApril.Chin@Sun.COM kiaentity(lexp,lexp->scriptname,-1,'f',1,lexp->sh->inlineno-1,r,'s',0,""); 19128462SApril.Chin@Sun.COM nv_scan(lexp->entity_tree,kia_add,(void*)lexp,NV_TAGGED,0); 19138462SApril.Chin@Sun.COM off1 = sfseek(lexp->kiafile,(off_t)0,SEEK_END); 19148462SApril.Chin@Sun.COM sfseek(lexp->kiatmp,(off_t)0,SEEK_SET); 19158462SApril.Chin@Sun.COM sfmove(lexp->kiatmp,lexp->kiafile,SF_UNBOUND,-1); 19168462SApril.Chin@Sun.COM off2 = sfseek(lexp->kiafile,(off_t)0,SEEK_END); 19174887Schin #ifdef SF_BUFCONST 19184887Schin if(off2==off1) 19198462SApril.Chin@Sun.COM n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%lld;%d\nDIRECTORY;",(Sflong_t)lexp->kiabegin,(size_t)(off1-lexp->kiabegin)); 19204887Schin else 19218462SApril.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)); 19224887Schin if(off2 >= INT_MAX) 19234887Schin off2 = -(n+12); 19248462SApril.Chin@Sun.COM sfprintf(lexp->kiafile,"%010.10lld;%010d\n",(Sflong_t)off2+10, n+12); 19254887Schin #else 19264887Schin if(off2==off1) 19278462SApril.Chin@Sun.COM n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%d;%d\nDIRECTORY;",lexp->kiabegin,off1-lexp->kiabegin); 19284887Schin else 19298462SApril.Chin@Sun.COM n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%d;%d\nRELATIONSHIP;%d;%d\nDIRECTORY;",lexp->kiabegin,off1-lexp->kiabegin,off1,off2-off1); 19308462SApril.Chin@Sun.COM sfprintf(lexp->kiafile,"%010d;%010d\n",off2+10, n+12); 19314887Schin #endif 19324887Schin } 19338462SApril.Chin@Sun.COM return(sfclose(lexp->kiafile)); 19344887Schin } 19354887Schin #endif /* SHOPT_KIA */ 1936