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