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