1*4887Schin /*********************************************************************** 2*4887Schin * * 3*4887Schin * This software is part of the ast package * 4*4887Schin * Copyright (c) 1982-2007 AT&T Knowledge Ventures * 5*4887Schin * and is licensed under the * 6*4887Schin * Common Public License, Version 1.0 * 7*4887Schin * by AT&T Knowledge Ventures * 8*4887Schin * * 9*4887Schin * A copy of the License is available at * 10*4887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 11*4887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12*4887Schin * * 13*4887Schin * Information and Software Systems Research * 14*4887Schin * AT&T Research * 15*4887Schin * Florham Park NJ * 16*4887Schin * * 17*4887Schin * David Korn <dgk@research.att.com> * 18*4887Schin * * 19*4887Schin ***********************************************************************/ 20*4887Schin #pragma prototyped 21*4887Schin /* 22*4887Schin * UNIX shell 23*4887Schin * 24*4887Schin * S. R. Bourne 25*4887Schin * Rewritten by David Korn 26*4887Schin * AT&T Labs 27*4887Schin * 28*4887Schin * This is the parser for a shell language 29*4887Schin */ 30*4887Schin 31*4887Schin #if KSHELL 32*4887Schin #include "defs.h" 33*4887Schin #else 34*4887Schin #include <shell.h> 35*4887Schin #endif 36*4887Schin #include <ctype.h> 37*4887Schin #include <fcin.h> 38*4887Schin #include <error.h> 39*4887Schin #include "shlex.h" 40*4887Schin #include "history.h" 41*4887Schin #include "builtins.h" 42*4887Schin #include "test.h" 43*4887Schin #include "history.h" 44*4887Schin 45*4887Schin #define HERE_MEM 1024 /* size of here-docs kept in memory */ 46*4887Schin 47*4887Schin #define hash nvlink.hl._hash 48*4887Schin 49*4887Schin /* These routines are local to this module */ 50*4887Schin 51*4887Schin static Shnode_t *makeparent(int, Shnode_t*); 52*4887Schin static Shnode_t *makelist(int, Shnode_t*, Shnode_t*); 53*4887Schin static struct argnod *qscan(struct comnod*, int); 54*4887Schin static struct ionod *inout(struct ionod*, int); 55*4887Schin static Shnode_t *sh_cmd(int,int); 56*4887Schin static Shnode_t *term(int); 57*4887Schin static Shnode_t *list(int); 58*4887Schin static struct regnod *syncase(int); 59*4887Schin static Shnode_t *item(int); 60*4887Schin static Shnode_t *simple(int, struct ionod*); 61*4887Schin static int skipnl(int); 62*4887Schin static Shnode_t *test_expr(int); 63*4887Schin static Shnode_t *test_and(void); 64*4887Schin static Shnode_t *test_or(void); 65*4887Schin static Shnode_t *test_primary(void); 66*4887Schin 67*4887Schin #define sh_getlineno() (shlex.lastline) 68*4887Schin 69*4887Schin #ifndef NIL 70*4887Schin # define NIL(type) ((type)0) 71*4887Schin #endif /* NIL */ 72*4887Schin #define CNTL(x) ((x)&037) 73*4887Schin 74*4887Schin 75*4887Schin #if !KSHELL 76*4887Schin static struct stdata 77*4887Schin { 78*4887Schin struct slnod *staklist; 79*4887Schin int cmdline; 80*4887Schin } st; 81*4887Schin #endif 82*4887Schin 83*4887Schin static int loop_level; 84*4887Schin static struct argnod *label_list; 85*4887Schin static struct argnod *label_last; 86*4887Schin 87*4887Schin #define getnode(type) ((Shnode_t*)stakalloc(sizeof(struct type))) 88*4887Schin 89*4887Schin #if SHOPT_KIA 90*4887Schin #include "path.h" 91*4887Schin /* 92*4887Schin * write out entities for each item in the list 93*4887Schin * type=='V' for variable assignment lists 94*4887Schin * Otherwise type is determined by the command */ 95*4887Schin static unsigned long writedefs(struct argnod *arglist, int line, int type, struct argnod *cmd) 96*4887Schin { 97*4887Schin register struct argnod *argp = arglist; 98*4887Schin register char *cp; 99*4887Schin register int n,eline; 100*4887Schin int width=0; 101*4887Schin unsigned long r=0; 102*4887Schin static char atbuff[20]; 103*4887Schin int justify=0; 104*4887Schin char *attribute = atbuff; 105*4887Schin unsigned long parent=shlex.script; 106*4887Schin if(type==0) 107*4887Schin { 108*4887Schin parent = shlex.current; 109*4887Schin type = 'v'; 110*4887Schin switch(*argp->argval) 111*4887Schin { 112*4887Schin case 'a': 113*4887Schin type='p'; 114*4887Schin justify = 'a'; 115*4887Schin break; 116*4887Schin case 'e': 117*4887Schin *attribute++ = 'x'; 118*4887Schin break; 119*4887Schin case 'r': 120*4887Schin *attribute++ = 'r'; 121*4887Schin break; 122*4887Schin case 'l': 123*4887Schin break; 124*4887Schin } 125*4887Schin while(argp = argp->argnxt.ap) 126*4887Schin { 127*4887Schin if((n= *(cp=argp->argval))!='-' && n!='+') 128*4887Schin break; 129*4887Schin if(cp[1]==n) 130*4887Schin break; 131*4887Schin while((n= *++cp)) 132*4887Schin { 133*4887Schin if(isdigit(n)) 134*4887Schin width = 10*width + n-'0'; 135*4887Schin else if(n=='L' || n=='R' || n =='Z') 136*4887Schin justify=n; 137*4887Schin else 138*4887Schin *attribute++ = n; 139*4887Schin } 140*4887Schin } 141*4887Schin } 142*4887Schin else if(cmd) 143*4887Schin parent=kiaentity(sh_argstr(cmd),-1,'p',-1,-1,shlex.unknown,'b',0,""); 144*4887Schin *attribute = 0; 145*4887Schin while(argp) 146*4887Schin { 147*4887Schin if((cp=strchr(argp->argval,'='))||(cp=strchr(argp->argval,'?'))) 148*4887Schin n = cp-argp->argval; 149*4887Schin else 150*4887Schin n = strlen(argp->argval); 151*4887Schin eline = sh.inlineno-(shlex.token==NL); 152*4887Schin r=kiaentity(argp->argval,n,type,line,eline,parent,justify,width,atbuff); 153*4887Schin sfprintf(shlex.kiatmp,"p;%..64d;v;%..64d;%d;%d;s;\n",shlex.current,r,line,eline); 154*4887Schin argp = argp->argnxt.ap; 155*4887Schin } 156*4887Schin return(r); 157*4887Schin } 158*4887Schin #endif /* SHOPT_KIA */ 159*4887Schin /* 160*4887Schin * Make a parent node for fork() or io-redirection 161*4887Schin */ 162*4887Schin static Shnode_t *makeparent(int flag, Shnode_t *child) 163*4887Schin { 164*4887Schin register Shnode_t *par = getnode(forknod); 165*4887Schin par->fork.forktyp = flag; 166*4887Schin par->fork.forktre = child; 167*4887Schin par->fork.forkio = 0; 168*4887Schin par->fork.forkline = sh_getlineno()-1; 169*4887Schin return(par); 170*4887Schin } 171*4887Schin 172*4887Schin static Shnode_t *getanode(struct argnod *ap) 173*4887Schin { 174*4887Schin register Shnode_t *t = getnode(arithnod); 175*4887Schin t->ar.artyp = TARITH; 176*4887Schin t->ar.arline = sh_getlineno(); 177*4887Schin t->ar.arexpr = ap; 178*4887Schin if(ap->argflag&ARG_RAW) 179*4887Schin t->ar.arcomp = sh_arithcomp(ap->argval); 180*4887Schin else 181*4887Schin t->ar.arcomp = 0; 182*4887Schin return(t); 183*4887Schin } 184*4887Schin 185*4887Schin /* 186*4887Schin * Make a node corresponding to a command list 187*4887Schin */ 188*4887Schin static Shnode_t *makelist(int type, Shnode_t *l, Shnode_t *r) 189*4887Schin { 190*4887Schin register Shnode_t *t; 191*4887Schin if(!l || !r) 192*4887Schin sh_syntax(); 193*4887Schin else 194*4887Schin { 195*4887Schin if((type&COMMSK) == TTST) 196*4887Schin t = getnode(tstnod); 197*4887Schin else 198*4887Schin t = getnode(lstnod); 199*4887Schin t->lst.lsttyp = type; 200*4887Schin t->lst.lstlef = l; 201*4887Schin t->lst.lstrit = r; 202*4887Schin } 203*4887Schin return(t); 204*4887Schin } 205*4887Schin 206*4887Schin /* 207*4887Schin * entry to shell parser 208*4887Schin * Flag can be the union of SH_EOF|SH_NL 209*4887Schin */ 210*4887Schin 211*4887Schin void *sh_parse(Shell_t *shp, Sfio_t *iop, int flag) 212*4887Schin { 213*4887Schin register Shnode_t *t; 214*4887Schin Fcin_t sav_input; 215*4887Schin struct argnod *sav_arg = shlex.arg; 216*4887Schin int sav_prompt = shp->nextprompt; 217*4887Schin if(shp->binscript && sffileno(iop)==shp->infd) 218*4887Schin return((void*)sh_trestore(iop)); 219*4887Schin fcsave(&sav_input); 220*4887Schin shp->st.staklist = 0; 221*4887Schin shlex.heredoc = 0; 222*4887Schin shlex.inlineno = shp->inlineno; 223*4887Schin shlex.firstline = shp->st.firstline; 224*4887Schin shp->nextprompt = 1; 225*4887Schin loop_level = 0; 226*4887Schin label_list = label_last = 0; 227*4887Schin if(sh_isoption(SH_INTERACTIVE)) 228*4887Schin sh_onstate(SH_INTERACTIVE); 229*4887Schin if(sh_isoption(SH_VERBOSE)) 230*4887Schin sh_onstate(SH_VERBOSE); 231*4887Schin sh_lexopen((Lex_t*)shp->lex_context,shp,0); 232*4887Schin if(fcfopen(iop) < 0) 233*4887Schin return(NIL(void*)); 234*4887Schin if(fcfile()) 235*4887Schin { 236*4887Schin char *cp = fcfirst(); 237*4887Schin if( cp[0]==CNTL('k') && cp[1]==CNTL('s') && cp[2]==CNTL('h') && cp[3]==0) 238*4887Schin { 239*4887Schin int version; 240*4887Schin fcseek(4); 241*4887Schin fcgetc(version); 242*4887Schin fcclose(); 243*4887Schin fcrestore(&sav_input); 244*4887Schin shlex.arg = sav_arg; 245*4887Schin if(version > 3) 246*4887Schin errormsg(SH_DICT,ERROR_exit(1),e_lexversion); 247*4887Schin if(sffileno(iop)==shp->infd) 248*4887Schin shp->binscript = 1; 249*4887Schin sfgetc(iop); 250*4887Schin return((void*)sh_trestore(iop)); 251*4887Schin } 252*4887Schin } 253*4887Schin if((flag&SH_NL) && (shp->inlineno=error_info.line+shp->st.firstline)==0) 254*4887Schin shp->inlineno=1; 255*4887Schin #if KSHELL 256*4887Schin shp->nextprompt = 2; 257*4887Schin #endif 258*4887Schin t = sh_cmd((flag&SH_EOF)?EOFSYM:'\n',SH_SEMI|SH_EMPTY|(flag&SH_NL)); 259*4887Schin fcclose(); 260*4887Schin fcrestore(&sav_input); 261*4887Schin shlex.arg = sav_arg; 262*4887Schin /* unstack any completed alias expansions */ 263*4887Schin if((sfset(iop,0,0)&SF_STRING) && !sfreserve(iop,0,-1)) 264*4887Schin { 265*4887Schin Sfio_t *sp = sfstack(iop,NULL); 266*4887Schin if(sp) 267*4887Schin sfclose(sp); 268*4887Schin } 269*4887Schin shp->nextprompt = sav_prompt; 270*4887Schin if(flag&SH_NL) 271*4887Schin { 272*4887Schin shp->st.firstline = shlex.firstline; 273*4887Schin shp->inlineno = shlex.inlineno; 274*4887Schin } 275*4887Schin stakseek(0); 276*4887Schin return((void*)t); 277*4887Schin } 278*4887Schin 279*4887Schin /* 280*4887Schin * This routine parses up the matching right parenthesis and returns 281*4887Schin * the parse tree 282*4887Schin */ 283*4887Schin Shnode_t *sh_dolparen(void) 284*4887Schin { 285*4887Schin register Shnode_t *t=0; 286*4887Schin register Lex_t *lp = (Lex_t*)sh.lex_context; 287*4887Schin Sfio_t *sp = fcfile(); 288*4887Schin int line = sh.inlineno; 289*4887Schin sh.inlineno = error_info.line+sh.st.firstline; 290*4887Schin sh_lexopen(lp,&sh,1); 291*4887Schin shlex.comsub = 1; 292*4887Schin switch(sh_lex()) 293*4887Schin { 294*4887Schin /* ((...)) arithmetic expression */ 295*4887Schin case EXPRSYM: 296*4887Schin t = getanode(shlex.arg); 297*4887Schin break; 298*4887Schin case LPAREN: 299*4887Schin t = sh_cmd(RPAREN,SH_NL|SH_EMPTY); 300*4887Schin break; 301*4887Schin } 302*4887Schin shlex.comsub = 0; 303*4887Schin if(!sp && (sp=fcfile())) 304*4887Schin { 305*4887Schin /* 306*4887Schin * This code handles the case where string has been converted 307*4887Schin * to a file by an alias setup 308*4887Schin */ 309*4887Schin register int c; 310*4887Schin char *cp; 311*4887Schin if(fcgetc(c) > 0) 312*4887Schin fcseek(-1); 313*4887Schin cp = fcseek(0); 314*4887Schin fcclose(); 315*4887Schin fcsopen(cp); 316*4887Schin sfclose(sp); 317*4887Schin } 318*4887Schin sh.inlineno = line; 319*4887Schin return(t); 320*4887Schin } 321*4887Schin 322*4887Schin /* 323*4887Schin * remove temporary files and stacks 324*4887Schin */ 325*4887Schin 326*4887Schin void sh_freeup(void) 327*4887Schin { 328*4887Schin if(sh.st.staklist) 329*4887Schin sh_funstaks(sh.st.staklist,-1); 330*4887Schin sh.st.staklist = 0; 331*4887Schin } 332*4887Schin 333*4887Schin /* 334*4887Schin * increase reference count for each stack in function list when flag>0 335*4887Schin * decrease reference count for each stack in function list when flag<=0 336*4887Schin * stack is freed when reference count is zero 337*4887Schin */ 338*4887Schin 339*4887Schin void sh_funstaks(register struct slnod *slp,int flag) 340*4887Schin { 341*4887Schin register struct slnod *slpold; 342*4887Schin while(slpold=slp) 343*4887Schin { 344*4887Schin if(slp->slchild) 345*4887Schin sh_funstaks(slp->slchild,flag); 346*4887Schin slp = slp->slnext; 347*4887Schin if(flag<=0) 348*4887Schin stakdelete(slpold->slptr); 349*4887Schin else 350*4887Schin staklink(slpold->slptr); 351*4887Schin } 352*4887Schin } 353*4887Schin /* 354*4887Schin * cmd 355*4887Schin * empty 356*4887Schin * list 357*4887Schin * list & [ cmd ] 358*4887Schin * list [ ; cmd ] 359*4887Schin */ 360*4887Schin 361*4887Schin static Shnode_t *sh_cmd(register int sym, int flag) 362*4887Schin { 363*4887Schin register Shnode_t *left, *right; 364*4887Schin register int type = FINT|FAMP; 365*4887Schin if(sym==NL) 366*4887Schin shlex.lasttok = 0; 367*4887Schin left = list(flag); 368*4887Schin if(shlex.token==NL) 369*4887Schin { 370*4887Schin if(flag&SH_NL) 371*4887Schin shlex.token=';'; 372*4887Schin } 373*4887Schin else if(!left && !(flag&SH_EMPTY)) 374*4887Schin sh_syntax(); 375*4887Schin switch(shlex.token) 376*4887Schin { 377*4887Schin case COOPSYM: /* set up a cooperating process */ 378*4887Schin type |= (FPIN|FPOU|FPCL|FCOOP); 379*4887Schin /* FALL THRU */ 380*4887Schin case '&': 381*4887Schin if(left) 382*4887Schin { 383*4887Schin /* (...)& -> {...;} & */ 384*4887Schin if(left->tre.tretyp==TPAR) 385*4887Schin left = left->par.partre; 386*4887Schin left = makeparent(TFORK|type, left); 387*4887Schin } 388*4887Schin /* FALL THRU */ 389*4887Schin case ';': 390*4887Schin if(!left) 391*4887Schin sh_syntax(); 392*4887Schin if(right=sh_cmd(sym,flag|SH_EMPTY)) 393*4887Schin left=makelist(TLST, left, right); 394*4887Schin break; 395*4887Schin case EOFSYM: 396*4887Schin if(sym==NL) 397*4887Schin break; 398*4887Schin default: 399*4887Schin if(sym && sym!=shlex.token) 400*4887Schin { 401*4887Schin if(sym!=ELSESYM || (shlex.token!=ELIFSYM && shlex.token!=FISYM)) 402*4887Schin sh_syntax(); 403*4887Schin } 404*4887Schin } 405*4887Schin return(left); 406*4887Schin } 407*4887Schin 408*4887Schin /* 409*4887Schin * list 410*4887Schin * term 411*4887Schin * list && term 412*4887Schin * list || term 413*4887Schin * unfortunately, these are equal precedence 414*4887Schin */ 415*4887Schin static Shnode_t *list(register int flag) 416*4887Schin { 417*4887Schin register Shnode_t *t = term(flag); 418*4887Schin register int token; 419*4887Schin while(t && ((token=shlex.token)==ANDFSYM || token==ORFSYM)) 420*4887Schin t = makelist((token==ANDFSYM?TAND:TORF), t, term(SH_NL|SH_SEMI)); 421*4887Schin return(t); 422*4887Schin } 423*4887Schin 424*4887Schin /* 425*4887Schin * term 426*4887Schin * item 427*4887Schin * item | term 428*4887Schin */ 429*4887Schin static Shnode_t *term(register int flag) 430*4887Schin { 431*4887Schin register Shnode_t *t; 432*4887Schin register int token; 433*4887Schin if(flag&SH_NL) 434*4887Schin token = skipnl(flag); 435*4887Schin else 436*4887Schin token = sh_lex(); 437*4887Schin /* check to see if pipeline is to be timed */ 438*4887Schin if(token==TIMESYM || token==NOTSYM) 439*4887Schin { 440*4887Schin t = getnode(parnod); 441*4887Schin t->par.partyp=TTIME; 442*4887Schin if(shlex.token==NOTSYM) 443*4887Schin t->par.partyp |= COMSCAN; 444*4887Schin t->par.partre = term(0); 445*4887Schin } 446*4887Schin else if((t=item(SH_NL|SH_EMPTY|(flag&SH_SEMI))) && shlex.token=='|') 447*4887Schin { 448*4887Schin register Shnode_t *tt; 449*4887Schin int showme = t->tre.tretyp&FSHOWME; 450*4887Schin t = makeparent(TFORK|FPOU,t); 451*4887Schin if(tt=term(SH_NL)) 452*4887Schin { 453*4887Schin switch(tt->tre.tretyp&COMMSK) 454*4887Schin { 455*4887Schin case TFORK: 456*4887Schin tt->tre.tretyp |= FPIN|FPCL; 457*4887Schin break; 458*4887Schin case TFIL: 459*4887Schin tt->lst.lstlef->tre.tretyp |= FPIN|FPCL; 460*4887Schin break; 461*4887Schin default: 462*4887Schin tt= makeparent(TSETIO|FPIN|FPCL,tt); 463*4887Schin } 464*4887Schin t=makelist(TFIL,t,tt); 465*4887Schin t->tre.tretyp |= showme; 466*4887Schin } 467*4887Schin else if(shlex.token) 468*4887Schin sh_syntax(); 469*4887Schin } 470*4887Schin return(t); 471*4887Schin } 472*4887Schin 473*4887Schin /* 474*4887Schin * case statement 475*4887Schin */ 476*4887Schin static struct regnod* syncase(register int esym) 477*4887Schin { 478*4887Schin register int tok = skipnl(0); 479*4887Schin register struct regnod *r; 480*4887Schin if(tok==esym) 481*4887Schin return(NIL(struct regnod*)); 482*4887Schin r = (struct regnod*)stakalloc(sizeof(struct regnod)); 483*4887Schin r->regptr=0; 484*4887Schin r->regflag=0; 485*4887Schin if(tok==LPAREN) 486*4887Schin skipnl(0); 487*4887Schin while(1) 488*4887Schin { 489*4887Schin if(!shlex.arg) 490*4887Schin sh_syntax(); 491*4887Schin shlex.arg->argnxt.ap=r->regptr; 492*4887Schin r->regptr = shlex.arg; 493*4887Schin if((tok=sh_lex())==RPAREN) 494*4887Schin break; 495*4887Schin else if(tok=='|') 496*4887Schin sh_lex(); 497*4887Schin else 498*4887Schin sh_syntax(); 499*4887Schin } 500*4887Schin r->regcom=sh_cmd(0,SH_NL|SH_EMPTY|SH_SEMI); 501*4887Schin if((tok=shlex.token)==BREAKCASESYM) 502*4887Schin r->regnxt=syncase(esym); 503*4887Schin else if(tok==FALLTHRUSYM) 504*4887Schin { 505*4887Schin r->regflag++; 506*4887Schin r->regnxt=syncase(esym); 507*4887Schin } 508*4887Schin else 509*4887Schin { 510*4887Schin if(tok!=esym && tok!=EOFSYM) 511*4887Schin sh_syntax(); 512*4887Schin r->regnxt=0; 513*4887Schin } 514*4887Schin if(shlex.token==EOFSYM) 515*4887Schin return(NIL(struct regnod*)); 516*4887Schin return(r); 517*4887Schin } 518*4887Schin 519*4887Schin /* 520*4887Schin * This routine creates the parse tree for the arithmetic for 521*4887Schin * When called, shlex.arg contains the string inside ((...)) 522*4887Schin * When the first argument is missing, a while node is returned 523*4887Schin * Otherise a list containing an arithmetic command and a while 524*4887Schin * is returned. 525*4887Schin */ 526*4887Schin static Shnode_t *arithfor(register Shnode_t *tf) 527*4887Schin { 528*4887Schin register Shnode_t *t, *tw = tf; 529*4887Schin register int offset; 530*4887Schin register struct argnod *argp; 531*4887Schin register int n; 532*4887Schin int argflag = shlex.arg->argflag; 533*4887Schin /* save current input */ 534*4887Schin Fcin_t sav_input; 535*4887Schin fcsave(&sav_input); 536*4887Schin fcsopen(shlex.arg->argval); 537*4887Schin /* split ((...)) into three expressions */ 538*4887Schin for(n=0; ; n++) 539*4887Schin { 540*4887Schin register int c; 541*4887Schin argp = (struct argnod*)stakseek(ARGVAL); 542*4887Schin argp->argnxt.ap = 0; 543*4887Schin argp->argchn.cp = 0; 544*4887Schin argp->argflag = argflag; 545*4887Schin if(n==2) 546*4887Schin break; 547*4887Schin /* copy up to ; onto the stack */ 548*4887Schin sh_lexskip(';',1,ST_NESTED); 549*4887Schin offset = staktell()-1; 550*4887Schin if((c=fcpeek(-1))!=';') 551*4887Schin break; 552*4887Schin /* remove trailing white space */ 553*4887Schin while(offset>ARGVAL && ((c= *stakptr(offset-1)),isspace(c))) 554*4887Schin offset--; 555*4887Schin /* check for empty initialization expression */ 556*4887Schin if(offset==ARGVAL && n==0) 557*4887Schin continue; 558*4887Schin stakseek(offset); 559*4887Schin /* check for empty condition and treat as while((1)) */ 560*4887Schin if(offset==ARGVAL) 561*4887Schin stakputc('1'); 562*4887Schin argp = (struct argnod*)stakfreeze(1); 563*4887Schin t = getanode(argp); 564*4887Schin if(n==0) 565*4887Schin tf = makelist(TLST,t,tw); 566*4887Schin else 567*4887Schin tw->wh.whtre = t; 568*4887Schin } 569*4887Schin while((offset=fcpeek(0)) && isspace(offset)) 570*4887Schin fcseek(1); 571*4887Schin stakputs(fcseek(0)); 572*4887Schin argp = (struct argnod*)stakfreeze(1); 573*4887Schin fcrestore(&sav_input); 574*4887Schin if(n<2) 575*4887Schin { 576*4887Schin shlex.token = RPAREN|SYMREP; 577*4887Schin sh_syntax(); 578*4887Schin } 579*4887Schin /* check whether the increment is present */ 580*4887Schin if(*argp->argval) 581*4887Schin { 582*4887Schin t = getanode(argp); 583*4887Schin tw->wh.whinc = (struct arithnod*)t; 584*4887Schin } 585*4887Schin else 586*4887Schin tw->wh.whinc = 0; 587*4887Schin sh_lexopen((Lex_t*)sh.lex_context, &sh,1); 588*4887Schin if((n=sh_lex())==NL) 589*4887Schin n = skipnl(0); 590*4887Schin else if(n==';') 591*4887Schin n = sh_lex(); 592*4887Schin if(n!=DOSYM && n!=LBRACE) 593*4887Schin sh_syntax(); 594*4887Schin tw->wh.dotre = sh_cmd(n==DOSYM?DONESYM:RBRACE,SH_NL); 595*4887Schin tw->wh.whtyp = TWH; 596*4887Schin return(tf); 597*4887Schin 598*4887Schin } 599*4887Schin 600*4887Schin static Shnode_t *funct(void) 601*4887Schin { 602*4887Schin register Shnode_t *t; 603*4887Schin register int flag; 604*4887Schin struct slnod *volatile slp=0; 605*4887Schin Stak_t *savstak; 606*4887Schin Sfoff_t first, last; 607*4887Schin struct functnod *fp; 608*4887Schin Sfio_t *iop; 609*4887Schin #if SHOPT_KIA 610*4887Schin unsigned long current = shlex.current; 611*4887Schin #endif /* SHOPT_KIA */ 612*4887Schin int jmpval, saveloop=loop_level; 613*4887Schin struct argnod *savelabel = label_last; 614*4887Schin struct checkpt buff; 615*4887Schin t = getnode(functnod); 616*4887Schin t->funct.functline = sh.inlineno; 617*4887Schin t->funct.functtyp=TFUN; 618*4887Schin t->funct.functargs = 0; 619*4887Schin if(!(flag = (shlex.token==FUNCTSYM))) 620*4887Schin t->funct.functtyp |= FPOSIX; 621*4887Schin else if(sh_lex()) 622*4887Schin sh_syntax(); 623*4887Schin if(!(iop=fcfile())) 624*4887Schin { 625*4887Schin iop = sfopen(NIL(Sfio_t*),fcseek(0),"s"); 626*4887Schin fcclose(); 627*4887Schin fcfopen(iop); 628*4887Schin } 629*4887Schin t->funct.functloc = first = fctell(); 630*4887Schin if(!sh.st.filename || sffileno(iop)<0) 631*4887Schin { 632*4887Schin if(fcfill() >= 0) 633*4887Schin fcseek(-1); 634*4887Schin if(sh_isstate(SH_HISTORY)) 635*4887Schin t->funct.functloc = sfseek(sh.hist_ptr->histfp,(off_t)0,SEEK_CUR); 636*4887Schin else 637*4887Schin { 638*4887Schin /* copy source to temporary file */ 639*4887Schin t->funct.functloc = 0; 640*4887Schin if(shlex.sh->heredocs) 641*4887Schin t->funct.functloc = sfseek(shlex.sh->heredocs,(Sfoff_t)0, SEEK_END); 642*4887Schin else 643*4887Schin shlex.sh->heredocs = sftmp(HERE_MEM); 644*4887Schin shlex.sh->funlog = shlex.sh->heredocs; 645*4887Schin t->funct.functtyp |= FPIN; 646*4887Schin } 647*4887Schin } 648*4887Schin t->funct.functnam= (char*)shlex.arg->argval; 649*4887Schin #if SHOPT_KIA 650*4887Schin if(shlex.kiafile) 651*4887Schin shlex.current = kiaentity(t->funct.functnam,-1,'p',-1,-1,shlex.script,'p',0,""); 652*4887Schin #endif /* SHOPT_KIA */ 653*4887Schin if(flag) 654*4887Schin { 655*4887Schin shlex.token = sh_lex(); 656*4887Schin #if SHOPT_BASH 657*4887Schin if(shlex.token == LPAREN) 658*4887Schin { 659*4887Schin if((shlex.token = sh_lex()) == RPAREN) 660*4887Schin t->funct.functtyp |= FPOSIX; 661*4887Schin else 662*4887Schin sh_syntax(); 663*4887Schin } 664*4887Schin #endif 665*4887Schin } 666*4887Schin if(t->funct.functtyp&FPOSIX) 667*4887Schin skipnl(0); 668*4887Schin else 669*4887Schin { 670*4887Schin if(shlex.token==0) 671*4887Schin t->funct.functargs = (struct comnod*)simple(SH_NOIO|SH_FUNDEF,NIL(struct ionod*)); 672*4887Schin while(shlex.token==NL) 673*4887Schin shlex.token = sh_lex(); 674*4887Schin } 675*4887Schin if((flag && shlex.token!=LBRACE) || shlex.token==EOFSYM) 676*4887Schin sh_syntax(); 677*4887Schin sh_pushcontext(&buff,1); 678*4887Schin jmpval = sigsetjmp(buff.buff,0); 679*4887Schin if(jmpval == 0) 680*4887Schin { 681*4887Schin /* create a new stak frame to compile the command */ 682*4887Schin savstak = stakcreate(STAK_SMALL); 683*4887Schin savstak = stakinstall(savstak, 0); 684*4887Schin slp = (struct slnod*)stakalloc(sizeof(struct slnod)+sizeof(struct functnod)); 685*4887Schin slp->slchild = 0; 686*4887Schin slp->slnext = sh.st.staklist; 687*4887Schin sh.st.staklist = 0; 688*4887Schin t->funct.functstak = (struct slnod*)slp; 689*4887Schin /* 690*4887Schin * store the pathname of function definition file on stack 691*4887Schin * in name field of fake for node 692*4887Schin */ 693*4887Schin fp = (struct functnod*)(slp+1); 694*4887Schin fp->functtyp = TFUN|FAMP; 695*4887Schin fp->functnam = 0; 696*4887Schin fp->functline = t->funct.functline; 697*4887Schin if(sh.st.filename) 698*4887Schin fp->functnam = stakcopy(sh.st.filename); 699*4887Schin loop_level = 0; 700*4887Schin label_last = label_list; 701*4887Schin if(!flag && shlex.token==0) 702*4887Schin { 703*4887Schin /* copy current word token to current stak frame */ 704*4887Schin struct argnod *ap; 705*4887Schin flag = ARGVAL + strlen(shlex.arg->argval); 706*4887Schin ap = (struct argnod*)stakalloc(flag); 707*4887Schin memcpy(ap,shlex.arg,flag); 708*4887Schin shlex.arg = ap; 709*4887Schin } 710*4887Schin t->funct.functtre = item(SH_NOIO); 711*4887Schin } 712*4887Schin sh_popcontext(&buff); 713*4887Schin loop_level = saveloop; 714*4887Schin label_last = savelabel; 715*4887Schin /* restore the old stack */ 716*4887Schin if(slp) 717*4887Schin { 718*4887Schin slp->slptr = stakinstall(savstak,0); 719*4887Schin slp->slchild = sh.st.staklist; 720*4887Schin } 721*4887Schin #if SHOPT_KIA 722*4887Schin shlex.current = current; 723*4887Schin #endif /* SHOPT_KIA */ 724*4887Schin if(jmpval) 725*4887Schin { 726*4887Schin if(slp && slp->slptr) 727*4887Schin { 728*4887Schin sh.st.staklist = slp->slnext; 729*4887Schin stakdelete(slp->slptr); 730*4887Schin } 731*4887Schin siglongjmp(*sh.jmplist,jmpval); 732*4887Schin } 733*4887Schin sh.st.staklist = (struct slnod*)slp; 734*4887Schin last = fctell(); 735*4887Schin fp->functline = (last-first); 736*4887Schin fp->functtre = t; 737*4887Schin if(shlex.sh->funlog) 738*4887Schin { 739*4887Schin if(fcfill()>0) 740*4887Schin fcseek(-1); 741*4887Schin shlex.sh->funlog = 0; 742*4887Schin } 743*4887Schin #if SHOPT_KIA 744*4887Schin if(shlex.kiafile) 745*4887Schin kiaentity(t->funct.functnam,-1,'p',t->funct.functline,sh.inlineno-1,shlex.current,'p',0,""); 746*4887Schin #endif /* SHOPT_KIA */ 747*4887Schin return(t); 748*4887Schin } 749*4887Schin 750*4887Schin /* 751*4887Schin * Compound assignment 752*4887Schin */ 753*4887Schin static struct argnod *assign(register struct argnod *ap) 754*4887Schin { 755*4887Schin register int n; 756*4887Schin register Shnode_t *t, **tp; 757*4887Schin register struct comnod *ac; 758*4887Schin int array=0; 759*4887Schin Namval_t *np; 760*4887Schin n = strlen(ap->argval)-1; 761*4887Schin if(ap->argval[n]!='=') 762*4887Schin sh_syntax(); 763*4887Schin if(ap->argval[n-1]=='+') 764*4887Schin { 765*4887Schin ap->argval[n--]=0; 766*4887Schin array = ARG_APPEND; 767*4887Schin } 768*4887Schin /* shift right */ 769*4887Schin while(n > 0) 770*4887Schin { 771*4887Schin ap->argval[n] = ap->argval[n-1]; 772*4887Schin n--; 773*4887Schin } 774*4887Schin *ap->argval=0; 775*4887Schin t = getnode(fornod); 776*4887Schin t->for_.fornam = (char*)(ap->argval+1); 777*4887Schin t->for_.fortyp = sh_getlineno(); 778*4887Schin tp = &t->for_.fortre; 779*4887Schin ap->argchn.ap = (struct argnod*)t; 780*4887Schin ap->argflag &= ARG_QUOTED; 781*4887Schin ap->argflag |= array; 782*4887Schin shlex.assignok = SH_ASSIGN; 783*4887Schin array=0; 784*4887Schin if((n=skipnl(0))==RPAREN || n==LPAREN) 785*4887Schin { 786*4887Schin int index= 0; 787*4887Schin struct argnod **settail; 788*4887Schin ac = (struct comnod*)getnode(comnod); 789*4887Schin settail= &ac->comset; 790*4887Schin memset((void*)ac,0,sizeof(*ac)); 791*4887Schin ac->comline = sh_getlineno(); 792*4887Schin while(n==LPAREN) 793*4887Schin { 794*4887Schin struct argnod *ap; 795*4887Schin ap = (struct argnod*)stakseek(ARGVAL); 796*4887Schin ap->argflag= ARG_ASSIGN; 797*4887Schin sfprintf(stkstd,"[%d]=",index++); 798*4887Schin ap = (struct argnod*)stakfreeze(1); 799*4887Schin ap->argnxt.ap = 0; 800*4887Schin ap = assign(ap); 801*4887Schin ap->argflag |= ARG_MESSAGE; 802*4887Schin *settail = ap; 803*4887Schin settail = &(ap->argnxt.ap); 804*4887Schin n = skipnl(0); 805*4887Schin } 806*4887Schin } 807*4887Schin else if(n) 808*4887Schin sh_syntax(); 809*4887Schin else if(!(shlex.arg->argflag&ARG_ASSIGN) && !((np=nv_search(shlex.arg->argval,sh.fun_tree,0)) && nv_isattr(np,BLT_DCL))) 810*4887Schin array=SH_ARRAY; 811*4887Schin while(1) 812*4887Schin { 813*4887Schin if((n=shlex.token)==RPAREN) 814*4887Schin break; 815*4887Schin if(n==FUNCTSYM || n==SYMRES) 816*4887Schin ac = (struct comnod*)funct(); 817*4887Schin else 818*4887Schin ac = (struct comnod*)simple(SH_NOIO|SH_ASSIGN|array,NIL(struct ionod*)); 819*4887Schin if((n=shlex.token)==RPAREN) 820*4887Schin break; 821*4887Schin if(n!=NL && n!=';') 822*4887Schin sh_syntax(); 823*4887Schin shlex.assignok = SH_ASSIGN; 824*4887Schin if((n=skipnl(0)) || array) 825*4887Schin { 826*4887Schin if(n==RPAREN) 827*4887Schin break; 828*4887Schin if(array || n!=FUNCTSYM) 829*4887Schin sh_syntax(); 830*4887Schin } 831*4887Schin if((n!=FUNCTSYM) && !(shlex.arg->argflag&ARG_ASSIGN) && !((np=nv_search(shlex.arg->argval,sh.fun_tree,0)) && nv_isattr(np,BLT_DCL))) 832*4887Schin { 833*4887Schin struct argnod *arg = shlex.arg; 834*4887Schin if(n!=0) 835*4887Schin sh_syntax(); 836*4887Schin /* check for sys5 style function */ 837*4887Schin if(sh_lex()!=LPAREN || sh_lex()!=RPAREN) 838*4887Schin { 839*4887Schin shlex.arg = arg; 840*4887Schin shlex.token = 0; 841*4887Schin sh_syntax(); 842*4887Schin } 843*4887Schin shlex.arg = arg; 844*4887Schin shlex.token = SYMRES; 845*4887Schin } 846*4887Schin t = makelist(TLST,(Shnode_t*)ac,t); 847*4887Schin *tp = t; 848*4887Schin tp = &t->lst.lstrit; 849*4887Schin } 850*4887Schin *tp = (Shnode_t*)ac; 851*4887Schin shlex.assignok = 0; 852*4887Schin return(ap); 853*4887Schin } 854*4887Schin 855*4887Schin /* 856*4887Schin * item 857*4887Schin * 858*4887Schin * ( cmd ) [ < in ] [ > out ] 859*4887Schin * word word* [ < in ] [ > out ] 860*4887Schin * if ... then ... else ... fi 861*4887Schin * for ... while ... do ... done 862*4887Schin * case ... in ... esac 863*4887Schin * begin ... end 864*4887Schin */ 865*4887Schin 866*4887Schin static Shnode_t *item(int flag) 867*4887Schin { 868*4887Schin register Shnode_t *t; 869*4887Schin register struct ionod *io; 870*4887Schin register int tok = (shlex.token&0xff); 871*4887Schin int savwdval = shlex.lasttok; 872*4887Schin int savline = shlex.lastline; 873*4887Schin int showme=0; 874*4887Schin if(!(flag&SH_NOIO) && (tok=='<' || tok=='>')) 875*4887Schin io=inout(NIL(struct ionod*),1); 876*4887Schin else 877*4887Schin io=0; 878*4887Schin if((tok=shlex.token) && tok!=EOFSYM && tok!=FUNCTSYM) 879*4887Schin { 880*4887Schin shlex.lastline = sh_getlineno(); 881*4887Schin shlex.lasttok = shlex.token; 882*4887Schin } 883*4887Schin switch(tok) 884*4887Schin { 885*4887Schin /* [[ ... ]] test expression */ 886*4887Schin case BTESTSYM: 887*4887Schin t = test_expr(ETESTSYM); 888*4887Schin t->tre.tretyp &= ~TTEST; 889*4887Schin break; 890*4887Schin /* ((...)) arithmetic expression */ 891*4887Schin case EXPRSYM: 892*4887Schin t = getanode(shlex.arg); 893*4887Schin sh_lex(); 894*4887Schin goto done; 895*4887Schin 896*4887Schin /* case statement */ 897*4887Schin case CASESYM: 898*4887Schin { 899*4887Schin int savetok = shlex.lasttok; 900*4887Schin int saveline = shlex.lastline; 901*4887Schin t = getnode(swnod); 902*4887Schin if(sh_lex()) 903*4887Schin sh_syntax(); 904*4887Schin t->sw.swarg=shlex.arg; 905*4887Schin t->sw.swtyp=TSW; 906*4887Schin t->sw.swio = 0; 907*4887Schin t->sw.swtyp |= FLINENO; 908*4887Schin t->sw.swline = sh.inlineno; 909*4887Schin if((tok=skipnl(0))!=INSYM && tok!=LBRACE) 910*4887Schin sh_syntax(); 911*4887Schin if(!(t->sw.swlst=syncase(tok==INSYM?ESACSYM:RBRACE)) && shlex.token==EOFSYM) 912*4887Schin { 913*4887Schin shlex.lasttok = savetok; 914*4887Schin shlex.lastline = saveline; 915*4887Schin sh_syntax(); 916*4887Schin } 917*4887Schin break; 918*4887Schin } 919*4887Schin 920*4887Schin /* if statement */ 921*4887Schin case IFSYM: 922*4887Schin { 923*4887Schin register Shnode_t *tt; 924*4887Schin t = getnode(ifnod); 925*4887Schin t->if_.iftyp=TIF; 926*4887Schin t->if_.iftre=sh_cmd(THENSYM,SH_NL); 927*4887Schin t->if_.thtre=sh_cmd(ELSESYM,SH_NL|SH_SEMI); 928*4887Schin tok = shlex.token; 929*4887Schin t->if_.eltre=(tok==ELSESYM?sh_cmd(FISYM,SH_NL|SH_SEMI): 930*4887Schin (tok==ELIFSYM?(shlex.token=IFSYM, tt=item(SH_NOIO)):0)); 931*4887Schin if(tok==ELIFSYM) 932*4887Schin { 933*4887Schin if(!tt || tt->tre.tretyp!=TSETIO) 934*4887Schin goto done; 935*4887Schin t->if_.eltre = tt->fork.forktre; 936*4887Schin tt->fork.forktre = t; 937*4887Schin t = tt; 938*4887Schin goto done; 939*4887Schin } 940*4887Schin break; 941*4887Schin } 942*4887Schin 943*4887Schin /* for and select statement */ 944*4887Schin case FORSYM: 945*4887Schin case SELECTSYM: 946*4887Schin { 947*4887Schin t = getnode(fornod); 948*4887Schin t->for_.fortyp=(shlex.token==FORSYM?TFOR:TSELECT); 949*4887Schin t->for_.forlst=0; 950*4887Schin t->for_.forline = sh.inlineno; 951*4887Schin if(sh_lex()) 952*4887Schin { 953*4887Schin if(shlex.token!=EXPRSYM || t->for_.fortyp!=TFOR) 954*4887Schin sh_syntax(); 955*4887Schin /* arithmetic for */ 956*4887Schin t = arithfor(t); 957*4887Schin break; 958*4887Schin } 959*4887Schin t->for_.fornam=(char*) shlex.arg->argval; 960*4887Schin t->for_.fortyp |= FLINENO; 961*4887Schin #if SHOPT_KIA 962*4887Schin if(shlex.kiafile) 963*4887Schin writedefs(shlex.arg,sh.inlineno,'v',NIL(struct argnod*)); 964*4887Schin #endif /* SHOPT_KIA */ 965*4887Schin while((tok=sh_lex())==NL); 966*4887Schin if(tok==INSYM) 967*4887Schin { 968*4887Schin if(sh_lex()) 969*4887Schin { 970*4887Schin if(shlex.token != NL && shlex.token !=';') 971*4887Schin sh_syntax(); 972*4887Schin /* some Linux scripts assume this */ 973*4887Schin if(sh_isoption(SH_NOEXEC)) 974*4887Schin errormsg(SH_DICT,ERROR_warn(0),e_lexemptyfor,sh.inlineno-(shlex.token=='\n')); 975*4887Schin t->for_.forlst = (struct comnod*)getnode(comnod); 976*4887Schin (t->for_.forlst)->comarg = 0; 977*4887Schin (t->for_.forlst)->comset = 0; 978*4887Schin (t->for_.forlst)->comnamp = 0; 979*4887Schin (t->for_.forlst)->comnamq = 0; 980*4887Schin (t->for_.forlst)->comstate = 0; 981*4887Schin (t->for_.forlst)->comio = 0; 982*4887Schin (t->for_.forlst)->comtyp = 0; 983*4887Schin } 984*4887Schin else 985*4887Schin t->for_.forlst=(struct comnod*)simple(SH_NOIO,NIL(struct ionod*)); 986*4887Schin if(shlex.token != NL && shlex.token !=';') 987*4887Schin sh_syntax(); 988*4887Schin tok = skipnl(0); 989*4887Schin } 990*4887Schin /* 'for i;do cmd' is valid syntax */ 991*4887Schin else if(tok==';') 992*4887Schin tok=sh_lex(); 993*4887Schin if(tok!=DOSYM && tok!=LBRACE) 994*4887Schin sh_syntax(); 995*4887Schin loop_level++; 996*4887Schin t->for_.fortre=sh_cmd(tok==DOSYM?DONESYM:RBRACE,SH_NL|SH_SEMI); 997*4887Schin if(--loop_level==0) 998*4887Schin label_last = label_list; 999*4887Schin break; 1000*4887Schin } 1001*4887Schin 1002*4887Schin /* This is the code for parsing function definitions */ 1003*4887Schin case FUNCTSYM: 1004*4887Schin return(funct()); 1005*4887Schin 1006*4887Schin #if SHOPT_NAMESPACE 1007*4887Schin case NSPACESYM: 1008*4887Schin t = getnode(fornod); 1009*4887Schin t->for_.fortyp=TNSPACE; 1010*4887Schin t->for_.forlst=0; 1011*4887Schin if(sh_lex()) 1012*4887Schin sh_syntax(); 1013*4887Schin t->for_.fornam=(char*) shlex.arg->argval; 1014*4887Schin while((tok=sh_lex())==NL); 1015*4887Schin if(tok!=LBRACE) 1016*4887Schin sh_syntax(); 1017*4887Schin t->for_.fortre = sh_cmd(RBRACE,SH_NL); 1018*4887Schin break; 1019*4887Schin #endif /* SHOPT_NAMESPACE */ 1020*4887Schin 1021*4887Schin /* while and until */ 1022*4887Schin case WHILESYM: 1023*4887Schin case UNTILSYM: 1024*4887Schin t = getnode(whnod); 1025*4887Schin t->wh.whtyp=(shlex.token==WHILESYM ? TWH : TUN); 1026*4887Schin loop_level++; 1027*4887Schin t->wh.whtre = sh_cmd(DOSYM,SH_NL); 1028*4887Schin t->wh.dotre = sh_cmd(DONESYM,SH_NL|SH_SEMI); 1029*4887Schin if(--loop_level==0) 1030*4887Schin label_last = label_list; 1031*4887Schin t->wh.whinc = 0; 1032*4887Schin break; 1033*4887Schin 1034*4887Schin case LABLSYM: 1035*4887Schin { 1036*4887Schin register struct argnod *argp = label_list; 1037*4887Schin while(argp) 1038*4887Schin { 1039*4887Schin if(strcmp(argp->argval,shlex.arg->argval)==0) 1040*4887Schin errormsg(SH_DICT,ERROR_exit(3),e_lexsyntax3,sh.inlineno,argp->argval); 1041*4887Schin argp = argp->argnxt.ap; 1042*4887Schin } 1043*4887Schin shlex.arg->argnxt.ap = label_list; 1044*4887Schin label_list = shlex.arg; 1045*4887Schin label_list->argchn.len = sh_getlineno(); 1046*4887Schin label_list->argflag = loop_level; 1047*4887Schin skipnl(flag); 1048*4887Schin if(!(t = item(SH_NL))) 1049*4887Schin sh_syntax(); 1050*4887Schin tok = (t->tre.tretyp&(COMSCAN|COMSCAN-1)); 1051*4887Schin if(sh_isoption(SH_NOEXEC) && tok!=TWH && tok!=TUN && tok!=TFOR && tok!=TSELECT) 1052*4887Schin errormsg(SH_DICT,ERROR_warn(0),e_lexlabignore,label_list->argchn.len,label_list->argval); 1053*4887Schin return(t); 1054*4887Schin } 1055*4887Schin 1056*4887Schin /* command group with {...} */ 1057*4887Schin case LBRACE: 1058*4887Schin t = sh_cmd(RBRACE,SH_NL); 1059*4887Schin break; 1060*4887Schin 1061*4887Schin case LPAREN: 1062*4887Schin t = getnode(parnod); 1063*4887Schin t->par.partre=sh_cmd(RPAREN,SH_NL); 1064*4887Schin t->par.partyp=TPAR; 1065*4887Schin break; 1066*4887Schin 1067*4887Schin default: 1068*4887Schin if(io==0) 1069*4887Schin return(0); 1070*4887Schin 1071*4887Schin case ';': 1072*4887Schin if(io==0) 1073*4887Schin { 1074*4887Schin if(!(flag&SH_SEMI)) 1075*4887Schin return(0); 1076*4887Schin if(sh_lex()==';') 1077*4887Schin sh_syntax(); 1078*4887Schin showme = FSHOWME; 1079*4887Schin } 1080*4887Schin /* simple command */ 1081*4887Schin case 0: 1082*4887Schin t = (Shnode_t*)simple(flag,io); 1083*4887Schin t->tre.tretyp |= showme; 1084*4887Schin return(t); 1085*4887Schin } 1086*4887Schin sh_lex(); 1087*4887Schin if(io=inout(io,0)) 1088*4887Schin { 1089*4887Schin if((tok=t->tre.tretyp&COMMSK) != TFORK) 1090*4887Schin tok = TSETIO; 1091*4887Schin t=makeparent(tok,t); 1092*4887Schin t->tre.treio=io; 1093*4887Schin } 1094*4887Schin done: 1095*4887Schin shlex.lasttok = savwdval; 1096*4887Schin shlex.lastline = savline; 1097*4887Schin return(t); 1098*4887Schin } 1099*4887Schin 1100*4887Schin /* 1101*4887Schin * This is for a simple command, for list, or compound assignment 1102*4887Schin */ 1103*4887Schin static Shnode_t *simple(int flag, struct ionod *io) 1104*4887Schin { 1105*4887Schin register struct comnod *t; 1106*4887Schin register struct argnod *argp; 1107*4887Schin register int tok; 1108*4887Schin struct argnod **argtail; 1109*4887Schin struct argnod **settail; 1110*4887Schin int argno = 0; 1111*4887Schin int assignment = 0; 1112*4887Schin int key_on = (!(flag&SH_NOIO) && sh_isoption(SH_KEYWORD)); 1113*4887Schin int associative=0; 1114*4887Schin if((argp=shlex.arg) && (argp->argflag&ARG_ASSIGN) && argp->argval[0]=='[') 1115*4887Schin { 1116*4887Schin flag |= SH_ARRAY; 1117*4887Schin associative = 1; 1118*4887Schin } 1119*4887Schin t = (struct comnod*)getnode(comnod); 1120*4887Schin t->comio=io; /*initial io chain*/ 1121*4887Schin /* set command line number for error messages */ 1122*4887Schin t->comline = sh_getlineno(); 1123*4887Schin argtail = &(t->comarg); 1124*4887Schin t->comset = 0; 1125*4887Schin t->comnamp = 0; 1126*4887Schin t->comnamq = 0; 1127*4887Schin t->comstate = 0; 1128*4887Schin settail = &(t->comset); 1129*4887Schin while(shlex.token==0) 1130*4887Schin { 1131*4887Schin argp = shlex.arg; 1132*4887Schin if(*argp->argval==LBRACE && (flag&SH_FUNDEF) && argp->argval[1]==0) 1133*4887Schin { 1134*4887Schin shlex.token = LBRACE; 1135*4887Schin break; 1136*4887Schin } 1137*4887Schin if(associative && argp->argval[0]!='[') 1138*4887Schin sh_syntax(); 1139*4887Schin /* check for assignment argument */ 1140*4887Schin if((argp->argflag&ARG_ASSIGN) && assignment!=2) 1141*4887Schin { 1142*4887Schin *settail = argp; 1143*4887Schin settail = &(argp->argnxt.ap); 1144*4887Schin shlex.assignok = (flag&SH_ASSIGN)?SH_ASSIGN:1; 1145*4887Schin if(assignment) 1146*4887Schin { 1147*4887Schin struct argnod *ap=argp; 1148*4887Schin char *last, *cp; 1149*4887Schin if(assignment==1) 1150*4887Schin { 1151*4887Schin last = strchr(argp->argval,'='); 1152*4887Schin if((cp=strchr(argp->argval,'[')) && (cp < last)) 1153*4887Schin last = cp; 1154*4887Schin stakseek(ARGVAL); 1155*4887Schin stakwrite(argp->argval,last-argp->argval); 1156*4887Schin ap=(struct argnod*)stakfreeze(1); 1157*4887Schin ap->argflag = ARG_RAW; 1158*4887Schin ap->argchn.ap = 0; 1159*4887Schin } 1160*4887Schin *argtail = ap; 1161*4887Schin argtail = &(ap->argnxt.ap); 1162*4887Schin if(argno>=0) 1163*4887Schin argno++; 1164*4887Schin } 1165*4887Schin else /* alias substitutions allowed */ 1166*4887Schin shlex.aliasok = 1; 1167*4887Schin } 1168*4887Schin else 1169*4887Schin { 1170*4887Schin if(!(argp->argflag&ARG_RAW)) 1171*4887Schin argno = -1; 1172*4887Schin if(argno>=0 && argno++==0 && !(flag&SH_ARRAY) && *argp->argval!='/') 1173*4887Schin { 1174*4887Schin /* check for builtin command */ 1175*4887Schin Namval_t *np=nv_bfsearch(argp->argval,sh.fun_tree, (Namval_t**)&t->comnamq,(char**)0); 1176*4887Schin if((t->comnamp=(void*)np) && is_abuiltin(np) && 1177*4887Schin nv_isattr(np,BLT_DCL)) 1178*4887Schin { 1179*4887Schin assignment = 1+(*argp->argval=='a'); 1180*4887Schin key_on = 1; 1181*4887Schin } 1182*4887Schin } 1183*4887Schin *argtail = argp; 1184*4887Schin argtail = &(argp->argnxt.ap); 1185*4887Schin if(!(shlex.assignok=key_on) && !(flag&SH_NOIO)) 1186*4887Schin shlex.assignok = SH_COMPASSIGN; 1187*4887Schin shlex.aliasok = 0; 1188*4887Schin } 1189*4887Schin retry: 1190*4887Schin tok = sh_lex(); 1191*4887Schin #if SHOPT_DEVFD 1192*4887Schin if((tok==IPROCSYM || tok==OPROCSYM)) 1193*4887Schin { 1194*4887Schin Shnode_t *t; 1195*4887Schin int mode = (tok==OPROCSYM); 1196*4887Schin t = sh_cmd(RPAREN,SH_NL); 1197*4887Schin argp = (struct argnod*)stakalloc(sizeof(struct argnod)); 1198*4887Schin *argp->argval = 0; 1199*4887Schin argno = -1; 1200*4887Schin *argtail = argp; 1201*4887Schin argtail = &(argp->argnxt.ap); 1202*4887Schin argp->argchn.ap = (struct argnod*)makeparent(mode?TFORK|FPIN|FAMP|FPCL:TFORK|FPOU,t); 1203*4887Schin argp->argflag = (ARG_EXP|mode); 1204*4887Schin goto retry; 1205*4887Schin } 1206*4887Schin #endif /* SHOPT_DEVFD */ 1207*4887Schin if(tok==LPAREN) 1208*4887Schin { 1209*4887Schin if(argp->argflag&ARG_ASSIGN) 1210*4887Schin { 1211*4887Schin argp = assign(argp); 1212*4887Schin if(associative) 1213*4887Schin shlex.assignok |= SH_ASSIGN; 1214*4887Schin goto retry; 1215*4887Schin } 1216*4887Schin else if(argno==1 && !t->comset) 1217*4887Schin { 1218*4887Schin /* SVR2 style function */ 1219*4887Schin if(sh_lex() == RPAREN) 1220*4887Schin { 1221*4887Schin shlex.arg = argp; 1222*4887Schin return(funct()); 1223*4887Schin } 1224*4887Schin shlex.token = LPAREN; 1225*4887Schin } 1226*4887Schin } 1227*4887Schin else if(flag&SH_ASSIGN) 1228*4887Schin { 1229*4887Schin if(tok==RPAREN) 1230*4887Schin break; 1231*4887Schin else if(tok==NL && (flag&SH_ARRAY)) 1232*4887Schin goto retry; 1233*4887Schin } 1234*4887Schin if(!(flag&SH_NOIO)) 1235*4887Schin { 1236*4887Schin if(io) 1237*4887Schin { 1238*4887Schin while(io->ionxt) 1239*4887Schin io = io->ionxt; 1240*4887Schin io->ionxt = inout((struct ionod*)0,0); 1241*4887Schin } 1242*4887Schin else 1243*4887Schin t->comio = io = inout((struct ionod*)0,0); 1244*4887Schin } 1245*4887Schin } 1246*4887Schin *argtail = 0; 1247*4887Schin t->comtyp = TCOM; 1248*4887Schin #if SHOPT_KIA 1249*4887Schin if(shlex.kiafile && !(flag&SH_NOIO)) 1250*4887Schin { 1251*4887Schin register Namval_t *np=(Namval_t*)t->comnamp; 1252*4887Schin unsigned long r=0; 1253*4887Schin int line = t->comline; 1254*4887Schin argp = t->comarg; 1255*4887Schin if(np) 1256*4887Schin r = kiaentity(nv_name(np),-1,'p',-1,0,shlex.unknown,'b',0,""); 1257*4887Schin else if(argp) 1258*4887Schin r = kiaentity(sh_argstr(argp),-1,'p',-1,0,shlex.unknown,'c',0,""); 1259*4887Schin if(r>0) 1260*4887Schin sfprintf(shlex.kiatmp,"p;%..64d;p;%..64d;%d;%d;c;\n",shlex.current,r,line,line); 1261*4887Schin if(t->comset && argno==0) 1262*4887Schin writedefs(t->comset,line,'v',t->comarg); 1263*4887Schin else if(np && nv_isattr(np,BLT_DCL)) 1264*4887Schin writedefs(argp,line,0,NIL(struct argnod*)); 1265*4887Schin else if(argp && strcmp(argp->argval,"read")==0) 1266*4887Schin writedefs(argp,line,0,NIL(struct argnod*)); 1267*4887Schin #if 0 1268*4887Schin else if(argp && strcmp(argp->argval,"unset")==0) 1269*4887Schin writedefs(argp,line,'u',NIL(struct argnod*)); 1270*4887Schin #endif 1271*4887Schin else if(argp && *argp->argval=='.' && argp->argval[1]==0 && (argp=argp->argnxt.ap)) 1272*4887Schin { 1273*4887Schin r = kiaentity(sh_argstr(argp),-1,'p',0,0,shlex.script,'d',0,""); 1274*4887Schin sfprintf(shlex.kiatmp,"p;%..64d;p;%..64d;%d;%d;d;\n",shlex.current,r,line,line); 1275*4887Schin } 1276*4887Schin } 1277*4887Schin #endif /* SHOPT_KIA */ 1278*4887Schin if(t->comnamp && (argp=t->comarg->argnxt.ap)) 1279*4887Schin { 1280*4887Schin Namval_t *np=(Namval_t*)t->comnamp; 1281*4887Schin if((np==SYSBREAK || np==SYSCONT) && (argp->argflag&ARG_RAW) && !isdigit(*argp->argval)) 1282*4887Schin { 1283*4887Schin register char *cp = argp->argval; 1284*4887Schin /* convert break/continue labels to numbers */ 1285*4887Schin tok = 0; 1286*4887Schin for(argp=label_list;argp!=label_last;argp=argp->argnxt.ap) 1287*4887Schin { 1288*4887Schin if(strcmp(cp,argp->argval)) 1289*4887Schin continue; 1290*4887Schin tok = loop_level-argp->argflag; 1291*4887Schin if(tok>=1) 1292*4887Schin { 1293*4887Schin argp = t->comarg->argnxt.ap; 1294*4887Schin if(tok>9) 1295*4887Schin { 1296*4887Schin argp->argval[1] = '0'+tok%10; 1297*4887Schin argp->argval[2] = 0; 1298*4887Schin tok /= 10; 1299*4887Schin } 1300*4887Schin else 1301*4887Schin argp->argval[1] = 0; 1302*4887Schin *argp->argval = '0'+tok; 1303*4887Schin } 1304*4887Schin break; 1305*4887Schin } 1306*4887Schin if(sh_isoption(SH_NOEXEC) && tok==0) 1307*4887Schin errormsg(SH_DICT,ERROR_warn(0),e_lexlabunknown,sh.inlineno-(shlex.token=='\n'),cp); 1308*4887Schin } 1309*4887Schin else if(sh_isoption(SH_NOEXEC) && np==SYSSET && ((tok= *argp->argval)=='-'||tok=='+') && 1310*4887Schin (argp->argval[1]==0||strchr(argp->argval,'k'))) 1311*4887Schin errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete5,sh.inlineno-(shlex.token=='\n'),argp->argval); 1312*4887Schin } 1313*4887Schin /* expand argument list if possible */ 1314*4887Schin if(argno>0) 1315*4887Schin t->comarg = qscan(t,argno); 1316*4887Schin else if(t->comarg) 1317*4887Schin t->comtyp |= COMSCAN; 1318*4887Schin shlex.aliasok = 0; 1319*4887Schin return((Shnode_t*)t); 1320*4887Schin } 1321*4887Schin 1322*4887Schin /* 1323*4887Schin * skip past newlines but issue prompt if interactive 1324*4887Schin */ 1325*4887Schin static int skipnl(int flag) 1326*4887Schin { 1327*4887Schin register int token; 1328*4887Schin while((token=sh_lex())==NL); 1329*4887Schin if(token==';' && !(flag&SH_SEMI)) 1330*4887Schin sh_syntax(); 1331*4887Schin return(token); 1332*4887Schin } 1333*4887Schin 1334*4887Schin /* 1335*4887Schin * check for and process and i/o redirections 1336*4887Schin * if flag>0 then an alias can be in the next word 1337*4887Schin * if flag<0 only one redirection will be processed 1338*4887Schin */ 1339*4887Schin static struct ionod *inout(struct ionod *lastio,int flag) 1340*4887Schin { 1341*4887Schin register int iof = shlex.digits, token=shlex.token; 1342*4887Schin register struct ionod *iop; 1343*4887Schin char *iovname=0; 1344*4887Schin #if SHOPT_BASH 1345*4887Schin register int errout=0; 1346*4887Schin #endif 1347*4887Schin if(token==IOVNAME) 1348*4887Schin { 1349*4887Schin iovname=shlex.arg->argval+1; 1350*4887Schin token= sh_lex(); 1351*4887Schin iof = 0; 1352*4887Schin } 1353*4887Schin switch(token&0xff) 1354*4887Schin { 1355*4887Schin case '<': 1356*4887Schin if(token==IODOCSYM) 1357*4887Schin iof |= (IODOC|IORAW); 1358*4887Schin else if(token==IOMOV0SYM) 1359*4887Schin iof |= IOMOV; 1360*4887Schin else if(token==IORDWRSYM) 1361*4887Schin iof |= IORDW; 1362*4887Schin else if((token&SYMSHARP) == SYMSHARP) 1363*4887Schin { 1364*4887Schin int n; 1365*4887Schin iof |= IOLSEEK; 1366*4887Schin if(fcgetc(n)=='#') 1367*4887Schin iof |= IOCOPY; 1368*4887Schin else if(n>0) 1369*4887Schin fcseek(-1); 1370*4887Schin } 1371*4887Schin break; 1372*4887Schin 1373*4887Schin case '>': 1374*4887Schin #if SHOPT_BASH 1375*4887Schin if(iof<0) 1376*4887Schin { 1377*4887Schin errout = 1; 1378*4887Schin iof = 1; 1379*4887Schin } 1380*4887Schin #endif 1381*4887Schin iof |= IOPUT; 1382*4887Schin if(token==IOAPPSYM) 1383*4887Schin iof |= IOAPP; 1384*4887Schin else if(token==IOMOV1SYM) 1385*4887Schin iof |= IOMOV; 1386*4887Schin else if(token==IOCLOBSYM) 1387*4887Schin iof |= IOCLOB; 1388*4887Schin else if((token&SYMSHARP) == SYMSHARP) 1389*4887Schin iof |= IOLSEEK; 1390*4887Schin break; 1391*4887Schin 1392*4887Schin default: 1393*4887Schin return(lastio); 1394*4887Schin } 1395*4887Schin shlex.digits=0; 1396*4887Schin iop=(struct ionod*) stakalloc(sizeof(struct ionod)); 1397*4887Schin iop->iodelim = 0; 1398*4887Schin if(token=sh_lex()) 1399*4887Schin { 1400*4887Schin if(token==RPAREN && (iof&IOLSEEK) && shlex.comsub) 1401*4887Schin { 1402*4887Schin shlex.arg = (struct argnod*)stakalloc(sizeof(struct argnod)+3); 1403*4887Schin strcpy(shlex.arg->argval,"CUR"); 1404*4887Schin shlex.arg->argflag = ARG_RAW; 1405*4887Schin iof |= IOARITH; 1406*4887Schin fcseek(-1); 1407*4887Schin } 1408*4887Schin else if(token==EXPRSYM && (iof&IOLSEEK)) 1409*4887Schin iof |= IOARITH; 1410*4887Schin else 1411*4887Schin sh_syntax(); 1412*4887Schin } 1413*4887Schin iop->ioname=shlex.arg->argval; 1414*4887Schin iop->iovname = iovname; 1415*4887Schin if(iof&IODOC) 1416*4887Schin { 1417*4887Schin if(shlex.digits==2) 1418*4887Schin { 1419*4887Schin iof |= IOSTRG; 1420*4887Schin if(!(shlex.arg->argflag&ARG_RAW)) 1421*4887Schin iof &= ~IORAW; 1422*4887Schin } 1423*4887Schin else 1424*4887Schin { 1425*4887Schin if(!shlex.sh->heredocs) 1426*4887Schin shlex.sh->heredocs = sftmp(HERE_MEM); 1427*4887Schin iop->iolst=shlex.heredoc; 1428*4887Schin shlex.heredoc=iop; 1429*4887Schin if(shlex.arg->argflag&ARG_QUOTED) 1430*4887Schin iof |= IOQUOTE; 1431*4887Schin if(shlex.digits==3) 1432*4887Schin iof |= IOLSEEK; 1433*4887Schin if(shlex.digits) 1434*4887Schin iof |= IOSTRIP; 1435*4887Schin } 1436*4887Schin } 1437*4887Schin else 1438*4887Schin { 1439*4887Schin iop->iolst = 0; 1440*4887Schin if(shlex.arg->argflag&ARG_RAW) 1441*4887Schin iof |= IORAW; 1442*4887Schin } 1443*4887Schin iop->iofile=iof; 1444*4887Schin if(flag>0) 1445*4887Schin /* allow alias substitutions and parameter assignments */ 1446*4887Schin shlex.aliasok = shlex.assignok = 1; 1447*4887Schin #if SHOPT_KIA 1448*4887Schin if(shlex.kiafile) 1449*4887Schin { 1450*4887Schin int n = sh.inlineno-(shlex.token=='\n'); 1451*4887Schin if(!(iof&IOMOV)) 1452*4887Schin { 1453*4887Schin unsigned long r=kiaentity((iof&IORAW)?sh_fmtq(iop->ioname):iop->ioname,-1,'f',0,0,shlex.script,'f',0,""); 1454*4887Schin sfprintf(shlex.kiatmp,"p;%..64d;f;%..64d;%d;%d;%c;%d\n",shlex.current,r,n,n,(iof&IOPUT)?((iof&IOAPP)?'a':'w'):((iof&IODOC)?'h':'r'),iof&IOUFD); 1455*4887Schin } 1456*4887Schin } 1457*4887Schin #endif /* SHOPT_KIA */ 1458*4887Schin if(flag>=0) 1459*4887Schin { 1460*4887Schin struct ionod *ioq=iop; 1461*4887Schin sh_lex(); 1462*4887Schin #if SHOPT_BASH 1463*4887Schin if(errout) 1464*4887Schin { 1465*4887Schin /* redirect standard output to standard error */ 1466*4887Schin ioq = (struct ionod*)stakalloc(sizeof(struct ionod)); 1467*4887Schin ioq->ioname = "1"; 1468*4887Schin ioq->iolst = 0; 1469*4887Schin ioq->iodelim = 0; 1470*4887Schin ioq->iofile = IORAW|IOPUT|IOMOV|2; 1471*4887Schin iop->ionxt=ioq; 1472*4887Schin } 1473*4887Schin #endif 1474*4887Schin ioq->ionxt=inout(lastio,flag); 1475*4887Schin } 1476*4887Schin else 1477*4887Schin iop->ionxt=0; 1478*4887Schin return(iop); 1479*4887Schin } 1480*4887Schin 1481*4887Schin /* 1482*4887Schin * convert argument chain to argument list when no special arguments 1483*4887Schin */ 1484*4887Schin 1485*4887Schin static struct argnod *qscan(struct comnod *ac,int argn) 1486*4887Schin { 1487*4887Schin register char **cp; 1488*4887Schin register struct argnod *ap; 1489*4887Schin register struct dolnod* dp; 1490*4887Schin register int special=0; 1491*4887Schin /* special hack for test -t compatibility */ 1492*4887Schin if((Namval_t*)ac->comnamp==SYSTEST) 1493*4887Schin special = 2; 1494*4887Schin else if(*(ac->comarg->argval)=='[' && ac->comarg->argval[1]==0) 1495*4887Schin special = 3; 1496*4887Schin if(special) 1497*4887Schin { 1498*4887Schin ap = ac->comarg->argnxt.ap; 1499*4887Schin if(argn==(special+1) && ap->argval[1]==0 && *ap->argval=='!') 1500*4887Schin ap = ap->argnxt.ap; 1501*4887Schin else if(argn!=special) 1502*4887Schin special=0; 1503*4887Schin } 1504*4887Schin if(special) 1505*4887Schin { 1506*4887Schin const char *message; 1507*4887Schin if(strcmp(ap->argval,"-t")) 1508*4887Schin { 1509*4887Schin message = "line %d: Invariant test"; 1510*4887Schin special=0; 1511*4887Schin } 1512*4887Schin else 1513*4887Schin { 1514*4887Schin message = "line %d: -t requires argument"; 1515*4887Schin argn++; 1516*4887Schin } 1517*4887Schin if(sh_isoption(SH_NOEXEC)) 1518*4887Schin errormsg(SH_DICT,ERROR_warn(0),message,ac->comline); 1519*4887Schin } 1520*4887Schin /* leave space for an extra argument at the front */ 1521*4887Schin dp = (struct dolnod*)stakalloc((unsigned)sizeof(struct dolnod) + ARG_SPARE*sizeof(char*) + argn*sizeof(char*)); 1522*4887Schin cp = dp->dolval+ARG_SPARE; 1523*4887Schin dp->dolnum = argn; 1524*4887Schin dp->dolbot = ARG_SPARE; 1525*4887Schin ap = ac->comarg; 1526*4887Schin while(ap) 1527*4887Schin { 1528*4887Schin *cp++ = ap->argval; 1529*4887Schin ap = ap->argnxt.ap; 1530*4887Schin } 1531*4887Schin if(special==3) 1532*4887Schin { 1533*4887Schin cp[0] = cp[-1]; 1534*4887Schin cp[-1] = "1"; 1535*4887Schin cp++; 1536*4887Schin } 1537*4887Schin else if(special) 1538*4887Schin *cp++ = "1"; 1539*4887Schin *cp = 0; 1540*4887Schin return((struct argnod*)dp); 1541*4887Schin } 1542*4887Schin 1543*4887Schin static Shnode_t *test_expr(int sym) 1544*4887Schin { 1545*4887Schin register Shnode_t *t = test_or(); 1546*4887Schin if(shlex.token!=sym) 1547*4887Schin sh_syntax(); 1548*4887Schin return(t); 1549*4887Schin } 1550*4887Schin 1551*4887Schin static Shnode_t *test_or(void) 1552*4887Schin { 1553*4887Schin register Shnode_t *t = test_and(); 1554*4887Schin while(shlex.token==ORFSYM) 1555*4887Schin t = makelist(TORF|TTEST,t,test_and()); 1556*4887Schin return(t); 1557*4887Schin } 1558*4887Schin 1559*4887Schin static Shnode_t *test_and(void) 1560*4887Schin { 1561*4887Schin register Shnode_t *t = test_primary(); 1562*4887Schin while(shlex.token==ANDFSYM) 1563*4887Schin t = makelist(TAND|TTEST,t,test_primary()); 1564*4887Schin return(t); 1565*4887Schin } 1566*4887Schin 1567*4887Schin /* 1568*4887Schin * convert =~ into == ~(E) 1569*4887Schin */ 1570*4887Schin static void ere_match(void) 1571*4887Schin { 1572*4887Schin Sfio_t *base, *iop = sfopen((Sfio_t*)0," ~(E)","s"); 1573*4887Schin register int c; 1574*4887Schin while( fcgetc(c),(c==' ' || c=='\t')); 1575*4887Schin if(c) 1576*4887Schin fcseek(-1); 1577*4887Schin if(!(base=fcfile())) 1578*4887Schin base = sfopen(NIL(Sfio_t*),fcseek(0),"s"); 1579*4887Schin fcclose(); 1580*4887Schin sfstack(base,iop); 1581*4887Schin fcfopen(base); 1582*4887Schin } 1583*4887Schin 1584*4887Schin static Shnode_t *test_primary(void) 1585*4887Schin { 1586*4887Schin register struct argnod *arg; 1587*4887Schin register Shnode_t *t; 1588*4887Schin register int num,token; 1589*4887Schin token = skipnl(0); 1590*4887Schin num = shlex.digits; 1591*4887Schin switch(token) 1592*4887Schin { 1593*4887Schin case '(': 1594*4887Schin t = test_expr(')'); 1595*4887Schin t = makelist(TTST|TTEST|TPAREN ,t, (Shnode_t*)pointerof(sh.inlineno)); 1596*4887Schin break; 1597*4887Schin case '!': 1598*4887Schin if(!(t = test_primary())) 1599*4887Schin sh_syntax(); 1600*4887Schin t->tre.tretyp |= TNEGATE; 1601*4887Schin return(t); 1602*4887Schin case TESTUNOP: 1603*4887Schin if(sh_lex()) 1604*4887Schin sh_syntax(); 1605*4887Schin #if SHOPT_KIA 1606*4887Schin if(shlex.kiafile && !strchr("sntzoOG",num)) 1607*4887Schin { 1608*4887Schin int line = sh.inlineno- (shlex.token==NL); 1609*4887Schin unsigned long r; 1610*4887Schin r=kiaentity(sh_argstr(shlex.arg),-1,'f',0,0,shlex.script,'t',0,""); 1611*4887Schin sfprintf(shlex.kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",shlex.current,r,line,line); 1612*4887Schin } 1613*4887Schin #endif /* SHOPT_KIA */ 1614*4887Schin t = makelist(TTST|TTEST|TUNARY|(num<<TSHIFT), 1615*4887Schin (Shnode_t*)shlex.arg,(Shnode_t*)shlex.arg); 1616*4887Schin t->tst.tstline = sh.inlineno; 1617*4887Schin break; 1618*4887Schin /* binary test operators */ 1619*4887Schin case 0: 1620*4887Schin arg = shlex.arg; 1621*4887Schin if((token=sh_lex())==TESTBINOP) 1622*4887Schin { 1623*4887Schin num = shlex.digits; 1624*4887Schin if(num==TEST_REP) 1625*4887Schin { 1626*4887Schin ere_match(); 1627*4887Schin num = TEST_PEQ; 1628*4887Schin } 1629*4887Schin } 1630*4887Schin else if(token=='<') 1631*4887Schin num = TEST_SLT; 1632*4887Schin else if(token=='>') 1633*4887Schin num = TEST_SGT; 1634*4887Schin else if(token==ANDFSYM||token==ORFSYM||token==ETESTSYM||token==RPAREN) 1635*4887Schin { 1636*4887Schin t = makelist(TTST|TTEST|TUNARY|('n'<<TSHIFT), 1637*4887Schin (Shnode_t*)arg,(Shnode_t*)arg); 1638*4887Schin t->tst.tstline = sh.inlineno; 1639*4887Schin return(t); 1640*4887Schin } 1641*4887Schin else 1642*4887Schin sh_syntax(); 1643*4887Schin #if SHOPT_KIA 1644*4887Schin if(shlex.kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT)) 1645*4887Schin { 1646*4887Schin int line = sh.inlineno- (shlex.token==NL); 1647*4887Schin unsigned long r; 1648*4887Schin r=kiaentity(sh_argstr(shlex.arg),-1,'f',0,0,shlex.current,'t',0,""); 1649*4887Schin sfprintf(shlex.kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",shlex.current,r,line,line); 1650*4887Schin } 1651*4887Schin #endif /* SHOPT_KIA */ 1652*4887Schin if(sh_lex()) 1653*4887Schin sh_syntax(); 1654*4887Schin if(num&TEST_PATTERN) 1655*4887Schin { 1656*4887Schin if(shlex.arg->argflag&(ARG_EXP|ARG_MAC)) 1657*4887Schin num &= ~TEST_PATTERN; 1658*4887Schin } 1659*4887Schin t = getnode(tstnod); 1660*4887Schin t->lst.lsttyp = TTST|TTEST|TBINARY|(num<<TSHIFT); 1661*4887Schin t->lst.lstlef = (Shnode_t*)arg; 1662*4887Schin t->lst.lstrit = (Shnode_t*)shlex.arg; 1663*4887Schin t->tst.tstline = sh.inlineno; 1664*4887Schin #if SHOPT_KIA 1665*4887Schin if(shlex.kiafile && (num==TEST_EF||num==TEST_NT||num==TEST_OT)) 1666*4887Schin { 1667*4887Schin int line = sh.inlineno-(shlex.token==NL); 1668*4887Schin unsigned long r; 1669*4887Schin r=kiaentity(sh_argstr(shlex.arg),-1,'f',0,0,shlex.current,'t',0,""); 1670*4887Schin sfprintf(shlex.kiatmp,"p;%..64d;f;%..64d;%d;%d;t;\n",shlex.current,r,line,line); 1671*4887Schin } 1672*4887Schin #endif /* SHOPT_KIA */ 1673*4887Schin break; 1674*4887Schin default: 1675*4887Schin return(0); 1676*4887Schin } 1677*4887Schin skipnl(0); 1678*4887Schin return(t); 1679*4887Schin } 1680*4887Schin 1681*4887Schin #if SHOPT_KIA 1682*4887Schin /* 1683*4887Schin * return an entity checksum 1684*4887Schin * The entity is created if it doesn't exist 1685*4887Schin */ 1686*4887Schin unsigned long kiaentity(const char *name,int len,int type,int first,int last,unsigned long parent, int pkind, int width, const char *attr) 1687*4887Schin { 1688*4887Schin Namval_t *np; 1689*4887Schin long offset = staktell(); 1690*4887Schin stakputc(type); 1691*4887Schin if(len>0) 1692*4887Schin stakwrite(name,len); 1693*4887Schin else 1694*4887Schin { 1695*4887Schin if(type=='p') 1696*4887Schin stakputs(path_basename(name)); 1697*4887Schin else 1698*4887Schin stakputs(name); 1699*4887Schin } 1700*4887Schin stakputc(0); 1701*4887Schin np = nv_search(stakptr(offset),shlex.entity_tree,NV_ADD); 1702*4887Schin stakseek(offset); 1703*4887Schin np->nvalue.i = pkind; 1704*4887Schin nv_setsize(np,width); 1705*4887Schin if(!nv_isattr(np,NV_TAGGED) && first>=0) 1706*4887Schin { 1707*4887Schin nv_onattr(np,NV_TAGGED); 1708*4887Schin if(!pkind) 1709*4887Schin pkind = '0'; 1710*4887Schin if(len>0) 1711*4887Schin sfprintf(shlex.kiafile,"%..64d;%c;%.*s;%d;%d;%..64d;%..64d;%c;%d;%s\n",np->hash,type,len,name,first,last,parent,shlex.fscript,pkind,width,attr); 1712*4887Schin else 1713*4887Schin sfprintf(shlex.kiafile,"%..64d;%c;%s;%d;%d;%..64d;%..64d;%c;%d;%s\n",np->hash,type,name,first,last,parent,shlex.fscript,pkind,width,attr); 1714*4887Schin } 1715*4887Schin return(np->hash); 1716*4887Schin } 1717*4887Schin 1718*4887Schin static void kia_add(register Namval_t *np, void *data) 1719*4887Schin { 1720*4887Schin char *name = nv_name(np); 1721*4887Schin NOT_USED(data); 1722*4887Schin kiaentity(name+1,-1,*name,0,-1,(*name=='p'?shlex.unknown:shlex.script),np->nvalue.i,nv_size(np),""); 1723*4887Schin } 1724*4887Schin 1725*4887Schin int kiaclose(void) 1726*4887Schin { 1727*4887Schin register off_t off1,off2; 1728*4887Schin register int n; 1729*4887Schin if(shlex.kiafile) 1730*4887Schin { 1731*4887Schin unsigned long r = kiaentity(shlex.scriptname,-1,'p',-1,sh.inlineno-1,0,'s',0,""); 1732*4887Schin kiaentity(shlex.scriptname,-1,'p',1,sh.inlineno-1,r,'s',0,""); 1733*4887Schin kiaentity(shlex.scriptname,-1,'f',1,sh.inlineno-1,r,'s',0,""); 1734*4887Schin nv_scan(shlex.entity_tree,kia_add,(void*)0,NV_TAGGED,0); 1735*4887Schin off1 = sfseek(shlex.kiafile,(off_t)0,SEEK_END); 1736*4887Schin sfseek(shlex.kiatmp,(off_t)0,SEEK_SET); 1737*4887Schin sfmove(shlex.kiatmp,shlex.kiafile,SF_UNBOUND,-1); 1738*4887Schin off2 = sfseek(shlex.kiafile,(off_t)0,SEEK_END); 1739*4887Schin #ifdef SF_BUFCONST 1740*4887Schin if(off2==off1) 1741*4887Schin n= sfprintf(shlex.kiafile,"DIRECTORY\nENTITY;%lld;%d\nDIRECTORY;",(Sflong_t)shlex.kiabegin,(size_t)(off1-shlex.kiabegin)); 1742*4887Schin else 1743*4887Schin n= sfprintf(shlex.kiafile,"DIRECTORY\nENTITY;%lld;%d\nRELATIONSHIP;%lld;%d\nDIRECTORY;",(Sflong_t)shlex.kiabegin,(size_t)(off1-shlex.kiabegin),(Sflong_t)off1,(size_t)(off2-off1)); 1744*4887Schin if(off2 >= INT_MAX) 1745*4887Schin off2 = -(n+12); 1746*4887Schin sfprintf(shlex.kiafile,"%010.10lld;%010d\n",(Sflong_t)off2+10, n+12); 1747*4887Schin #else 1748*4887Schin if(off2==off1) 1749*4887Schin n= sfprintf(shlex.kiafile,"DIRECTORY\nENTITY;%d;%d\nDIRECTORY;",shlex.kiabegin,off1-shlex.kiabegin); 1750*4887Schin else 1751*4887Schin n= sfprintf(shlex.kiafile,"DIRECTORY\nENTITY;%d;%d\nRELATIONSHIP;%d;%d\nDIRECTORY;",shlex.kiabegin,off1-shlex.kiabegin,off1,off2-off1); 1752*4887Schin sfprintf(shlex.kiafile,"%010d;%010d\n",off2+10, n+12); 1753*4887Schin #endif 1754*4887Schin } 1755*4887Schin return(sfclose(shlex.kiafile)); 1756*4887Schin } 1757*4887Schin #endif /* SHOPT_KIA */ 1758