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