14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1982-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.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> 354887Schin #endif 364887Schin #include <ctype.h> 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 51*8462SApril.Chin@Sun.COM static Shnode_t *makeparent(Lex_t*, int, Shnode_t*); 52*8462SApril.Chin@Sun.COM static Shnode_t *makelist(Lex_t*, int, Shnode_t*, Shnode_t*); 534887Schin static struct argnod *qscan(struct comnod*, int); 54*8462SApril.Chin@Sun.COM static struct ionod *inout(Lex_t*,struct ionod*, int); 55*8462SApril.Chin@Sun.COM static Shnode_t *sh_cmd(Lex_t*,int,int); 56*8462SApril.Chin@Sun.COM static Shnode_t *term(Lex_t*,int); 57*8462SApril.Chin@Sun.COM static Shnode_t *list(Lex_t*,int); 58*8462SApril.Chin@Sun.COM static struct regnod *syncase(Lex_t*,int); 59*8462SApril.Chin@Sun.COM static Shnode_t *item(Lex_t*,int); 60*8462SApril.Chin@Sun.COM static Shnode_t *simple(Lex_t*,int, struct ionod*); 61*8462SApril.Chin@Sun.COM static int skipnl(Lex_t*,int); 62*8462SApril.Chin@Sun.COM static Shnode_t *test_expr(Lex_t*,int); 63*8462SApril.Chin@Sun.COM static Shnode_t *test_and(Lex_t*); 64*8462SApril.Chin@Sun.COM static Shnode_t *test_or(Lex_t*); 65*8462SApril.Chin@Sun.COM static Shnode_t *test_primary(Lex_t*); 664887Schin 67*8462SApril.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 83*8462SApril.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 */ 96*8462SApril.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; 106*8462SApril.Chin@Sun.COM unsigned long parent=lexp->script; 1074887Schin if(type==0) 1084887Schin { 109*8462SApril.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) 144*8462SApril.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); 152*8462SApril.Chin@Sun.COM eline = lexp->sh->inlineno-(lexp->token==NL); 153*8462SApril.Chin@Sun.COM r=kiaentity(lexp,argp->argval,n,type,line,eline,parent,justify,width,atbuff); 154*8462SApril.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 */ 160*8462SApril.Chin@Sun.COM 161*8462SApril.Chin@Sun.COM static void typeset_order(const char *str,int line) 162*8462SApril.Chin@Sun.COM { 163*8462SApril.Chin@Sun.COM register int c,n=0; 164*8462SApril.Chin@Sun.COM unsigned const char *cp=(unsigned char*)str; 165*8462SApril.Chin@Sun.COM static unsigned char *table; 166*8462SApril.Chin@Sun.COM if(*cp!='+' && *cp!='-') 167*8462SApril.Chin@Sun.COM return; 168*8462SApril.Chin@Sun.COM if(!table) 169*8462SApril.Chin@Sun.COM { 170*8462SApril.Chin@Sun.COM table = calloc(1,256); 171*8462SApril.Chin@Sun.COM for(cp=(unsigned char*)"bflmnprstuxACHS";c = *cp; cp++) 172*8462SApril.Chin@Sun.COM table[c] = 1; 173*8462SApril.Chin@Sun.COM for(cp=(unsigned char*)"aiEFLRXhTZ";c = *cp; cp++) 174*8462SApril.Chin@Sun.COM table[c] = 2; 175*8462SApril.Chin@Sun.COM for(c='0'; c <='9'; c++) 176*8462SApril.Chin@Sun.COM table[c] = 3; 177*8462SApril.Chin@Sun.COM } 178*8462SApril.Chin@Sun.COM for(cp=(unsigned char*)str; c= *cp++; n=table[c]) 179*8462SApril.Chin@Sun.COM { 180*8462SApril.Chin@Sun.COM if(table[c] < n) 181*8462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_warn(0),e_lextypeset,line,str); 182*8462SApril.Chin@Sun.COM } 183*8462SApril.Chin@Sun.COM } 184*8462SApril.Chin@Sun.COM 185*8462SApril.Chin@Sun.COM /* 186*8462SApril.Chin@Sun.COM * add type definitions when compiling with -n 187*8462SApril.Chin@Sun.COM */ 188*8462SApril.Chin@Sun.COM static void check_typedef(struct comnod *tp) 189*8462SApril.Chin@Sun.COM { 190*8462SApril.Chin@Sun.COM char *cp=0; 191*8462SApril.Chin@Sun.COM if(tp->comtyp&COMSCAN) 192*8462SApril.Chin@Sun.COM { 193*8462SApril.Chin@Sun.COM struct argnod *ap = tp->comarg; 194*8462SApril.Chin@Sun.COM while(ap = ap->argnxt.ap) 195*8462SApril.Chin@Sun.COM { 196*8462SApril.Chin@Sun.COM if(!(ap->argflag&ARG_RAW) || memcmp(ap->argval,"--",2)) 197*8462SApril.Chin@Sun.COM break; 198*8462SApril.Chin@Sun.COM if(sh_isoption(SH_NOEXEC)) 199*8462SApril.Chin@Sun.COM typeset_order(ap->argval,tp->comline); 200*8462SApril.Chin@Sun.COM if(memcmp(ap->argval,"-T",2)==0) 201*8462SApril.Chin@Sun.COM { 202*8462SApril.Chin@Sun.COM if(ap->argval[2]) 203*8462SApril.Chin@Sun.COM cp = ap->argval+2; 204*8462SApril.Chin@Sun.COM else if((ap->argnxt.ap)->argflag&ARG_RAW) 205*8462SApril.Chin@Sun.COM cp = (ap->argnxt.ap)->argval; 206*8462SApril.Chin@Sun.COM if(cp) 207*8462SApril.Chin@Sun.COM break; 208*8462SApril.Chin@Sun.COM } 209*8462SApril.Chin@Sun.COM } 210*8462SApril.Chin@Sun.COM } 211*8462SApril.Chin@Sun.COM else 212*8462SApril.Chin@Sun.COM { 213*8462SApril.Chin@Sun.COM struct dolnod *dp = (struct dolnod*)tp->comarg; 214*8462SApril.Chin@Sun.COM char **argv = dp->dolval + dp->dolbot+1; 215*8462SApril.Chin@Sun.COM while((cp= *argv++) && memcmp(cp,"--",2)) 216*8462SApril.Chin@Sun.COM { 217*8462SApril.Chin@Sun.COM if(sh_isoption(SH_NOEXEC)) 218*8462SApril.Chin@Sun.COM typeset_order(cp,tp->comline); 219*8462SApril.Chin@Sun.COM if(memcmp(cp,"-T",2)==0) 220*8462SApril.Chin@Sun.COM { 221*8462SApril.Chin@Sun.COM if(cp[2]) 222*8462SApril.Chin@Sun.COM cp = cp+2; 223*8462SApril.Chin@Sun.COM else 224*8462SApril.Chin@Sun.COM cp = *argv; 225*8462SApril.Chin@Sun.COM break; 226*8462SApril.Chin@Sun.COM } 227*8462SApril.Chin@Sun.COM } 228*8462SApril.Chin@Sun.COM } 229*8462SApril.Chin@Sun.COM if(cp) 230*8462SApril.Chin@Sun.COM { 231*8462SApril.Chin@Sun.COM Namval_t *mp=(Namval_t*)tp->comnamp ,*bp; 232*8462SApril.Chin@Sun.COM bp = sh_addbuiltin(cp,mp->nvalue.bfp, (void*)0); 233*8462SApril.Chin@Sun.COM nv_onattr(bp,nv_isattr(mp,NV_PUBLIC)); 234*8462SApril.Chin@Sun.COM } 235*8462SApril.Chin@Sun.COM } 236*8462SApril.Chin@Sun.COM 2374887Schin /* 2384887Schin * Make a parent node for fork() or io-redirection 2394887Schin */ 240*8462SApril.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; 246*8462SApril.Chin@Sun.COM par->fork.forkline = sh_getlineno(lp)-1; 2474887Schin return(par); 2484887Schin } 2494887Schin 250*8462SApril.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; 254*8462SApril.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 */ 266*8462SApril.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) 270*8462SApril.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; 292*8462SApril.Chin@Sun.COM Lex_t *lexp = (Lex_t*)shp->lex_context; 2934887Schin Fcin_t sav_input; 294*8462SApril.Chin@Sun.COM struct argnod *sav_arg = lexp->arg; 2954887Schin int sav_prompt = shp->nextprompt; 2964887Schin if(shp->binscript && sffileno(iop)==shp->infd) 297*8462SApril.Chin@Sun.COM return((void*)sh_trestore(shp,iop)); 2984887Schin fcsave(&sav_input); 2994887Schin shp->st.staklist = 0; 300*8462SApril.Chin@Sun.COM lexp->heredoc = 0; 301*8462SApril.Chin@Sun.COM lexp->inlineno = shp->inlineno; 302*8462SApril.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); 310*8462SApril.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); 323*8462SApril.Chin@Sun.COM lexp->arg = sav_arg; 3244887Schin if(version > 3) 3254887Schin errormsg(SH_DICT,ERROR_exit(1),e_lexversion); 3264887Schin if(sffileno(iop)==shp->infd) 3274887Schin shp->binscript = 1; 3284887Schin sfgetc(iop); 329*8462SApril.Chin@Sun.COM return((void*)sh_trestore(shp,iop)); 3304887Schin } 3314887Schin } 3324887Schin if((flag&SH_NL) && (shp->inlineno=error_info.line+shp->st.firstline)==0) 3334887Schin shp->inlineno=1; 3344887Schin #if KSHELL 3354887Schin shp->nextprompt = 2; 3364887Schin #endif 337*8462SApril.Chin@Sun.COM t = sh_cmd(lexp,(flag&SH_EOF)?EOFSYM:'\n',SH_SEMI|SH_EMPTY|(flag&SH_NL)); 3384887Schin fcclose(); 3394887Schin fcrestore(&sav_input); 340*8462SApril.Chin@Sun.COM lexp->arg = sav_arg; 3414887Schin /* unstack any completed alias expansions */ 3424887Schin if((sfset(iop,0,0)&SF_STRING) && !sfreserve(iop,0,-1)) 3434887Schin { 3444887Schin Sfio_t *sp = sfstack(iop,NULL); 3454887Schin if(sp) 3464887Schin sfclose(sp); 3474887Schin } 3484887Schin shp->nextprompt = sav_prompt; 3494887Schin if(flag&SH_NL) 3504887Schin { 351*8462SApril.Chin@Sun.COM shp->st.firstline = lexp->firstline; 352*8462SApril.Chin@Sun.COM shp->inlineno = lexp->inlineno; 3534887Schin } 354*8462SApril.Chin@Sun.COM stkseek(shp->stk,0); 3554887Schin return((void*)t); 3564887Schin } 3574887Schin 3584887Schin /* 3594887Schin * This routine parses up the matching right parenthesis and returns 3604887Schin * the parse tree 3614887Schin */ 362*8462SApril.Chin@Sun.COM Shnode_t *sh_dolparen(Lex_t* lp) 3634887Schin { 3644887Schin register Shnode_t *t=0; 3654887Schin Sfio_t *sp = fcfile(); 366*8462SApril.Chin@Sun.COM int line = lp->sh->inlineno; 367*8462SApril.Chin@Sun.COM lp->sh->inlineno = error_info.line+lp->sh->st.firstline; 368*8462SApril.Chin@Sun.COM sh_lexopen(lp,lp->sh,1); 369*8462SApril.Chin@Sun.COM lp->comsub = 1; 370*8462SApril.Chin@Sun.COM switch(sh_lex(lp)) 3714887Schin { 3724887Schin /* ((...)) arithmetic expression */ 3734887Schin case EXPRSYM: 374*8462SApril.Chin@Sun.COM t = getanode(lp,lp->arg); 3754887Schin break; 3764887Schin case LPAREN: 377*8462SApril.Chin@Sun.COM t = sh_cmd(lp,RPAREN,SH_NL|SH_EMPTY); 378*8462SApril.Chin@Sun.COM break; 379*8462SApril.Chin@Sun.COM case LBRACE: 380*8462SApril.Chin@Sun.COM t = sh_cmd(lp,RBRACE,SH_NL|SH_EMPTY); 3814887Schin break; 3824887Schin } 383*8462SApril.Chin@Sun.COM lp->comsub = 0; 3844887Schin if(!sp && (sp=fcfile())) 3854887Schin { 3864887Schin /* 3874887Schin * This code handles the case where string has been converted 3884887Schin * to a file by an alias setup 3894887Schin */ 3904887Schin register int c; 3914887Schin char *cp; 3924887Schin if(fcgetc(c) > 0) 3934887Schin fcseek(-1); 3944887Schin cp = fcseek(0); 3954887Schin fcclose(); 3964887Schin fcsopen(cp); 3974887Schin sfclose(sp); 3984887Schin } 399*8462SApril.Chin@Sun.COM lp->sh->inlineno = line; 4004887Schin return(t); 4014887Schin } 4024887Schin 4034887Schin /* 4044887Schin * remove temporary files and stacks 4054887Schin */ 4064887Schin 407*8462SApril.Chin@Sun.COM void sh_freeup(Shell_t *shp) 4084887Schin { 409*8462SApril.Chin@Sun.COM if(shp->st.staklist) 410*8462SApril.Chin@Sun.COM sh_funstaks(shp->st.staklist,-1); 411*8462SApril.Chin@Sun.COM shp->st.staklist = 0; 4124887Schin } 4134887Schin 4144887Schin /* 4154887Schin * increase reference count for each stack in function list when flag>0 4164887Schin * decrease reference count for each stack in function list when flag<=0 4174887Schin * stack is freed when reference count is zero 4184887Schin */ 4194887Schin 4204887Schin void sh_funstaks(register struct slnod *slp,int flag) 4214887Schin { 4224887Schin register struct slnod *slpold; 4234887Schin while(slpold=slp) 4244887Schin { 4254887Schin if(slp->slchild) 4264887Schin sh_funstaks(slp->slchild,flag); 4274887Schin slp = slp->slnext; 4284887Schin if(flag<=0) 4294887Schin stakdelete(slpold->slptr); 4304887Schin else 4314887Schin staklink(slpold->slptr); 4324887Schin } 4334887Schin } 4344887Schin /* 4354887Schin * cmd 4364887Schin * empty 4374887Schin * list 4384887Schin * list & [ cmd ] 4394887Schin * list [ ; cmd ] 4404887Schin */ 4414887Schin 442*8462SApril.Chin@Sun.COM static Shnode_t *sh_cmd(Lex_t *lexp, register int sym, int flag) 4434887Schin { 4444887Schin register Shnode_t *left, *right; 4454887Schin register int type = FINT|FAMP; 4464887Schin if(sym==NL) 447*8462SApril.Chin@Sun.COM lexp->lasttok = 0; 448*8462SApril.Chin@Sun.COM left = list(lexp,flag); 449*8462SApril.Chin@Sun.COM if(lexp->token==NL) 4504887Schin { 4514887Schin if(flag&SH_NL) 452*8462SApril.Chin@Sun.COM lexp->token=';'; 4534887Schin } 4544887Schin else if(!left && !(flag&SH_EMPTY)) 455*8462SApril.Chin@Sun.COM sh_syntax(lexp); 456*8462SApril.Chin@Sun.COM switch(lexp->token) 4574887Schin { 4584887Schin case COOPSYM: /* set up a cooperating process */ 4594887Schin type |= (FPIN|FPOU|FPCL|FCOOP); 4604887Schin /* FALL THRU */ 4614887Schin case '&': 4624887Schin if(left) 4634887Schin { 4644887Schin /* (...)& -> {...;} & */ 4654887Schin if(left->tre.tretyp==TPAR) 4664887Schin left = left->par.partre; 467*8462SApril.Chin@Sun.COM left = makeparent(lexp,TFORK|type, left); 4684887Schin } 4694887Schin /* FALL THRU */ 4704887Schin case ';': 4714887Schin if(!left) 472*8462SApril.Chin@Sun.COM sh_syntax(lexp); 473*8462SApril.Chin@Sun.COM if(right=sh_cmd(lexp,sym,flag|SH_EMPTY)) 474*8462SApril.Chin@Sun.COM left=makelist(lexp,TLST, left, right); 4754887Schin break; 4764887Schin case EOFSYM: 4774887Schin if(sym==NL) 4784887Schin break; 4794887Schin default: 480*8462SApril.Chin@Sun.COM if(sym && sym!=lexp->token) 4814887Schin { 482*8462SApril.Chin@Sun.COM if(sym!=ELSESYM || (lexp->token!=ELIFSYM && lexp->token!=FISYM)) 483*8462SApril.Chin@Sun.COM sh_syntax(lexp); 4844887Schin } 4854887Schin } 4864887Schin return(left); 4874887Schin } 4884887Schin 4894887Schin /* 4904887Schin * list 4914887Schin * term 4924887Schin * list && term 4934887Schin * list || term 4944887Schin * unfortunately, these are equal precedence 4954887Schin */ 496*8462SApril.Chin@Sun.COM static Shnode_t *list(Lex_t *lexp, register int flag) 4974887Schin { 498*8462SApril.Chin@Sun.COM register Shnode_t *t = term(lexp,flag); 4994887Schin register int token; 500*8462SApril.Chin@Sun.COM while(t && ((token=lexp->token)==ANDFSYM || token==ORFSYM)) 501*8462SApril.Chin@Sun.COM t = makelist(lexp,(token==ANDFSYM?TAND:TORF), t, term(lexp,SH_NL|SH_SEMI)); 5024887Schin return(t); 5034887Schin } 5044887Schin 5054887Schin /* 5064887Schin * term 5074887Schin * item 5084887Schin * item | term 5094887Schin */ 510*8462SApril.Chin@Sun.COM static Shnode_t *term(Lex_t *lexp,register int flag) 5114887Schin { 5124887Schin register Shnode_t *t; 5134887Schin register int token; 5144887Schin if(flag&SH_NL) 515*8462SApril.Chin@Sun.COM token = skipnl(lexp,flag); 5164887Schin else 517*8462SApril.Chin@Sun.COM token = sh_lex(lexp); 5184887Schin /* check to see if pipeline is to be timed */ 5194887Schin if(token==TIMESYM || token==NOTSYM) 5204887Schin { 5214887Schin t = getnode(parnod); 5224887Schin t->par.partyp=TTIME; 523*8462SApril.Chin@Sun.COM if(lexp->token==NOTSYM) 5244887Schin t->par.partyp |= COMSCAN; 525*8462SApril.Chin@Sun.COM t->par.partre = term(lexp,0); 5264887Schin } 527*8462SApril.Chin@Sun.COM else if((t=item(lexp,SH_NL|SH_EMPTY|(flag&SH_SEMI))) && lexp->token=='|') 5284887Schin { 5294887Schin register Shnode_t *tt; 5304887Schin int showme = t->tre.tretyp&FSHOWME; 531*8462SApril.Chin@Sun.COM t = makeparent(lexp,TFORK|FPOU,t); 532*8462SApril.Chin@Sun.COM if(tt=term(lexp,SH_NL)) 5334887Schin { 5344887Schin switch(tt->tre.tretyp&COMMSK) 5354887Schin { 5364887Schin case TFORK: 5374887Schin tt->tre.tretyp |= FPIN|FPCL; 5384887Schin break; 5394887Schin case TFIL: 5404887Schin tt->lst.lstlef->tre.tretyp |= FPIN|FPCL; 5414887Schin break; 5424887Schin default: 543*8462SApril.Chin@Sun.COM tt= makeparent(lexp,TSETIO|FPIN|FPCL,tt); 5444887Schin } 545*8462SApril.Chin@Sun.COM t=makelist(lexp,TFIL,t,tt); 5464887Schin t->tre.tretyp |= showme; 5474887Schin } 548*8462SApril.Chin@Sun.COM else if(lexp->token) 549*8462SApril.Chin@Sun.COM sh_syntax(lexp); 5504887Schin } 5514887Schin return(t); 5524887Schin } 5534887Schin 5544887Schin /* 5554887Schin * case statement 5564887Schin */ 557*8462SApril.Chin@Sun.COM static struct regnod* syncase(Lex_t *lexp,register int esym) 5584887Schin { 559*8462SApril.Chin@Sun.COM register int tok = skipnl(lexp,0); 5604887Schin register struct regnod *r; 5614887Schin if(tok==esym) 5624887Schin return(NIL(struct regnod*)); 5634887Schin r = (struct regnod*)stakalloc(sizeof(struct regnod)); 5644887Schin r->regptr=0; 5654887Schin r->regflag=0; 5664887Schin if(tok==LPAREN) 567*8462SApril.Chin@Sun.COM skipnl(lexp,0); 5684887Schin while(1) 5694887Schin { 570*8462SApril.Chin@Sun.COM if(!lexp->arg) 571*8462SApril.Chin@Sun.COM sh_syntax(lexp); 572*8462SApril.Chin@Sun.COM lexp->arg->argnxt.ap=r->regptr; 573*8462SApril.Chin@Sun.COM r->regptr = lexp->arg; 574*8462SApril.Chin@Sun.COM if((tok=sh_lex(lexp))==RPAREN) 5754887Schin break; 5764887Schin else if(tok=='|') 577*8462SApril.Chin@Sun.COM sh_lex(lexp); 5784887Schin else 579*8462SApril.Chin@Sun.COM sh_syntax(lexp); 5804887Schin } 581*8462SApril.Chin@Sun.COM r->regcom=sh_cmd(lexp,0,SH_NL|SH_EMPTY|SH_SEMI); 582*8462SApril.Chin@Sun.COM if((tok=lexp->token)==BREAKCASESYM) 583*8462SApril.Chin@Sun.COM r->regnxt=syncase(lexp,esym); 5844887Schin else if(tok==FALLTHRUSYM) 5854887Schin { 5864887Schin r->regflag++; 587*8462SApril.Chin@Sun.COM r->regnxt=syncase(lexp,esym); 5884887Schin } 5894887Schin else 5904887Schin { 5914887Schin if(tok!=esym && tok!=EOFSYM) 592*8462SApril.Chin@Sun.COM sh_syntax(lexp); 5934887Schin r->regnxt=0; 5944887Schin } 595*8462SApril.Chin@Sun.COM if(lexp->token==EOFSYM) 5964887Schin return(NIL(struct regnod*)); 5974887Schin return(r); 5984887Schin } 5994887Schin 6004887Schin /* 6014887Schin * This routine creates the parse tree for the arithmetic for 6024887Schin * When called, shlex.arg contains the string inside ((...)) 6034887Schin * When the first argument is missing, a while node is returned 6044887Schin * Otherise a list containing an arithmetic command and a while 6054887Schin * is returned. 6064887Schin */ 607*8462SApril.Chin@Sun.COM static Shnode_t *arithfor(Lex_t *lexp,register Shnode_t *tf) 6084887Schin { 6094887Schin register Shnode_t *t, *tw = tf; 6104887Schin register int offset; 6114887Schin register struct argnod *argp; 6124887Schin register int n; 613*8462SApril.Chin@Sun.COM Stk_t *stkp = lexp->sh->stk; 614*8462SApril.Chin@Sun.COM int argflag = lexp->arg->argflag; 6154887Schin /* save current input */ 6164887Schin Fcin_t sav_input; 6174887Schin fcsave(&sav_input); 618*8462SApril.Chin@Sun.COM fcsopen(lexp->arg->argval); 6194887Schin /* split ((...)) into three expressions */ 6204887Schin for(n=0; ; n++) 6214887Schin { 6224887Schin register int c; 623*8462SApril.Chin@Sun.COM argp = (struct argnod*)stkseek(stkp,ARGVAL); 6244887Schin argp->argnxt.ap = 0; 6254887Schin argp->argchn.cp = 0; 6264887Schin argp->argflag = argflag; 6274887Schin if(n==2) 6284887Schin break; 6294887Schin /* copy up to ; onto the stack */ 630*8462SApril.Chin@Sun.COM sh_lexskip(lexp,';',1,ST_NESTED); 631*8462SApril.Chin@Sun.COM offset = stktell(stkp)-1; 6324887Schin if((c=fcpeek(-1))!=';') 6334887Schin break; 6344887Schin /* remove trailing white space */ 635*8462SApril.Chin@Sun.COM while(offset>ARGVAL && ((c= *stkptr(stkp,offset-1)),isspace(c))) 6364887Schin offset--; 6374887Schin /* check for empty initialization expression */ 6384887Schin if(offset==ARGVAL && n==0) 6394887Schin continue; 640*8462SApril.Chin@Sun.COM stkseek(stkp,offset); 6414887Schin /* check for empty condition and treat as while((1)) */ 6424887Schin if(offset==ARGVAL) 643*8462SApril.Chin@Sun.COM sfputc(stkp,'1'); 644*8462SApril.Chin@Sun.COM argp = (struct argnod*)stkfreeze(stkp,1); 645*8462SApril.Chin@Sun.COM t = getanode(lexp,argp); 6464887Schin if(n==0) 647*8462SApril.Chin@Sun.COM tf = makelist(lexp,TLST,t,tw); 6484887Schin else 6494887Schin tw->wh.whtre = t; 6504887Schin } 6514887Schin while((offset=fcpeek(0)) && isspace(offset)) 6524887Schin fcseek(1); 6534887Schin stakputs(fcseek(0)); 6544887Schin argp = (struct argnod*)stakfreeze(1); 6554887Schin fcrestore(&sav_input); 6564887Schin if(n<2) 6574887Schin { 658*8462SApril.Chin@Sun.COM lexp->token = RPAREN|SYMREP; 659*8462SApril.Chin@Sun.COM sh_syntax(lexp); 6604887Schin } 6614887Schin /* check whether the increment is present */ 6624887Schin if(*argp->argval) 6634887Schin { 664*8462SApril.Chin@Sun.COM t = getanode(lexp,argp); 6654887Schin tw->wh.whinc = (struct arithnod*)t; 6664887Schin } 6674887Schin else 6684887Schin tw->wh.whinc = 0; 669*8462SApril.Chin@Sun.COM sh_lexopen(lexp, lexp->sh,1); 670*8462SApril.Chin@Sun.COM if((n=sh_lex(lexp))==NL) 671*8462SApril.Chin@Sun.COM n = skipnl(lexp,0); 6724887Schin else if(n==';') 673*8462SApril.Chin@Sun.COM n = sh_lex(lexp); 6744887Schin if(n!=DOSYM && n!=LBRACE) 675*8462SApril.Chin@Sun.COM sh_syntax(lexp); 676*8462SApril.Chin@Sun.COM tw->wh.dotre = sh_cmd(lexp,n==DOSYM?DONESYM:RBRACE,SH_NL); 6774887Schin tw->wh.whtyp = TWH; 6784887Schin return(tf); 6794887Schin 6804887Schin } 6814887Schin 682*8462SApril.Chin@Sun.COM static Shnode_t *funct(Lex_t *lexp) 6834887Schin { 684*8462SApril.Chin@Sun.COM Shell_t *shp = lexp->sh; 6854887Schin register Shnode_t *t; 6864887Schin register int flag; 6874887Schin struct slnod *volatile slp=0; 6884887Schin Stak_t *savstak; 6894887Schin Sfoff_t first, last; 690*8462SApril.Chin@Sun.COM struct functnod *volatile fp; 6914887Schin Sfio_t *iop; 6924887Schin #if SHOPT_KIA 693*8462SApril.Chin@Sun.COM unsigned long current = lexp->current; 6944887Schin #endif /* SHOPT_KIA */ 6954887Schin int jmpval, saveloop=loop_level; 6964887Schin struct argnod *savelabel = label_last; 6974887Schin struct checkpt buff; 698*8462SApril.Chin@Sun.COM int save_optget = opt_get; 699*8462SApril.Chin@Sun.COM void *in_mktype = shp->mktype; 700*8462SApril.Chin@Sun.COM shp->mktype = 0; 701*8462SApril.Chin@Sun.COM opt_get = 0; 7024887Schin t = getnode(functnod); 703*8462SApril.Chin@Sun.COM t->funct.functline = shp->inlineno; 7044887Schin t->funct.functtyp=TFUN; 7054887Schin t->funct.functargs = 0; 706*8462SApril.Chin@Sun.COM if(!(flag = (lexp->token==FUNCTSYM))) 7074887Schin t->funct.functtyp |= FPOSIX; 708*8462SApril.Chin@Sun.COM else if(sh_lex(lexp)) 709*8462SApril.Chin@Sun.COM sh_syntax(lexp); 7104887Schin if(!(iop=fcfile())) 7114887Schin { 7124887Schin iop = sfopen(NIL(Sfio_t*),fcseek(0),"s"); 7134887Schin fcclose(); 7144887Schin fcfopen(iop); 7154887Schin } 7164887Schin t->funct.functloc = first = fctell(); 717*8462SApril.Chin@Sun.COM if(!shp->st.filename || sffileno(iop)<0) 7184887Schin { 7194887Schin if(fcfill() >= 0) 7204887Schin fcseek(-1); 7214887Schin if(sh_isstate(SH_HISTORY)) 722*8462SApril.Chin@Sun.COM t->funct.functloc = sfseek(shp->hist_ptr->histfp,(off_t)0,SEEK_CUR); 7234887Schin else 7244887Schin { 7254887Schin /* copy source to temporary file */ 7264887Schin t->funct.functloc = 0; 727*8462SApril.Chin@Sun.COM if(lexp->sh->heredocs) 728*8462SApril.Chin@Sun.COM t->funct.functloc = sfseek(lexp->sh->heredocs,(Sfoff_t)0, SEEK_END); 7294887Schin else 730*8462SApril.Chin@Sun.COM lexp->sh->heredocs = sftmp(HERE_MEM); 731*8462SApril.Chin@Sun.COM lexp->sh->funlog = lexp->sh->heredocs; 7324887Schin t->funct.functtyp |= FPIN; 7334887Schin } 7344887Schin } 735*8462SApril.Chin@Sun.COM t->funct.functnam= (char*)lexp->arg->argval; 7364887Schin #if SHOPT_KIA 737*8462SApril.Chin@Sun.COM if(lexp->kiafile) 738*8462SApril.Chin@Sun.COM lexp->current = kiaentity(lexp,t->funct.functnam,-1,'p',-1,-1,lexp->script,'p',0,""); 7394887Schin #endif /* SHOPT_KIA */ 7404887Schin if(flag) 7414887Schin { 742*8462SApril.Chin@Sun.COM lexp->token = sh_lex(lexp); 7434887Schin #if SHOPT_BASH 744*8462SApril.Chin@Sun.COM if(lexp->token == LPAREN) 7454887Schin { 746*8462SApril.Chin@Sun.COM if((lexp->token = sh_lex(lexp)) == RPAREN) 7474887Schin t->funct.functtyp |= FPOSIX; 7484887Schin else 749*8462SApril.Chin@Sun.COM sh_syntax(lexp); 7504887Schin } 7514887Schin #endif 7524887Schin } 7534887Schin if(t->funct.functtyp&FPOSIX) 754*8462SApril.Chin@Sun.COM skipnl(lexp,0); 7554887Schin else 7564887Schin { 757*8462SApril.Chin@Sun.COM if(lexp->token==0) 758*8462SApril.Chin@Sun.COM t->funct.functargs = (struct comnod*)simple(lexp,SH_NOIO|SH_FUNDEF,NIL(struct ionod*)); 759*8462SApril.Chin@Sun.COM while(lexp->token==NL) 760*8462SApril.Chin@Sun.COM lexp->token = sh_lex(lexp); 7614887Schin } 762*8462SApril.Chin@Sun.COM if((flag && lexp->token!=LBRACE) || lexp->token==EOFSYM) 763*8462SApril.Chin@Sun.COM sh_syntax(lexp); 7644887Schin sh_pushcontext(&buff,1); 7654887Schin jmpval = sigsetjmp(buff.buff,0); 7664887Schin if(jmpval == 0) 7674887Schin { 7684887Schin /* create a new stak frame to compile the command */ 7694887Schin savstak = stakcreate(STAK_SMALL); 7704887Schin savstak = stakinstall(savstak, 0); 7714887Schin slp = (struct slnod*)stakalloc(sizeof(struct slnod)+sizeof(struct functnod)); 7724887Schin slp->slchild = 0; 773*8462SApril.Chin@Sun.COM slp->slnext = shp->st.staklist; 774*8462SApril.Chin@Sun.COM shp->st.staklist = 0; 7754887Schin t->funct.functstak = (struct slnod*)slp; 7764887Schin /* 7774887Schin * store the pathname of function definition file on stack 7784887Schin * in name field of fake for node 7794887Schin */ 7804887Schin fp = (struct functnod*)(slp+1); 7814887Schin fp->functtyp = TFUN|FAMP; 7824887Schin fp->functnam = 0; 7834887Schin fp->functline = t->funct.functline; 784*8462SApril.Chin@Sun.COM if(shp->st.filename) 785*8462SApril.Chin@Sun.COM fp->functnam = stakcopy(shp->st.filename); 7864887Schin loop_level = 0; 7874887Schin label_last = label_list; 788*8462SApril.Chin@Sun.COM if(!flag && lexp->token==0) 7894887Schin { 7904887Schin /* copy current word token to current stak frame */ 7914887Schin struct argnod *ap; 792*8462SApril.Chin@Sun.COM flag = ARGVAL + strlen(lexp->arg->argval); 7934887Schin ap = (struct argnod*)stakalloc(flag); 794*8462SApril.Chin@Sun.COM memcpy(ap,lexp->arg,flag); 795*8462SApril.Chin@Sun.COM lexp->arg = ap; 7964887Schin } 797*8462SApril.Chin@Sun.COM t->funct.functtre = item(lexp,SH_NOIO); 7984887Schin } 7994887Schin sh_popcontext(&buff); 8004887Schin loop_level = saveloop; 8014887Schin label_last = savelabel; 8024887Schin /* restore the old stack */ 8034887Schin if(slp) 8044887Schin { 8054887Schin slp->slptr = stakinstall(savstak,0); 806*8462SApril.Chin@Sun.COM slp->slchild = shp->st.staklist; 8074887Schin } 8084887Schin #if SHOPT_KIA 809*8462SApril.Chin@Sun.COM lexp->current = current; 8104887Schin #endif /* SHOPT_KIA */ 8114887Schin if(jmpval) 8124887Schin { 8134887Schin if(slp && slp->slptr) 8144887Schin { 815*8462SApril.Chin@Sun.COM shp->st.staklist = slp->slnext; 8164887Schin stakdelete(slp->slptr); 8174887Schin } 818*8462SApril.Chin@Sun.COM siglongjmp(*shp->jmplist,jmpval); 8194887Schin } 820*8462SApril.Chin@Sun.COM shp->st.staklist = (struct slnod*)slp; 8214887Schin last = fctell(); 8224887Schin fp->functline = (last-first); 8234887Schin fp->functtre = t; 824*8462SApril.Chin@Sun.COM shp->mktype = in_mktype; 825*8462SApril.Chin@Sun.COM if(lexp->sh->funlog) 8264887Schin { 8274887Schin if(fcfill()>0) 8284887Schin fcseek(-1); 829*8462SApril.Chin@Sun.COM lexp->sh->funlog = 0; 8304887Schin } 8314887Schin #if SHOPT_KIA 832*8462SApril.Chin@Sun.COM if(lexp->kiafile) 833*8462SApril.Chin@Sun.COM kiaentity(lexp,t->funct.functnam,-1,'p',t->funct.functline,shp->inlineno-1,lexp->current,'p',0,""); 8344887Schin #endif /* SHOPT_KIA */ 835*8462SApril.Chin@Sun.COM t->funct.functtyp |= opt_get; 836*8462SApril.Chin@Sun.COM opt_get = save_optget; 8374887Schin return(t); 8384887Schin } 8394887Schin 8404887Schin /* 8414887Schin * Compound assignment 8424887Schin */ 843*8462SApril.Chin@Sun.COM static struct argnod *assign(Lex_t *lexp, register struct argnod *ap, int tdef) 8444887Schin { 8454887Schin register int n; 8464887Schin register Shnode_t *t, **tp; 8474887Schin register struct comnod *ac; 848*8462SApril.Chin@Sun.COM Stk_t *stkp = lexp->sh->stk; 8494887Schin int array=0; 8504887Schin Namval_t *np; 8514887Schin n = strlen(ap->argval)-1; 8524887Schin if(ap->argval[n]!='=') 853*8462SApril.Chin@Sun.COM sh_syntax(lexp); 8544887Schin if(ap->argval[n-1]=='+') 8554887Schin { 8564887Schin ap->argval[n--]=0; 8574887Schin array = ARG_APPEND; 8584887Schin } 8594887Schin /* shift right */ 8604887Schin while(n > 0) 8614887Schin { 8624887Schin ap->argval[n] = ap->argval[n-1]; 8634887Schin n--; 8644887Schin } 8654887Schin *ap->argval=0; 8664887Schin t = getnode(fornod); 8674887Schin t->for_.fornam = (char*)(ap->argval+1); 868*8462SApril.Chin@Sun.COM t->for_.fortyp = sh_getlineno(lexp); 8694887Schin tp = &t->for_.fortre; 8704887Schin ap->argchn.ap = (struct argnod*)t; 8714887Schin ap->argflag &= ARG_QUOTED; 8724887Schin ap->argflag |= array; 873*8462SApril.Chin@Sun.COM lexp->assignok = SH_ASSIGN; 874*8462SApril.Chin@Sun.COM lexp->aliasok = 1; 8754887Schin array=0; 876*8462SApril.Chin@Sun.COM if((n=skipnl(lexp,0))==RPAREN || n==LPAREN) 8774887Schin { 8784887Schin int index= 0; 8794887Schin struct argnod **settail; 8804887Schin ac = (struct comnod*)getnode(comnod); 8814887Schin settail= &ac->comset; 8824887Schin memset((void*)ac,0,sizeof(*ac)); 883*8462SApril.Chin@Sun.COM ac->comline = sh_getlineno(lexp); 8844887Schin while(n==LPAREN) 8854887Schin { 8864887Schin struct argnod *ap; 887*8462SApril.Chin@Sun.COM ap = (struct argnod*)stkseek(stkp,ARGVAL); 8884887Schin ap->argflag= ARG_ASSIGN; 889*8462SApril.Chin@Sun.COM sfprintf(stkp,"[%d]=",index++); 890*8462SApril.Chin@Sun.COM ap = (struct argnod*)stkfreeze(stkp,1); 8914887Schin ap->argnxt.ap = 0; 892*8462SApril.Chin@Sun.COM ap = assign(lexp,ap,0); 8934887Schin ap->argflag |= ARG_MESSAGE; 8944887Schin *settail = ap; 8954887Schin settail = &(ap->argnxt.ap); 896*8462SApril.Chin@Sun.COM while((n = skipnl(lexp,0))==0) 897*8462SApril.Chin@Sun.COM { 898*8462SApril.Chin@Sun.COM ap = (struct argnod*)stkseek(stkp,ARGVAL); 899*8462SApril.Chin@Sun.COM ap->argflag= ARG_ASSIGN; 900*8462SApril.Chin@Sun.COM sfprintf(stkp,"[%d]=",index++); 901*8462SApril.Chin@Sun.COM stakputs(lexp->arg->argval); 902*8462SApril.Chin@Sun.COM ap = (struct argnod*)stkfreeze(stkp,1); 903*8462SApril.Chin@Sun.COM ap->argnxt.ap = 0; 904*8462SApril.Chin@Sun.COM ap->argflag = lexp->arg->argflag; 905*8462SApril.Chin@Sun.COM *settail = ap; 906*8462SApril.Chin@Sun.COM settail = &(ap->argnxt.ap); 907*8462SApril.Chin@Sun.COM } 9084887Schin } 9094887Schin } 910*8462SApril.Chin@Sun.COM else if(n && n!=FUNCTSYM) 911*8462SApril.Chin@Sun.COM sh_syntax(lexp); 912*8462SApril.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))) 913*8462SApril.Chin@Sun.COM { 9144887Schin array=SH_ARRAY; 915*8462SApril.Chin@Sun.COM if(fcgetc(n)==LPAREN) 916*8462SApril.Chin@Sun.COM { 917*8462SApril.Chin@Sun.COM int c; 918*8462SApril.Chin@Sun.COM if(fcgetc(c)==RPAREN) 919*8462SApril.Chin@Sun.COM { 920*8462SApril.Chin@Sun.COM lexp->token = SYMRES; 921*8462SApril.Chin@Sun.COM array = 0; 922*8462SApril.Chin@Sun.COM } 923*8462SApril.Chin@Sun.COM else 924*8462SApril.Chin@Sun.COM fcseek(-2); 925*8462SApril.Chin@Sun.COM } 926*8462SApril.Chin@Sun.COM else if(n>0) 927*8462SApril.Chin@Sun.COM fcseek(-1); 928*8462SApril.Chin@Sun.COM if(array && tdef) 929*8462SApril.Chin@Sun.COM sh_syntax(lexp); 930*8462SApril.Chin@Sun.COM } 9314887Schin while(1) 9324887Schin { 933*8462SApril.Chin@Sun.COM if((n=lexp->token)==RPAREN) 9344887Schin break; 9354887Schin if(n==FUNCTSYM || n==SYMRES) 936*8462SApril.Chin@Sun.COM ac = (struct comnod*)funct(lexp); 9374887Schin else 938*8462SApril.Chin@Sun.COM ac = (struct comnod*)simple(lexp,SH_NOIO|SH_ASSIGN|array,NIL(struct ionod*)); 939*8462SApril.Chin@Sun.COM if((n=lexp->token)==RPAREN) 9404887Schin break; 9414887Schin if(n!=NL && n!=';') 942*8462SApril.Chin@Sun.COM sh_syntax(lexp); 943*8462SApril.Chin@Sun.COM lexp->assignok = SH_ASSIGN; 944*8462SApril.Chin@Sun.COM if((n=skipnl(lexp,0)) || array) 9454887Schin { 9464887Schin if(n==RPAREN) 9474887Schin break; 9484887Schin if(array || n!=FUNCTSYM) 949*8462SApril.Chin@Sun.COM sh_syntax(lexp); 9504887Schin } 951*8462SApril.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))) 9524887Schin { 953*8462SApril.Chin@Sun.COM struct argnod *arg = lexp->arg; 9544887Schin if(n!=0) 955*8462SApril.Chin@Sun.COM sh_syntax(lexp); 9564887Schin /* check for sys5 style function */ 957*8462SApril.Chin@Sun.COM if(sh_lex(lexp)!=LPAREN || sh_lex(lexp)!=RPAREN) 9584887Schin { 959*8462SApril.Chin@Sun.COM lexp->arg = arg; 960*8462SApril.Chin@Sun.COM lexp->token = 0; 961*8462SApril.Chin@Sun.COM sh_syntax(lexp); 9624887Schin } 963*8462SApril.Chin@Sun.COM lexp->arg = arg; 964*8462SApril.Chin@Sun.COM lexp->token = SYMRES; 9654887Schin } 966*8462SApril.Chin@Sun.COM t = makelist(lexp,TLST,(Shnode_t*)ac,t); 9674887Schin *tp = t; 9684887Schin tp = &t->lst.lstrit; 9694887Schin } 9704887Schin *tp = (Shnode_t*)ac; 971*8462SApril.Chin@Sun.COM lexp->assignok = 0; 9724887Schin return(ap); 9734887Schin } 9744887Schin 9754887Schin /* 9764887Schin * item 9774887Schin * 9784887Schin * ( cmd ) [ < in ] [ > out ] 9794887Schin * word word* [ < in ] [ > out ] 9804887Schin * if ... then ... else ... fi 9814887Schin * for ... while ... do ... done 9824887Schin * case ... in ... esac 9834887Schin * begin ... end 9844887Schin */ 9854887Schin 986*8462SApril.Chin@Sun.COM static Shnode_t *item(Lex_t *lexp,int flag) 9874887Schin { 9884887Schin register Shnode_t *t; 9894887Schin register struct ionod *io; 990*8462SApril.Chin@Sun.COM register int tok = (lexp->token&0xff); 991*8462SApril.Chin@Sun.COM int savwdval = lexp->lasttok; 992*8462SApril.Chin@Sun.COM int savline = lexp->lastline; 993*8462SApril.Chin@Sun.COM int showme=0, comsub; 994*8462SApril.Chin@Sun.COM if(!(flag&SH_NOIO) && (tok=='<' || tok=='>' || lexp->token==IOVNAME)) 995*8462SApril.Chin@Sun.COM io=inout(lexp,NIL(struct ionod*),1); 9964887Schin else 9974887Schin io=0; 998*8462SApril.Chin@Sun.COM if((tok=lexp->token) && tok!=EOFSYM && tok!=FUNCTSYM) 9994887Schin { 1000*8462SApril.Chin@Sun.COM lexp->lastline = sh_getlineno(lexp); 1001*8462SApril.Chin@Sun.COM lexp->lasttok = lexp->token; 10024887Schin } 10034887Schin switch(tok) 10044887Schin { 10054887Schin /* [[ ... ]] test expression */ 10064887Schin case BTESTSYM: 1007*8462SApril.Chin@Sun.COM t = test_expr(lexp,ETESTSYM); 10084887Schin t->tre.tretyp &= ~TTEST; 10094887Schin break; 10104887Schin /* ((...)) arithmetic expression */ 10114887Schin case EXPRSYM: 1012*8462SApril.Chin@Sun.COM t = getanode(lexp,lexp->arg); 1013*8462SApril.Chin@Sun.COM sh_lex(lexp); 10144887Schin goto done; 10154887Schin 10164887Schin /* case statement */ 10174887Schin case CASESYM: 10184887Schin { 1019*8462SApril.Chin@Sun.COM int savetok = lexp->lasttok; 1020*8462SApril.Chin@Sun.COM int saveline = lexp->lastline; 10214887Schin t = getnode(swnod); 1022*8462SApril.Chin@Sun.COM if(sh_lex(lexp)) 1023*8462SApril.Chin@Sun.COM sh_syntax(lexp); 1024*8462SApril.Chin@Sun.COM t->sw.swarg=lexp->arg; 10254887Schin t->sw.swtyp=TSW; 10264887Schin t->sw.swio = 0; 10274887Schin t->sw.swtyp |= FLINENO; 1028*8462SApril.Chin@Sun.COM t->sw.swline = lexp->sh->inlineno; 1029*8462SApril.Chin@Sun.COM if((tok=skipnl(lexp,0))!=INSYM && tok!=LBRACE) 1030*8462SApril.Chin@Sun.COM sh_syntax(lexp); 1031*8462SApril.Chin@Sun.COM if(!(t->sw.swlst=syncase(lexp,tok==INSYM?ESACSYM:RBRACE)) && lexp->token==EOFSYM) 10324887Schin { 1033*8462SApril.Chin@Sun.COM lexp->lasttok = savetok; 1034*8462SApril.Chin@Sun.COM lexp->lastline = saveline; 1035*8462SApril.Chin@Sun.COM sh_syntax(lexp); 10364887Schin } 10374887Schin break; 10384887Schin } 10394887Schin 10404887Schin /* if statement */ 10414887Schin case IFSYM: 10424887Schin { 10434887Schin register Shnode_t *tt; 10444887Schin t = getnode(ifnod); 10454887Schin t->if_.iftyp=TIF; 1046*8462SApril.Chin@Sun.COM t->if_.iftre=sh_cmd(lexp,THENSYM,SH_NL); 1047*8462SApril.Chin@Sun.COM t->if_.thtre=sh_cmd(lexp,ELSESYM,SH_NL|SH_SEMI); 1048*8462SApril.Chin@Sun.COM tok = lexp->token; 1049*8462SApril.Chin@Sun.COM t->if_.eltre=(tok==ELSESYM?sh_cmd(lexp,FISYM,SH_NL|SH_SEMI): 1050*8462SApril.Chin@Sun.COM (tok==ELIFSYM?(lexp->token=IFSYM, tt=item(lexp,SH_NOIO)):0)); 10514887Schin if(tok==ELIFSYM) 10524887Schin { 10534887Schin if(!tt || tt->tre.tretyp!=TSETIO) 10544887Schin goto done; 10554887Schin t->if_.eltre = tt->fork.forktre; 10564887Schin tt->fork.forktre = t; 10574887Schin t = tt; 10584887Schin goto done; 10594887Schin } 10604887Schin break; 10614887Schin } 10624887Schin 10634887Schin /* for and select statement */ 10644887Schin case FORSYM: 10654887Schin case SELECTSYM: 10664887Schin { 10674887Schin t = getnode(fornod); 1068*8462SApril.Chin@Sun.COM t->for_.fortyp=(lexp->token==FORSYM?TFOR:TSELECT); 10694887Schin t->for_.forlst=0; 1070*8462SApril.Chin@Sun.COM t->for_.forline = lexp->sh->inlineno; 1071*8462SApril.Chin@Sun.COM if(sh_lex(lexp)) 10724887Schin { 1073*8462SApril.Chin@Sun.COM if(lexp->token!=EXPRSYM || t->for_.fortyp!=TFOR) 1074*8462SApril.Chin@Sun.COM sh_syntax(lexp); 10754887Schin /* arithmetic for */ 1076*8462SApril.Chin@Sun.COM t = arithfor(lexp,t); 10774887Schin break; 10784887Schin } 1079*8462SApril.Chin@Sun.COM t->for_.fornam=(char*) lexp->arg->argval; 10804887Schin t->for_.fortyp |= FLINENO; 10814887Schin #if SHOPT_KIA 1082*8462SApril.Chin@Sun.COM if(lexp->kiafile) 1083*8462SApril.Chin@Sun.COM writedefs(lexp,lexp->arg,lexp->sh->inlineno,'v',NIL(struct argnod*)); 10844887Schin #endif /* SHOPT_KIA */ 1085*8462SApril.Chin@Sun.COM while((tok=sh_lex(lexp))==NL); 10864887Schin if(tok==INSYM) 10874887Schin { 1088*8462SApril.Chin@Sun.COM if(sh_lex(lexp)) 10894887Schin { 1090*8462SApril.Chin@Sun.COM if(lexp->token != NL && lexp->token !=';') 1091*8462SApril.Chin@Sun.COM sh_syntax(lexp); 10924887Schin /* some Linux scripts assume this */ 10934887Schin if(sh_isoption(SH_NOEXEC)) 1094*8462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_warn(0),e_lexemptyfor,lexp->sh->inlineno-(lexp->token=='\n')); 10954887Schin t->for_.forlst = (struct comnod*)getnode(comnod); 10964887Schin (t->for_.forlst)->comarg = 0; 10974887Schin (t->for_.forlst)->comset = 0; 10984887Schin (t->for_.forlst)->comnamp = 0; 10994887Schin (t->for_.forlst)->comnamq = 0; 11004887Schin (t->for_.forlst)->comstate = 0; 11014887Schin (t->for_.forlst)->comio = 0; 11024887Schin (t->for_.forlst)->comtyp = 0; 11034887Schin } 11044887Schin else 1105*8462SApril.Chin@Sun.COM t->for_.forlst=(struct comnod*)simple(lexp,SH_NOIO,NIL(struct ionod*)); 1106*8462SApril.Chin@Sun.COM if(lexp->token != NL && lexp->token !=';') 1107*8462SApril.Chin@Sun.COM sh_syntax(lexp); 1108*8462SApril.Chin@Sun.COM tok = skipnl(lexp,0); 11094887Schin } 11104887Schin /* 'for i;do cmd' is valid syntax */ 11114887Schin else if(tok==';') 1112*8462SApril.Chin@Sun.COM tok=sh_lex(lexp); 11134887Schin if(tok!=DOSYM && tok!=LBRACE) 1114*8462SApril.Chin@Sun.COM sh_syntax(lexp); 11154887Schin loop_level++; 1116*8462SApril.Chin@Sun.COM t->for_.fortre=sh_cmd(lexp,tok==DOSYM?DONESYM:RBRACE,SH_NL|SH_SEMI); 11174887Schin if(--loop_level==0) 11184887Schin label_last = label_list; 11194887Schin break; 11204887Schin } 11214887Schin 11224887Schin /* This is the code for parsing function definitions */ 11234887Schin case FUNCTSYM: 1124*8462SApril.Chin@Sun.COM return(funct(lexp)); 11254887Schin 11264887Schin #if SHOPT_NAMESPACE 11274887Schin case NSPACESYM: 11284887Schin t = getnode(fornod); 11294887Schin t->for_.fortyp=TNSPACE; 11304887Schin t->for_.forlst=0; 1131*8462SApril.Chin@Sun.COM if(sh_lex(lexp)) 1132*8462SApril.Chin@Sun.COM sh_syntax(lexp); 1133*8462SApril.Chin@Sun.COM t->for_.fornam=(char*) lexp->arg->argval; 1134*8462SApril.Chin@Sun.COM while((tok=sh_lex(lexp))==NL); 11354887Schin if(tok!=LBRACE) 1136*8462SApril.Chin@Sun.COM sh_syntax(lexp); 1137*8462SApril.Chin@Sun.COM t->for_.fortre = sh_cmd(lexp,RBRACE,SH_NL); 11384887Schin break; 11394887Schin #endif /* SHOPT_NAMESPACE */ 11404887Schin 11414887Schin /* while and until */ 11424887Schin case WHILESYM: 11434887Schin case UNTILSYM: 11444887Schin t = getnode(whnod); 1145*8462SApril.Chin@Sun.COM t->wh.whtyp=(lexp->token==WHILESYM ? TWH : TUN); 11464887Schin loop_level++; 1147*8462SApril.Chin@Sun.COM t->wh.whtre = sh_cmd(lexp,DOSYM,SH_NL); 1148*8462SApril.Chin@Sun.COM t->wh.dotre = sh_cmd(lexp,DONESYM,SH_NL|SH_SEMI); 11494887Schin if(--loop_level==0) 11504887Schin label_last = label_list; 11514887Schin t->wh.whinc = 0; 11524887Schin break; 11534887Schin 11544887Schin case LABLSYM: 11554887Schin { 11564887Schin register struct argnod *argp = label_list; 11574887Schin while(argp) 11584887Schin { 1159*8462SApril.Chin@Sun.COM if(strcmp(argp->argval,lexp->arg->argval)==0) 1160*8462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax3,lexp->sh->inlineno,argp->argval); 11614887Schin argp = argp->argnxt.ap; 11624887Schin } 1163*8462SApril.Chin@Sun.COM lexp->arg->argnxt.ap = label_list; 1164*8462SApril.Chin@Sun.COM label_list = lexp->arg; 1165*8462SApril.Chin@Sun.COM label_list->argchn.len = sh_getlineno(lexp); 11664887Schin label_list->argflag = loop_level; 1167*8462SApril.Chin@Sun.COM skipnl(lexp,flag); 1168*8462SApril.Chin@Sun.COM if(!(t = item(lexp,SH_NL))) 1169*8462SApril.Chin@Sun.COM sh_syntax(lexp); 11704887Schin tok = (t->tre.tretyp&(COMSCAN|COMSCAN-1)); 11714887Schin if(sh_isoption(SH_NOEXEC) && tok!=TWH && tok!=TUN && tok!=TFOR && tok!=TSELECT) 11724887Schin errormsg(SH_DICT,ERROR_warn(0),e_lexlabignore,label_list->argchn.len,label_list->argval); 11734887Schin return(t); 11744887Schin } 11754887Schin 11764887Schin /* command group with {...} */ 11774887Schin case LBRACE: 1178*8462SApril.Chin@Sun.COM comsub = lexp->comsub; 1179*8462SApril.Chin@Sun.COM lexp->comsub = 0; 1180*8462SApril.Chin@Sun.COM t = sh_cmd(lexp,RBRACE,SH_NL); 1181*8462SApril.Chin@Sun.COM lexp->comsub = comsub; 11824887Schin break; 11834887Schin 11844887Schin case LPAREN: 11854887Schin t = getnode(parnod); 1186*8462SApril.Chin@Sun.COM t->par.partre=sh_cmd(lexp,RPAREN,SH_NL); 11874887Schin t->par.partyp=TPAR; 11884887Schin break; 11894887Schin 11904887Schin default: 11914887Schin if(io==0) 11924887Schin return(0); 11934887Schin 11944887Schin case ';': 11954887Schin if(io==0) 11964887Schin { 11974887Schin if(!(flag&SH_SEMI)) 11984887Schin return(0); 1199*8462SApril.Chin@Sun.COM if(sh_lex(lexp)==';') 1200*8462SApril.Chin@Sun.COM sh_syntax(lexp); 12014887Schin showme = FSHOWME; 12024887Schin } 12034887Schin /* simple command */ 12044887Schin case 0: 1205*8462SApril.Chin@Sun.COM t = (Shnode_t*)simple(lexp,flag,io); 1206*8462SApril.Chin@Sun.COM if(t->com.comarg && lexp->intypeset && (lexp->sh->shcomp || sh_isoption(SH_NOEXEC) || sh.dot_depth)) 1207*8462SApril.Chin@Sun.COM check_typedef(&t->com); 1208*8462SApril.Chin@Sun.COM lexp->intypeset = 0; 1209*8462SApril.Chin@Sun.COM lexp->inexec = 0; 12104887Schin t->tre.tretyp |= showme; 12114887Schin return(t); 12124887Schin } 1213*8462SApril.Chin@Sun.COM sh_lex(lexp); 1214*8462SApril.Chin@Sun.COM if(io=inout(lexp,io,0)) 12154887Schin { 12164887Schin if((tok=t->tre.tretyp&COMMSK) != TFORK) 12174887Schin tok = TSETIO; 1218*8462SApril.Chin@Sun.COM t=makeparent(lexp,tok,t); 12194887Schin t->tre.treio=io; 12204887Schin } 12214887Schin done: 1222*8462SApril.Chin@Sun.COM lexp->lasttok = savwdval; 1223*8462SApril.Chin@Sun.COM lexp->lastline = savline; 12244887Schin return(t); 12254887Schin } 12264887Schin 12274887Schin /* 12284887Schin * This is for a simple command, for list, or compound assignment 12294887Schin */ 1230*8462SApril.Chin@Sun.COM static Shnode_t *simple(Lex_t *lexp,int flag, struct ionod *io) 12314887Schin { 12324887Schin register struct comnod *t; 12334887Schin register struct argnod *argp; 12344887Schin register int tok; 1235*8462SApril.Chin@Sun.COM Stk_t *stkp = lexp->sh->stk; 12364887Schin struct argnod **argtail; 12374887Schin struct argnod **settail; 1238*8462SApril.Chin@Sun.COM int cmdarg=0; 1239*8462SApril.Chin@Sun.COM int argno = 0, argmax=0; 12404887Schin int assignment = 0; 12414887Schin int key_on = (!(flag&SH_NOIO) && sh_isoption(SH_KEYWORD)); 12424887Schin int associative=0; 1243*8462SApril.Chin@Sun.COM if((argp=lexp->arg) && (argp->argflag&ARG_ASSIGN) && argp->argval[0]=='[') 12444887Schin { 12454887Schin flag |= SH_ARRAY; 12464887Schin associative = 1; 12474887Schin } 12484887Schin t = (struct comnod*)getnode(comnod); 12494887Schin t->comio=io; /*initial io chain*/ 12504887Schin /* set command line number for error messages */ 1251*8462SApril.Chin@Sun.COM t->comline = sh_getlineno(lexp); 12524887Schin argtail = &(t->comarg); 12534887Schin t->comset = 0; 12544887Schin t->comnamp = 0; 12554887Schin t->comnamq = 0; 12564887Schin t->comstate = 0; 12574887Schin settail = &(t->comset); 1258*8462SApril.Chin@Sun.COM while(lexp->token==0) 12594887Schin { 1260*8462SApril.Chin@Sun.COM argp = lexp->arg; 12614887Schin if(*argp->argval==LBRACE && (flag&SH_FUNDEF) && argp->argval[1]==0) 12624887Schin { 1263*8462SApril.Chin@Sun.COM lexp->token = LBRACE; 12644887Schin break; 12654887Schin } 12664887Schin if(associative && argp->argval[0]!='[') 1267*8462SApril.Chin@Sun.COM sh_syntax(lexp); 12684887Schin /* check for assignment argument */ 12694887Schin if((argp->argflag&ARG_ASSIGN) && assignment!=2) 12704887Schin { 12714887Schin *settail = argp; 12724887Schin settail = &(argp->argnxt.ap); 1273*8462SApril.Chin@Sun.COM lexp->assignok = (flag&SH_ASSIGN)?SH_ASSIGN:1; 12744887Schin if(assignment) 12754887Schin { 12764887Schin struct argnod *ap=argp; 12774887Schin char *last, *cp; 12784887Schin if(assignment==1) 12794887Schin { 12804887Schin last = strchr(argp->argval,'='); 12814887Schin if((cp=strchr(argp->argval,'[')) && (cp < last)) 12824887Schin last = cp; 1283*8462SApril.Chin@Sun.COM stkseek(stkp,ARGVAL); 1284*8462SApril.Chin@Sun.COM sfwrite(stkp,argp->argval,last-argp->argval); 1285*8462SApril.Chin@Sun.COM ap=(struct argnod*)stkfreeze(stkp,1); 12864887Schin ap->argflag = ARG_RAW; 12874887Schin ap->argchn.ap = 0; 12884887Schin } 12894887Schin *argtail = ap; 12904887Schin argtail = &(ap->argnxt.ap); 12914887Schin if(argno>=0) 12924887Schin argno++; 12934887Schin } 12944887Schin else /* alias substitutions allowed */ 1295*8462SApril.Chin@Sun.COM lexp->aliasok = 1; 12964887Schin } 12974887Schin else 12984887Schin { 12994887Schin if(!(argp->argflag&ARG_RAW)) 1300*8462SApril.Chin@Sun.COM { 1301*8462SApril.Chin@Sun.COM if(argno>0) 1302*8462SApril.Chin@Sun.COM argmax = argno; 13034887Schin argno = -1; 1304*8462SApril.Chin@Sun.COM } 1305*8462SApril.Chin@Sun.COM if(argno>=0 && argno++==cmdarg && !(flag&SH_ARRAY) && *argp->argval!='/') 13064887Schin { 13074887Schin /* check for builtin command */ 1308*8462SApril.Chin@Sun.COM Namval_t *np=nv_bfsearch(argp->argval,lexp->sh->fun_tree, (Namval_t**)&t->comnamq,(char**)0); 1309*8462SApril.Chin@Sun.COM if(cmdarg==0) 1310*8462SApril.Chin@Sun.COM t->comnamp = (void*)np; 1311*8462SApril.Chin@Sun.COM if(np && is_abuiltin(np)) 13124887Schin { 1313*8462SApril.Chin@Sun.COM if(nv_isattr(np,BLT_DCL)) 1314*8462SApril.Chin@Sun.COM { 1315*8462SApril.Chin@Sun.COM assignment = 1+(*argp->argval=='a'); 1316*8462SApril.Chin@Sun.COM if(np==SYSTYPESET) 1317*8462SApril.Chin@Sun.COM lexp->intypeset = 1; 1318*8462SApril.Chin@Sun.COM key_on = 1; 1319*8462SApril.Chin@Sun.COM } 1320*8462SApril.Chin@Sun.COM else if(np==SYSCOMMAND) 1321*8462SApril.Chin@Sun.COM cmdarg++; 1322*8462SApril.Chin@Sun.COM else if(np==SYSEXEC) 1323*8462SApril.Chin@Sun.COM lexp->inexec = 1; 1324*8462SApril.Chin@Sun.COM else if(np->nvalue.bfp==b_getopts) 1325*8462SApril.Chin@Sun.COM opt_get |= FOPTGET; 13264887Schin } 13274887Schin } 13284887Schin *argtail = argp; 13294887Schin argtail = &(argp->argnxt.ap); 1330*8462SApril.Chin@Sun.COM if(!(lexp->assignok=key_on) && !(flag&SH_NOIO) && sh_isoption(SH_NOEXEC)) 1331*8462SApril.Chin@Sun.COM lexp->assignok = SH_COMPASSIGN; 1332*8462SApril.Chin@Sun.COM lexp->aliasok = 0; 13334887Schin } 13344887Schin retry: 1335*8462SApril.Chin@Sun.COM tok = sh_lex(lexp); 1336*8462SApril.Chin@Sun.COM if(tok==LABLSYM && (flag&SH_ASSIGN)) 1337*8462SApril.Chin@Sun.COM lexp->token = tok = 0; 13384887Schin #if SHOPT_DEVFD 13394887Schin if((tok==IPROCSYM || tok==OPROCSYM)) 13404887Schin { 13414887Schin Shnode_t *t; 13424887Schin int mode = (tok==OPROCSYM); 1343*8462SApril.Chin@Sun.COM t = sh_cmd(lexp,RPAREN,SH_NL); 1344*8462SApril.Chin@Sun.COM argp = (struct argnod*)stkalloc(stkp,sizeof(struct argnod)); 13454887Schin *argp->argval = 0; 1346*8462SApril.Chin@Sun.COM argmax = 0; 13474887Schin argno = -1; 13484887Schin *argtail = argp; 13494887Schin argtail = &(argp->argnxt.ap); 1350*8462SApril.Chin@Sun.COM argp->argchn.ap = (struct argnod*)makeparent(lexp,mode?TFORK|FPIN|FAMP|FPCL:TFORK|FPOU,t); 13514887Schin argp->argflag = (ARG_EXP|mode); 13524887Schin goto retry; 13534887Schin } 13544887Schin #endif /* SHOPT_DEVFD */ 13554887Schin if(tok==LPAREN) 13564887Schin { 13574887Schin if(argp->argflag&ARG_ASSIGN) 13584887Schin { 1359*8462SApril.Chin@Sun.COM int intypeset = lexp->intypeset; 1360*8462SApril.Chin@Sun.COM int tdef = 0; 1361*8462SApril.Chin@Sun.COM lexp->intypeset = 0; 1362*8462SApril.Chin@Sun.COM if(t->comnamp==SYSTYPESET && t->comarg->argnxt.ap && strcmp(t->comarg->argnxt.ap->argval,"-T")==0) 1363*8462SApril.Chin@Sun.COM tdef = 1; 1364*8462SApril.Chin@Sun.COM argp = assign(lexp,argp,tdef); 1365*8462SApril.Chin@Sun.COM lexp->intypeset = intypeset; 13664887Schin if(associative) 1367*8462SApril.Chin@Sun.COM lexp->assignok |= SH_ASSIGN; 13684887Schin goto retry; 13694887Schin } 13704887Schin else if(argno==1 && !t->comset) 13714887Schin { 13724887Schin /* SVR2 style function */ 1373*8462SApril.Chin@Sun.COM if(sh_lex(lexp) == RPAREN) 13744887Schin { 1375*8462SApril.Chin@Sun.COM lexp->arg = argp; 1376*8462SApril.Chin@Sun.COM return(funct(lexp)); 13774887Schin } 1378*8462SApril.Chin@Sun.COM lexp->token = LPAREN; 13794887Schin } 13804887Schin } 13814887Schin else if(flag&SH_ASSIGN) 13824887Schin { 13834887Schin if(tok==RPAREN) 13844887Schin break; 13854887Schin else if(tok==NL && (flag&SH_ARRAY)) 1386*8462SApril.Chin@Sun.COM { 1387*8462SApril.Chin@Sun.COM lexp->comp_assign = 2; 13884887Schin goto retry; 1389*8462SApril.Chin@Sun.COM } 1390*8462SApril.Chin@Sun.COM 13914887Schin } 13924887Schin if(!(flag&SH_NOIO)) 13934887Schin { 13944887Schin if(io) 13954887Schin { 13964887Schin while(io->ionxt) 13974887Schin io = io->ionxt; 1398*8462SApril.Chin@Sun.COM io->ionxt = inout(lexp,(struct ionod*)0,0); 13994887Schin } 14004887Schin else 1401*8462SApril.Chin@Sun.COM t->comio = io = inout(lexp,(struct ionod*)0,0); 14024887Schin } 14034887Schin } 14044887Schin *argtail = 0; 1405*8462SApril.Chin@Sun.COM if(argno>0) 1406*8462SApril.Chin@Sun.COM argmax = argno; 1407*8462SApril.Chin@Sun.COM t->comtyp = TCOM | (argmax<<(COMBITS+2)); 14084887Schin #if SHOPT_KIA 1409*8462SApril.Chin@Sun.COM if(lexp->kiafile && !(flag&SH_NOIO)) 14104887Schin { 14114887Schin register Namval_t *np=(Namval_t*)t->comnamp; 14124887Schin unsigned long r=0; 14134887Schin int line = t->comline; 14144887Schin argp = t->comarg; 14154887Schin if(np) 1416*8462SApril.Chin@Sun.COM r = kiaentity(lexp,nv_name(np),-1,'p',-1,0,lexp->unknown,'b',0,""); 14174887Schin else if(argp) 1418*8462SApril.Chin@Sun.COM r = kiaentity(lexp,sh_argstr(argp),-1,'p',-1,0,lexp->unknown,'c',0,""); 14194887Schin if(r>0) 1420*8462SApril.Chin@Sun.COM sfprintf(lexp->kiatmp,"p;%..64d;p;%..64d;%d;%d;c;\n",lexp->current,r,line,line); 14214887Schin if(t->comset && argno==0) 1422*8462SApril.Chin@Sun.COM writedefs(lexp,t->comset,line,'v',t->comarg); 14234887Schin else if(np && nv_isattr(np,BLT_DCL)) 1424*8462SApril.Chin@Sun.COM writedefs(lexp,argp,line,0,NIL(struct argnod*)); 14254887Schin else if(argp && strcmp(argp->argval,"read")==0) 1426*8462SApril.Chin@Sun.COM writedefs(lexp,argp,line,0,NIL(struct argnod*)); 14274887Schin #if 0 14284887Schin else if(argp && strcmp(argp->argval,"unset")==0) 1429*8462SApril.Chin@Sun.COM writedefs(lexp,argp,line,'u',NIL(struct argnod*)); 14304887Schin #endif 14314887Schin else if(argp && *argp->argval=='.' && argp->argval[1]==0 && (argp=argp->argnxt.ap)) 14324887Schin { 1433*8462SApril.Chin@Sun.COM r = kiaentity(lexp,sh_argstr(argp),-1,'p',0,0,lexp->script,'d',0,""); 1434*8462SApril.Chin@Sun.COM sfprintf(lexp->kiatmp,"p;%..64d;p;%..64d;%d;%d;d;\n",lexp->current,r,line,line); 14354887Schin } 14364887Schin } 14374887Schin #endif /* SHOPT_KIA */ 14384887Schin if(t->comnamp && (argp=t->comarg->argnxt.ap)) 14394887Schin { 14404887Schin Namval_t *np=(Namval_t*)t->comnamp; 14414887Schin if((np==SYSBREAK || np==SYSCONT) && (argp->argflag&ARG_RAW) && !isdigit(*argp->argval)) 14424887Schin { 14434887Schin register char *cp = argp->argval; 14444887Schin /* convert break/continue labels to numbers */ 14454887Schin tok = 0; 14464887Schin for(argp=label_list;argp!=label_last;argp=argp->argnxt.ap) 14474887Schin { 14484887Schin if(strcmp(cp,argp->argval)) 14494887Schin continue; 14504887Schin tok = loop_level-argp->argflag; 14514887Schin if(tok>=1) 14524887Schin { 14534887Schin argp = t->comarg->argnxt.ap; 14544887Schin if(tok>9) 14554887Schin { 14564887Schin argp->argval[1] = '0'+tok%10; 14574887Schin argp->argval[2] = 0; 14584887Schin tok /= 10; 14594887Schin } 14604887Schin else 14614887Schin argp->argval[1] = 0; 14624887Schin *argp->argval = '0'+tok; 14634887Schin } 14644887Schin break; 14654887Schin } 14664887Schin if(sh_isoption(SH_NOEXEC) && tok==0) 1467*8462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_warn(0),e_lexlabunknown,lexp->sh->inlineno-(lexp->token=='\n'),cp); 14684887Schin } 14694887Schin else if(sh_isoption(SH_NOEXEC) && np==SYSSET && ((tok= *argp->argval)=='-'||tok=='+') && 14704887Schin (argp->argval[1]==0||strchr(argp->argval,'k'))) 1471*8462SApril.Chin@Sun.COM errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete5,lexp->sh->inlineno-(lexp->token=='\n'),argp->argval); 14724887Schin } 14734887Schin /* expand argument list if possible */ 14744887Schin if(argno>0) 14754887Schin t->comarg = qscan(t,argno); 14764887Schin else if(t->comarg) 14774887Schin t->comtyp |= COMSCAN; 1478*8462SApril.Chin@Sun.COM lexp->aliasok = 0; 14794887Schin return((Shnode_t*)t); 14804887Schin } 14814887Schin 14824887Schin /* 14834887Schin * skip past newlines but issue prompt if interactive 14844887Schin */ 1485*8462SApril.Chin@Sun.COM static int skipnl(Lex_t *lexp,int flag) 14864887Schin { 14874887Schin register int token; 1488*8462SApril.Chin@Sun.COM while((token=sh_lex(lexp))==NL); 14894887Schin if(token==';' && !(flag&SH_SEMI)) 1490*8462SApril.Chin@Sun.COM sh_syntax(lexp); 14914887Schin return(token); 14924887Schin } 14934887Schin 14944887Schin /* 14954887Schin * check for and process and i/o redirections 14964887Schin * if flag>0 then an alias can be in the next word 14974887Schin * if flag<0 only one redirection will be processed 14984887Schin */ 1499*8462SApril.Chin@Sun.COM static struct ionod *inout(Lex_t *lexp,struct ionod *lastio,int flag) 15004887Schin { 1501*8462SApril.Chin@Sun.COM register int iof = lexp->digits, token=lexp->token; 15024887Schin register struct ionod *iop; 1503*8462SApril.Chin@Sun.COM Stk_t *stkp = lexp->sh->stk; 15044887Schin char *iovname=0; 15054887Schin #if SHOPT_BASH 15064887Schin register int errout=0; 15074887Schin #endif 15084887Schin if(token==IOVNAME) 15094887Schin { 1510*8462SApril.Chin@Sun.COM iovname=lexp->arg->argval+1; 1511*8462SApril.Chin@Sun.COM token= sh_lex(lexp); 15124887Schin iof = 0; 15134887Schin } 15144887Schin switch(token&0xff) 15154887Schin { 15164887Schin case '<': 15174887Schin if(token==IODOCSYM) 15184887Schin iof |= (IODOC|IORAW); 15194887Schin else if(token==IOMOV0SYM) 15204887Schin iof |= IOMOV; 15214887Schin else if(token==IORDWRSYM) 15224887Schin iof |= IORDW; 15234887Schin else if((token&SYMSHARP) == SYMSHARP) 15244887Schin { 15254887Schin int n; 15264887Schin iof |= IOLSEEK; 15274887Schin if(fcgetc(n)=='#') 15284887Schin iof |= IOCOPY; 15294887Schin else if(n>0) 15304887Schin fcseek(-1); 15314887Schin } 15324887Schin break; 15334887Schin 15344887Schin case '>': 15354887Schin #if SHOPT_BASH 15364887Schin if(iof<0) 15374887Schin { 15384887Schin errout = 1; 15394887Schin iof = 1; 15404887Schin } 15414887Schin #endif 15424887Schin iof |= IOPUT; 15434887Schin if(token==IOAPPSYM) 15444887Schin iof |= IOAPP; 15454887Schin else if(token==IOMOV1SYM) 15464887Schin iof |= IOMOV; 15474887Schin else if(token==IOCLOBSYM) 15484887Schin iof |= IOCLOB; 15494887Schin else if((token&SYMSHARP) == SYMSHARP) 15504887Schin iof |= IOLSEEK; 1551*8462SApril.Chin@Sun.COM else if((token&SYMSEMI) == SYMSEMI) 1552*8462SApril.Chin@Sun.COM iof |= IOREWRITE; 15534887Schin break; 15544887Schin 15554887Schin default: 15564887Schin return(lastio); 15574887Schin } 1558*8462SApril.Chin@Sun.COM lexp->digits=0; 1559*8462SApril.Chin@Sun.COM iop=(struct ionod*) stkalloc(stkp,sizeof(struct ionod)); 15604887Schin iop->iodelim = 0; 1561*8462SApril.Chin@Sun.COM if(token=sh_lex(lexp)) 15624887Schin { 1563*8462SApril.Chin@Sun.COM if(token==RPAREN && (iof&IOLSEEK) && lexp->comsub) 15644887Schin { 1565*8462SApril.Chin@Sun.COM lexp->arg = (struct argnod*)stkalloc(stkp,sizeof(struct argnod)+3); 1566*8462SApril.Chin@Sun.COM strcpy(lexp->arg->argval,"CUR"); 1567*8462SApril.Chin@Sun.COM lexp->arg->argflag = ARG_RAW; 15684887Schin iof |= IOARITH; 15694887Schin fcseek(-1); 15704887Schin } 15714887Schin else if(token==EXPRSYM && (iof&IOLSEEK)) 15724887Schin iof |= IOARITH; 15734887Schin else 1574*8462SApril.Chin@Sun.COM sh_syntax(lexp); 15754887Schin } 1576*8462SApril.Chin@Sun.COM iop->ioname=lexp->arg->argval; 15774887Schin iop->iovname = iovname; 15784887Schin if(iof&IODOC) 15794887Schin { 1580*8462SApril.Chin@Sun.COM if(lexp->digits==2) 15814887Schin { 15824887Schin iof |= IOSTRG; 1583*8462SApril.Chin@Sun.COM if(!(lexp->arg->argflag&ARG_RAW)) 15844887Schin iof &= ~IORAW; 15854887Schin } 15864887Schin else 15874887Schin { 1588*8462SApril.Chin@Sun.COM if(!lexp->sh->heredocs) 1589*8462SApril.Chin@Sun.COM lexp->sh->heredocs = sftmp(HERE_MEM); 1590*8462SApril.Chin@Sun.COM iop->iolst=lexp->heredoc; 1591*8462SApril.Chin@Sun.COM lexp->heredoc=iop; 1592*8462SApril.Chin@Sun.COM if(lexp->arg->argflag&ARG_QUOTED) 15934887Schin iof |= IOQUOTE; 1594*8462SApril.Chin@Sun.COM if(lexp->digits==3) 15954887Schin iof |= IOLSEEK; 1596*8462SApril.Chin@Sun.COM if(lexp->digits) 15974887Schin iof |= IOSTRIP; 15984887Schin } 15994887Schin } 16004887Schin else 16014887Schin { 16024887Schin iop->iolst = 0; 1603*8462SApril.Chin@Sun.COM if(lexp->arg->argflag&ARG_RAW) 16044887Schin iof |= IORAW; 16054887Schin } 16064887Schin iop->iofile=iof; 16074887Schin if(flag>0) 16084887Schin /* allow alias substitutions and parameter assignments */ 1609*8462SApril.Chin@Sun.COM lexp->aliasok = lexp->assignok = 1; 16104887Schin #if SHOPT_KIA 1611*8462SApril.Chin@Sun.COM if(lexp->kiafile) 16124887Schin { 1613*8462SApril.Chin@Sun.COM int n = lexp->sh->inlineno-(lexp->token=='\n'); 16144887Schin if(!(iof&IOMOV)) 16154887Schin { 1616*8462SApril.Chin@Sun.COM unsigned long r=kiaentity(lexp,(iof&IORAW)?sh_fmtq(iop->ioname):iop->ioname,-1,'f',0,0,lexp->script,'f',0,""); 1617*8462SApril.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); 16184887Schin } 16194887Schin } 16204887Schin #endif /* SHOPT_KIA */ 16214887Schin if(flag>=0) 16224887Schin { 16234887Schin struct ionod *ioq=iop; 1624*8462SApril.Chin@Sun.COM sh_lex(lexp); 16254887Schin #if SHOPT_BASH 16264887Schin if(errout) 16274887Schin { 16284887Schin /* redirect standard output to standard error */ 1629*8462SApril.Chin@Sun.COM ioq = (struct ionod*)stkalloc(stkp,sizeof(struct ionod)); 16304887Schin ioq->ioname = "1"; 16314887Schin ioq->iolst = 0; 16324887Schin ioq->iodelim = 0; 16334887Schin ioq->iofile = IORAW|IOPUT|IOMOV|2; 16344887Schin iop->ionxt=ioq; 16354887Schin } 16364887Schin #endif 1637*8462SApril.Chin@Sun.COM ioq->ionxt=inout(lexp,lastio,flag); 16384887Schin } 16394887Schin else 16404887Schin iop->ionxt=0; 16414887Schin return(iop); 16424887Schin } 16434887Schin 16444887Schin /* 16454887Schin * convert argument chain to argument list when no special arguments 16464887Schin */ 16474887Schin 16484887Schin static struct argnod *qscan(struct comnod *ac,int argn) 16494887Schin { 16504887Schin register char **cp; 16514887Schin register struct argnod *ap; 16524887Schin register struct dolnod* dp; 16534887Schin register int special=0; 16544887Schin /* special hack for test -t compatibility */ 16554887Schin if((Namval_t*)ac->comnamp==SYSTEST) 16564887Schin special = 2; 16574887Schin else if(*(ac->comarg->argval)=='[' && ac->comarg->argval[1]==0) 16584887Schin special = 3; 16594887Schin if(special) 16604887Schin { 16614887Schin ap = ac->comarg->argnxt.ap; 16624887Schin if(argn==(special+1) && ap->argval[1]==0 && *ap->argval=='!') 16634887Schin ap = ap->argnxt.ap; 16644887Schin else if(argn!=special) 16654887Schin special=0; 16664887Schin } 16674887Schin if(special) 16684887Schin { 16694887Schin const char *message; 16704887Schin if(strcmp(ap->argval,"-t")) 16714887Schin { 16724887Schin message = "line %d: Invariant test"; 16734887Schin special=0; 16744887Schin } 16754887Schin else 16764887Schin { 16774887Schin message = "line %d: -t requires argument"; 16784887Schin argn++; 16794887Schin } 16804887Schin if(sh_isoption(SH_NOEXEC)) 16814887Schin errormsg(SH_DICT,ERROR_warn(0),message,ac->comline); 16824887Schin } 16834887Schin /* leave space for an extra argument at the front */ 16844887Schin dp = (struct dolnod*)stakalloc((unsigned)sizeof(struct dolnod) + ARG_SPARE*sizeof(char*) + argn*sizeof(char*)); 16854887Schin cp = dp->dolval+ARG_SPARE; 16864887Schin dp->dolnum = argn; 16874887Schin dp->dolbot = ARG_SPARE; 16884887Schin ap = ac->comarg; 16894887Schin while(ap) 16904887Schin { 16914887Schin *cp++ = ap->argval; 16924887Schin ap = ap->argnxt.ap; 16934887Schin } 16944887Schin if(special==3) 16954887Schin { 16964887Schin cp[0] = cp[-1]; 16974887Schin cp[-1] = "1"; 16984887Schin cp++; 16994887Schin } 17004887Schin else if(special) 17014887Schin *cp++ = "1"; 17024887Schin *cp = 0; 17034887Schin return((struct argnod*)dp); 17044887Schin } 17054887Schin 1706*8462SApril.Chin@Sun.COM static Shnode_t *test_expr(Lex_t *lp,int sym) 17074887Schin { 1708*8462SApril.Chin@Sun.COM register Shnode_t *t = test_or(lp); 1709*8462SApril.Chin@Sun.COM if(lp->token!=sym) 1710*8462SApril.Chin@Sun.COM sh_syntax(lp); 17114887Schin return(t); 17124887Schin } 17134887Schin 1714*8462SApril.Chin@Sun.COM static Shnode_t *test_or(Lex_t *lp) 17154887Schin { 1716*8462SApril.Chin@Sun.COM register Shnode_t *t = test_and(lp); 1717*8462SApril.Chin@Sun.COM while(lp->token==ORFSYM) 1718*8462SApril.Chin@Sun.COM t = makelist(lp,TORF|TTEST,t,test_and(lp)); 17194887Schin return(t); 17204887Schin } 17214887Schin 1722*8462SApril.Chin@Sun.COM static Shnode_t *test_and(Lex_t *lp) 17234887Schin { 1724*8462SApril.Chin@Sun.COM register Shnode_t *t = test_primary(lp); 1725*8462SApril.Chin@Sun.COM while(lp->token==ANDFSYM) 1726*8462SApril.Chin@Sun.COM t = makelist(lp,TAND|TTEST,t,test_primary(lp)); 17274887Schin return(t); 17284887Schin } 17294887Schin 17304887Schin /* 17314887Schin * convert =~ into == ~(E) 17324887Schin */ 17334887Schin static void ere_match(void) 17344887Schin { 17354887Schin Sfio_t *base, *iop = sfopen((Sfio_t*)0," ~(E)","s"); 17364887Schin register int c; 17374887Schin while( fcgetc(c),(c==' ' || c=='\t')); 17384887Schin if(c) 17394887Schin fcseek(-1); 17404887Schin if(!(base=fcfile())) 17414887Schin base = sfopen(NIL(Sfio_t*),fcseek(0),"s"); 17424887Schin fcclose(); 17434887Schin sfstack(base,iop); 17444887Schin fcfopen(base); 17454887Schin } 17464887Schin 1747*8462SApril.Chin@Sun.COM static Shnode_t *test_primary(Lex_t *lexp) 17484887Schin { 17494887Schin register struct argnod *arg; 17504887Schin register Shnode_t *t; 17514887Schin register int num,token; 1752*8462SApril.Chin@Sun.COM token = skipnl(lexp,0); 1753*8462SApril.Chin@Sun.COM num = lexp->digits; 17544887Schin switch(token) 17554887Schin { 17564887Schin case '(': 1757*8462SApril.Chin@Sun.COM t = test_expr(lexp,')'); 1758*8462SApril.Chin@Sun.COM t = makelist(lexp,TTST|TTEST|TPAREN ,t, (Shnode_t*)pointerof(lexp->sh->inlineno)); 17594887Schin break; 17604887Schin case '!': 1761*8462SApril.Chin@Sun.COM if(!(t = test_primary(lexp))) 1762*8462SApril.Chin@Sun.COM sh_syntax(lexp); 17634887Schin t->tre.tretyp |= TNEGATE; 17644887Schin return(t); 17654887Schin case TESTUNOP: 1766*8462SApril.Chin@Sun.COM if(sh_lex(lexp)) 1767*8462SApril.Chin@Sun.COM sh_syntax(lexp); 17684887Schin #if SHOPT_KIA 1769*8462SApril.Chin@Sun.COM if(lexp->kiafile && !strchr("sntzoOG",num)) 17704887Schin { 1771*8462SApril.Chin@Sun.COM int line = lexp->sh->inlineno- (lexp->token==NL); 17724887Schin unsigned long r; 1773*8462SApril.Chin@Sun.COM r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->script,'t',0,""); 1774*8462SApril.Chin@Sun.COM sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line); 17754887Schin } 17764887Schin #endif /* SHOPT_KIA */ 1777*8462SApril.Chin@Sun.COM t = makelist(lexp,TTST|TTEST|TUNARY|(num<<TSHIFT), 1778*8462SApril.Chin@Sun.COM (Shnode_t*)lexp->arg,(Shnode_t*)lexp->arg); 1779*8462SApril.Chin@Sun.COM t->tst.tstline = lexp->sh->inlineno; 17804887Schin break; 17814887Schin /* binary test operators */ 17824887Schin case 0: 1783*8462SApril.Chin@Sun.COM arg = lexp->arg; 1784*8462SApril.Chin@Sun.COM if((token=sh_lex(lexp))==TESTBINOP) 17854887Schin { 1786*8462SApril.Chin@Sun.COM num = lexp->digits; 17874887Schin if(num==TEST_REP) 17884887Schin { 17894887Schin ere_match(); 17904887Schin num = TEST_PEQ; 17914887Schin } 17924887Schin } 17934887Schin else if(token=='<') 17944887Schin num = TEST_SLT; 17954887Schin else if(token=='>') 17964887Schin num = TEST_SGT; 17974887Schin else if(token==ANDFSYM||token==ORFSYM||token==ETESTSYM||token==RPAREN) 17984887Schin { 1799*8462SApril.Chin@Sun.COM t = makelist(lexp,TTST|TTEST|TUNARY|('n'<<TSHIFT), 18004887Schin (Shnode_t*)arg,(Shnode_t*)arg); 1801*8462SApril.Chin@Sun.COM t->tst.tstline = lexp->sh->inlineno; 18024887Schin return(t); 18034887Schin } 18044887Schin else 1805*8462SApril.Chin@Sun.COM sh_syntax(lexp); 18064887Schin #if SHOPT_KIA 1807*8462SApril.Chin@Sun.COM if(lexp->kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT)) 18084887Schin { 1809*8462SApril.Chin@Sun.COM int line = lexp->sh->inlineno- (lexp->token==NL); 18104887Schin unsigned long r; 1811*8462SApril.Chin@Sun.COM r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->current,'t',0,""); 1812*8462SApril.Chin@Sun.COM sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line); 18134887Schin } 18144887Schin #endif /* SHOPT_KIA */ 1815*8462SApril.Chin@Sun.COM if(sh_lex(lexp)) 1816*8462SApril.Chin@Sun.COM sh_syntax(lexp); 18174887Schin if(num&TEST_PATTERN) 18184887Schin { 1819*8462SApril.Chin@Sun.COM if(lexp->arg->argflag&(ARG_EXP|ARG_MAC)) 18204887Schin num &= ~TEST_PATTERN; 18214887Schin } 18224887Schin t = getnode(tstnod); 18234887Schin t->lst.lsttyp = TTST|TTEST|TBINARY|(num<<TSHIFT); 18244887Schin t->lst.lstlef = (Shnode_t*)arg; 1825*8462SApril.Chin@Sun.COM t->lst.lstrit = (Shnode_t*)lexp->arg; 1826*8462SApril.Chin@Sun.COM t->tst.tstline = lexp->sh->inlineno; 18274887Schin #if SHOPT_KIA 1828*8462SApril.Chin@Sun.COM if(lexp->kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT)) 18294887Schin { 1830*8462SApril.Chin@Sun.COM int line = lexp->sh->inlineno-(lexp->token==NL); 18314887Schin unsigned long r; 1832*8462SApril.Chin@Sun.COM r=kiaentity(lexp,sh_argstr(lexp->arg),-1,'f',0,0,lexp->current,'t',0,""); 1833*8462SApril.Chin@Sun.COM sfprintf(lexp->kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",lexp->current,r,line,line); 18344887Schin } 18354887Schin #endif /* SHOPT_KIA */ 18364887Schin break; 18374887Schin default: 18384887Schin return(0); 18394887Schin } 1840*8462SApril.Chin@Sun.COM skipnl(lexp,0); 18414887Schin return(t); 18424887Schin } 18434887Schin 18444887Schin #if SHOPT_KIA 18454887Schin /* 18464887Schin * return an entity checksum 18474887Schin * The entity is created if it doesn't exist 18484887Schin */ 1849*8462SApril.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) 18504887Schin { 1851*8462SApril.Chin@Sun.COM Stk_t *stkp = lexp->sh->stk; 18524887Schin Namval_t *np; 1853*8462SApril.Chin@Sun.COM long offset = stktell(stkp); 1854*8462SApril.Chin@Sun.COM sfputc(stkp,type); 18554887Schin if(len>0) 1856*8462SApril.Chin@Sun.COM sfwrite(stkp,name,len); 18574887Schin else 18584887Schin { 18594887Schin if(type=='p') 1860*8462SApril.Chin@Sun.COM sfputr(stkp,path_basename(name),0); 18614887Schin else 1862*8462SApril.Chin@Sun.COM sfputr(stkp,name,0); 18634887Schin } 1864*8462SApril.Chin@Sun.COM np = nv_search(stakptr(offset),lexp->entity_tree,NV_ADD); 1865*8462SApril.Chin@Sun.COM stkseek(stkp,offset); 18664887Schin np->nvalue.i = pkind; 18674887Schin nv_setsize(np,width); 18684887Schin if(!nv_isattr(np,NV_TAGGED) && first>=0) 18694887Schin { 18704887Schin nv_onattr(np,NV_TAGGED); 18714887Schin if(!pkind) 18724887Schin pkind = '0'; 18734887Schin if(len>0) 1874*8462SApril.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); 18754887Schin else 1876*8462SApril.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); 18774887Schin } 18784887Schin return(np->hash); 18794887Schin } 18804887Schin 18814887Schin static void kia_add(register Namval_t *np, void *data) 18824887Schin { 18834887Schin char *name = nv_name(np); 1884*8462SApril.Chin@Sun.COM Lex_t *lp = (Lex_t*)data; 18854887Schin NOT_USED(data); 1886*8462SApril.Chin@Sun.COM kiaentity(lp,name+1,-1,*name,0,-1,(*name=='p'?lp->unknown:lp->script),np->nvalue.i,nv_size(np),""); 18874887Schin } 18884887Schin 1889*8462SApril.Chin@Sun.COM int kiaclose(Lex_t *lexp) 18904887Schin { 18914887Schin register off_t off1,off2; 18924887Schin register int n; 1893*8462SApril.Chin@Sun.COM if(lexp->kiafile) 18944887Schin { 1895*8462SApril.Chin@Sun.COM unsigned long r = kiaentity(lexp,lexp->scriptname,-1,'p',-1,lexp->sh->inlineno-1,0,'s',0,""); 1896*8462SApril.Chin@Sun.COM kiaentity(lexp,lexp->scriptname,-1,'p',1,lexp->sh->inlineno-1,r,'s',0,""); 1897*8462SApril.Chin@Sun.COM kiaentity(lexp,lexp->scriptname,-1,'f',1,lexp->sh->inlineno-1,r,'s',0,""); 1898*8462SApril.Chin@Sun.COM nv_scan(lexp->entity_tree,kia_add,(void*)lexp,NV_TAGGED,0); 1899*8462SApril.Chin@Sun.COM off1 = sfseek(lexp->kiafile,(off_t)0,SEEK_END); 1900*8462SApril.Chin@Sun.COM sfseek(lexp->kiatmp,(off_t)0,SEEK_SET); 1901*8462SApril.Chin@Sun.COM sfmove(lexp->kiatmp,lexp->kiafile,SF_UNBOUND,-1); 1902*8462SApril.Chin@Sun.COM off2 = sfseek(lexp->kiafile,(off_t)0,SEEK_END); 19034887Schin #ifdef SF_BUFCONST 19044887Schin if(off2==off1) 1905*8462SApril.Chin@Sun.COM n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%lld;%d\nDIRECTORY;",(Sflong_t)lexp->kiabegin,(size_t)(off1-lexp->kiabegin)); 19064887Schin else 1907*8462SApril.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)); 19084887Schin if(off2 >= INT_MAX) 19094887Schin off2 = -(n+12); 1910*8462SApril.Chin@Sun.COM sfprintf(lexp->kiafile,"%010.10lld;%010d\n",(Sflong_t)off2+10, n+12); 19114887Schin #else 19124887Schin if(off2==off1) 1913*8462SApril.Chin@Sun.COM n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%d;%d\nDIRECTORY;",lexp->kiabegin,off1-lexp->kiabegin); 19144887Schin else 1915*8462SApril.Chin@Sun.COM n= sfprintf(lexp->kiafile,"DIRECTORY\nENTITY;%d;%d\nRELATIONSHIP;%d;%d\nDIRECTORY;",lexp->kiabegin,off1-lexp->kiabegin,off1,off2-off1); 1916*8462SApril.Chin@Sun.COM sfprintf(lexp->kiafile,"%010d;%010d\n",off2+10, n+12); 19174887Schin #endif 19184887Schin } 1919*8462SApril.Chin@Sun.COM return(sfclose(lexp->kiafile)); 19204887Schin } 19214887Schin #endif /* SHOPT_KIA */ 1922