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