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