1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1982-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * David Korn <dgk@research.att.com> * 18 * * 19 ***********************************************************************/ 20 #pragma prototyped 21 /* 22 * KornShell lexical analyzer 23 * 24 * Written by David Korn 25 * AT&T Labs 26 * 27 */ 28 29 #include <ast.h> 30 #include <stak.h> 31 #include <fcin.h> 32 #include <nval.h> 33 #include "FEATURE/options" 34 35 #if KSHELL 36 # include "defs.h" 37 #else 38 # include <shell.h> 39 # define nv_getval(np) ((np)->nvalue) 40 Shell_t sh = {1}; 41 #endif /* KSHELL */ 42 43 #include "argnod.h" 44 #include "test.h" 45 #include "lexstates.h" 46 #include "io.h" 47 48 #define TEST_RE 3 49 #define SYNBAD 3 /* exit value for syntax errors */ 50 #define STACK_ARRAY 3 /* size of depth match stack growth */ 51 52 #if _lib_iswblank < 0 /* set in lexstates.h to enable this code */ 53 54 int 55 local_iswblank(wchar_t wc) 56 { 57 static int initialized; 58 static wctype_t wt; 59 60 if (!initialized) 61 { 62 initialized = 1; 63 wt = wctype("blank"); 64 } 65 return(iswctype(wc, wt)); 66 } 67 68 #endif 69 70 /* 71 * This structure allows for arbitrary depth nesting of (...), {...}, [...] 72 */ 73 struct lexstate 74 { 75 char incase; /* 1 for case pattern, 2 after case */ 76 char intest; /* 1 inside [[...]] */ 77 char testop1; /* 1 when unary test op legal */ 78 char testop2; /* 1 when binary test op legal */ 79 char reservok; /* >0 for reserved word legal */ 80 char skipword; /* next word can't be reserved */ 81 char last_quote; /* last multi-line quote character */ 82 char comp_assign; /* inside compound assignment */ 83 }; 84 85 struct lexdata 86 { 87 char nocopy; 88 char paren; 89 char dolparen; 90 char nest; 91 char docword; 92 char *docend; 93 char noarg; 94 char balance; 95 char warn; 96 char message; 97 char arith; 98 char *first; 99 int level; 100 int lastc; 101 int lex_max; 102 int *lex_match; 103 int lex_state; 104 #if SHOPT_KIA 105 off_t kiaoff; 106 #endif 107 }; 108 109 #define _SHLEX_PRIVATE \ 110 struct lexdata _lexd; \ 111 struct lexstate _lex; 112 113 #include "shlex.h" 114 115 #define lexd lp->_lexd 116 #define lex lp->_lex 117 #undef shlex 118 #define shlex lp->_shlex 119 120 121 #define pushlevel(c,s) ((lexd.level>=lexd.lex_max?stack_grow(lp):1) &&\ 122 ((lexd.lex_match[lexd.level++]=lexd.lastc),\ 123 lexd.lastc=(((s)<<CHAR_BIT)|(c)))) 124 #define oldmode() (lexd.lastc>>CHAR_BIT) 125 #define endchar() (lexd.lastc&0xff) 126 #define setchar(c) (lexd.lastc = ((lexd.lastc&~0xff)|(c))) 127 #define poplevel() (lexd.lastc=lexd.lex_match[--lexd.level]) 128 129 static char *fmttoken(Lex_t*, int, char*); 130 #ifdef SF_BUFCONST 131 static int alias_exceptf(Sfio_t*, int, void*, Sfdisc_t*); 132 #else 133 static int alias_exceptf(Sfio_t*, int, Sfdisc_t*); 134 #endif 135 static void setupalias(Lex_t*,const char*, Namval_t*); 136 static int comsub(Lex_t*); 137 static void nested_here(Lex_t*); 138 static int here_copy(Lex_t*, struct ionod*); 139 static int stack_grow(Lex_t*); 140 static const Sfdisc_t alias_disc = { NULL, NULL, NULL, alias_exceptf, NULL }; 141 142 #if SHOPT_KIA 143 144 static void refvar(int type) 145 { 146 register Shell_t *shp = sh_getinterp(); 147 register Lex_t *lp = (Lex_t*)shp->lex_context; 148 off_t off = (fcseek(0)-(type+1))-(lexd.first?lexd.first:fcfirst()); 149 unsigned long r; 150 if(lexd.first) 151 { 152 off = (fcseek(0)-(type+1)) - lexd.first; 153 r=kiaentity(lexd.first+lexd.kiaoff+type,off-lexd.kiaoff,'v',-1,-1,shlex.current,'v',0,""); 154 } 155 else 156 { 157 int n,offset = staktell(); 158 char *savptr,*begin; 159 off = offset + (fcseek(0)-(type+1)) - fcfirst(); 160 if(lexd.kiaoff < offset) 161 { 162 /* variable starts on stak, copy remainder */ 163 if(off>offset) 164 stakwrite(fcfirst()+type,off-offset); 165 n = staktell()-lexd.kiaoff; 166 begin = stakptr(lexd.kiaoff); 167 } 168 else 169 { 170 /* variable in data buffer */ 171 begin = fcfirst()+(type+lexd.kiaoff-offset); 172 n = off-lexd.kiaoff; 173 } 174 savptr = stakfreeze(0); 175 r=kiaentity(begin,n,'v',-1,-1,shlex.current,'v',0,""); 176 stakset(savptr,offset); 177 } 178 sfprintf(shlex.kiatmp,"p;%..64d;v;%..64d;%d;%d;r;\n",shlex.current,r,shp->inlineno,shp->inlineno); 179 } 180 #endif /* SHOPT_KIA */ 181 182 /* 183 * This routine gets called when reading across a buffer boundary 184 * If lexd.nocopy is off, then current token is saved on the stack 185 */ 186 static void lex_advance(Sfio_t *iop, const char *buff, register int size) 187 { 188 register Shell_t *shp = sh_getinterp(); 189 register Lex_t *lp = (Lex_t*)shp->lex_context; 190 register Sfio_t *log= shp->funlog; 191 #if KSHELL 192 /* write to history file and to stderr if necessary */ 193 if(iop && !sfstacked(iop)) 194 { 195 if(sh_isstate(SH_HISTORY) && shp->hist_ptr) 196 log = shp->hist_ptr->histfp; 197 sfwrite(log, (void*)buff, size); 198 if(sh_isstate(SH_VERBOSE)) 199 sfwrite(sfstderr, buff, size); 200 } 201 #endif 202 if(lexd.nocopy) 203 return; 204 if(lexd.first) 205 { 206 size -= (lexd.first-(char*)buff); 207 buff = lexd.first; 208 if(!lexd.noarg) 209 shlex.arg = (struct argnod*)stakseek(ARGVAL); 210 #if SHOPT_KIA 211 lexd.kiaoff += ARGVAL; 212 #endif /* SHOPT_KIA */ 213 } 214 if(size>0 && (shlex.arg||lexd.noarg)) 215 { 216 stakwrite(buff,size); 217 lexd.first = 0; 218 } 219 } 220 221 /* 222 * fill up another input buffer 223 * preserves lexical state 224 */ 225 static int lexfill(void) 226 { 227 Shell_t *shp = sh_getinterp(); 228 register int c; 229 register Lex_t *lp = (Lex_t*)shp->lex_context; 230 struct shlex_t savelex; 231 struct lexdata savedata; 232 struct lexstate savestate; 233 struct argnod *ap; 234 int aok; 235 savelex = shlex; 236 savedata = lexd; 237 savestate = lex; 238 ap = shlex.arg; 239 c = fcfill(); 240 if(ap) 241 shlex.arg = ap; 242 lex = savestate; 243 lexd = savedata; 244 lexd.first = 0; 245 aok= shlex.aliasok; 246 ap = shlex.arg; 247 shlex = savelex; 248 shlex.arg = ap; 249 shlex.aliasok = aok; 250 return(c); 251 } 252 253 /* 254 * mode=1 for reinitialization 255 */ 256 Lex_t *sh_lexopen(Lex_t *lp, Shell_t *sp, int mode) 257 { 258 fcnotify(lex_advance); 259 if(!lp) 260 { 261 lp = (Lex_t*)newof(0,Lex_t,1,0); 262 lp->_shlex.sh = sp; 263 } 264 lex.intest = lex.incase = lex.skipword = lexd.warn = 0; 265 lex.comp_assign = 0; 266 lex.reservok = 1; 267 if(!sh_isoption(SH_DICTIONARY) && sh_isoption(SH_NOEXEC)) 268 lexd.warn=1; 269 if(!mode) 270 { 271 lexd.noarg = lexd.level= lexd.dolparen = 0; 272 lexd.nocopy = lexd.docword = lexd.nest = lexd.paren = 0; 273 } 274 shlex.comsub = 0; 275 return(lp); 276 } 277 278 #ifdef DBUG 279 extern int lextoken(void); 280 int sh_lex(void) 281 { 282 Shell_t *shp = sh_getinterp(); 283 register Lex_t *lp = (Lex_t*)shp->lex_context; 284 register int flag; 285 char *quoted, *macro, *split, *expand; 286 char tokstr[3]; 287 register int tok = lextoken(); 288 quoted = macro = split = expand = ""; 289 if(tok==0 && (flag=shlex.arg->argflag)) 290 { 291 if(flag&ARG_MAC) 292 macro = "macro:"; 293 if(flag&ARG_EXP) 294 expand = "expand:"; 295 if(flag&ARG_QUOTED) 296 quoted = "quoted:"; 297 } 298 sfprintf(sfstderr,"line %d: %o:%s%s%s%s %s\n",shp->inlineno,tok,quoted, 299 macro, split, expand, fmttoken(lp,tok,tokstr)); 300 return(tok); 301 } 302 #define sh_lex lextoken 303 #endif 304 305 /* 306 * Get the next word and put it on the top of the stak 307 * A pointer to the current word is stored in shlex.arg 308 * Returns the token type 309 */ 310 int sh_lex(void) 311 { 312 register Shell_t *shp = sh_getinterp(); 313 register const char *state; 314 register int n, c, mode=ST_BEGIN, wordflags=0; 315 register Lex_t *lp = (Lex_t*)shp->lex_context; 316 int inlevel=lexd.level, assignment=0, ingrave=0; 317 Sfio_t *sp; 318 #if SHOPT_MULTIBYTE 319 LEN=1; 320 #endif /* SHOPT_MULTIBYTE */ 321 if(lexd.paren) 322 { 323 lexd.paren = 0; 324 return(shlex.token=LPAREN); 325 } 326 if(lex.incase) 327 shlex.assignok = 0; 328 else 329 shlex.assignok |= lex.reservok; 330 if(lex.comp_assign==2) 331 lex.comp_assign = lex.reservok = 0; 332 lexd.arith = (lexd.nest==1); 333 if(lexd.nest) 334 { 335 pushlevel(lexd.nest,ST_NONE); 336 lexd.nest = 0; 337 mode = lexd.lex_state; 338 } 339 else if(lexd.docword) 340 { 341 if(fcgetc(c)=='-' || c=='#') 342 { 343 lexd.docword++; 344 shlex.digits=(c=='#'?3:1); 345 } 346 else if(c=='<') 347 { 348 shlex.digits=2; 349 lexd.docword=0; 350 } 351 else if(c>0) 352 fcseek(-1); 353 } 354 if(!lexd.dolparen) 355 { 356 shlex.arg = 0; 357 if(mode!=ST_BEGIN) 358 lexd.first = fcseek(0); 359 else 360 lexd.first = 0; 361 } 362 shlex.lastline = sh.inlineno; 363 while(1) 364 { 365 /* skip over characters in the current state */ 366 state = sh_lexstates[mode]; 367 while((n=STATE(state,c))==0); 368 switch(n) 369 { 370 case S_BREAK: 371 fcseek(-1); 372 goto breakloop; 373 case S_EOF: 374 sp = fcfile(); 375 if((n=lexfill()) > 0) 376 { 377 fcseek(-1); 378 continue; 379 } 380 /* check for zero byte in file */ 381 if(n==0 && fcfile()) 382 { 383 if(shp->readscript) 384 { 385 char *cp = error_info.id; 386 errno = ENOEXEC; 387 error_info.id = shp->readscript; 388 errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,cp); 389 } 390 else 391 { 392 shlex.token = -1; 393 sh_syntax(); 394 } 395 } 396 /* end-of-file */ 397 if(mode==ST_BEGIN) 398 return(shlex.token=EOFSYM); 399 if(mode >ST_NORM && lexd.level>0) 400 { 401 switch(c=endchar()) 402 { 403 case '$': 404 if(mode==ST_LIT) 405 { 406 c = '\''; 407 break; 408 } 409 mode = oldmode(); 410 poplevel(); 411 continue; 412 case RBRACT: 413 c = LBRACT; 414 break; 415 case 1: /* for ((...)) */ 416 case RPAREN: 417 c = LPAREN; 418 break; 419 default: 420 c = LBRACE; 421 break; 422 case '"': case '`': case '\'': 423 lexd.balance = c; 424 break; 425 } 426 if(sp && !(sfset(sp,0,0)&SF_STRING)) 427 { 428 shlex.lasttok = c; 429 shlex.token = EOFSYM; 430 sh_syntax(); 431 } 432 lexd.balance = c; 433 } 434 goto breakloop; 435 case S_COM: 436 /* skip one or more comment line(s) */ 437 lex.reservok = !lex.intest; 438 if((n=lexd.nocopy) && lexd.dolparen) 439 lexd.nocopy--; 440 do 441 { 442 while(fcgetc(c)>0 && c!='\n'); 443 if(c<=0 || shlex.heredoc) 444 break; 445 while(shp->inlineno++,fcpeek(0)=='\n') 446 fcseek(1); 447 while(state[c=fcpeek(0)]==0) 448 fcseek(1); 449 } 450 while(c=='#'); 451 lexd.nocopy = n; 452 if(c<0) 453 return(shlex.token=EOFSYM); 454 n = S_NLTOK; 455 shp->inlineno--; 456 /* FALL THRU */ 457 case S_NLTOK: 458 /* check for here-document */ 459 if(shlex.heredoc) 460 { 461 if(!lexd.dolparen) 462 lexd.nocopy++; 463 c = shp->inlineno; 464 if(here_copy(lp,shlex.heredoc)<=0 && shlex.lasttok) 465 { 466 shlex.lasttok = IODOCSYM; 467 shlex.token = EOFSYM; 468 shlex.lastline = c; 469 sh_syntax(); 470 } 471 if(!lexd.dolparen) 472 lexd.nocopy--; 473 shlex.heredoc = 0; 474 } 475 lex.reservok = !lex.intest; 476 lex.skipword = 0; 477 /* FALL THRU */ 478 case S_NL: 479 /* skip over new-lines */ 480 lex.last_quote = 0; 481 while(shp->inlineno++,fcget()=='\n'); 482 fcseek(-1); 483 if(n==S_NLTOK) 484 { 485 lex.comp_assign = 0; 486 return(shlex.token='\n'); 487 } 488 case S_BLNK: 489 if(lex.incase<=TEST_RE) 490 continue; 491 /* implicit RPAREN for =~ test operator */ 492 if(inlevel+1==lexd.level) 493 { 494 fcseek(-1); 495 c = RPAREN; 496 goto do_pop; 497 } 498 continue; 499 case S_OP: 500 /* return operator token */ 501 if(c=='<' || c=='>') 502 { 503 if(lex.testop2) 504 lex.testop2 = 0; 505 else 506 { 507 shlex.digits = (c=='>'); 508 lex.skipword = 1; 509 shlex.aliasok = lex.reservok; 510 lex.reservok = 0; 511 } 512 } 513 else 514 { 515 lex.reservok = !lex.intest; 516 if(c==RPAREN) 517 { 518 if(!lexd.dolparen) 519 lex.incase = 0; 520 return(shlex.token=c); 521 } 522 lex.testop1 = lex.intest; 523 } 524 if(fcgetc(n)>0) 525 fcseek(-1); 526 if(state[n]==S_OP || n=='#') 527 { 528 if(n==c) 529 { 530 if(c=='<') 531 lexd.docword=1; 532 else if(n==LPAREN) 533 { 534 lexd.nest=1; 535 shlex.lastline = shp->inlineno; 536 lexd.lex_state = ST_NESTED; 537 fcseek(1); 538 return(sh_lex()); 539 } 540 c |= SYMREP; 541 } 542 else if(c=='(' || c==')') 543 return(shlex.token=c); 544 else if(c=='&') 545 { 546 #if SHOPT_BASH 547 if(!sh_isoption(SH_POSIX) && n=='>') 548 { 549 shlex.digits = -1; 550 c = '>'; 551 } 552 else 553 #endif 554 n = 0; 555 } 556 else if(n=='&') 557 c |= SYMAMP; 558 else if(c!='<' && c!='>') 559 n = 0; 560 else if(n==LPAREN) 561 { 562 c |= SYMLPAR; 563 lex.reservok = 1; 564 lex.skipword = 0; 565 } 566 else if(n=='|') 567 c |= SYMPIPE; 568 else if(c=='<' && n=='>') 569 c = IORDWRSYM; 570 else if(n=='#' && (c=='<'||c=='>')) 571 c |= SYMSHARP; 572 else 573 n = 0; 574 if(n) 575 { 576 fcseek(1); 577 lex.incase = (c==BREAKCASESYM || c==FALLTHRUSYM); 578 } 579 else 580 { 581 if((n=fcpeek(0))!=RPAREN && n!=LPAREN && lexd.warn) 582 errormsg(SH_DICT,ERROR_warn(0),e_lexspace,shp->inlineno,c,n); 583 } 584 } 585 if(c==LPAREN && lex.comp_assign && !lex.intest && !lex.incase) 586 lex.comp_assign = 2; 587 else 588 lex.comp_assign = 0; 589 return(shlex.token=c); 590 case S_ESC: 591 /* check for \<new-line> */ 592 fcgetc(n); 593 c=2; 594 #if SHOPT_CRNL 595 if(n=='\r') 596 { 597 if(fcgetc(n)=='\n') 598 c=3; 599 else 600 { 601 n='\r'; 602 fcseek(-1); 603 } 604 } 605 #endif /* SHOPT_CRNL */ 606 if(n=='\n') 607 { 608 Sfio_t *sp; 609 struct argnod *ap; 610 shp->inlineno++; 611 /* synchronize */ 612 if(!(sp=fcfile())) 613 state=fcseek(0); 614 fcclose(); 615 ap = shlex.arg; 616 if(sp) 617 fcfopen(sp); 618 else 619 fcsopen((char*)state); 620 /* remove \new-line */ 621 n = staktell()-c; 622 stakseek(n); 623 shlex.arg = ap; 624 if(n<=ARGVAL) 625 { 626 mode = 0; 627 lexd.first = 0; 628 } 629 continue; 630 } 631 wordflags |= ARG_QUOTED; 632 if(mode==ST_DOL) 633 goto err; 634 #ifndef STR_MAXIMAL 635 else if(mode==ST_NESTED && lexd.warn && 636 endchar()==RBRACE && 637 sh_lexstates[ST_DOL][n]==S_DIG 638 ) 639 errormsg(SH_DICT,ERROR_warn(0),e_lexfuture,shp->inlineno,n); 640 #endif /* STR_MAXIMAL */ 641 break; 642 case S_NAME: 643 if(!lex.skipword) 644 lex.reservok *= 2; 645 /* FALL THRU */ 646 case S_TILDE: 647 case S_RES: 648 if(!lexd.dolparen) 649 lexd.first = fcseek(0)-LEN; 650 else if(lexd.docword) 651 lexd.docend = fcseek(0)-LEN; 652 mode = ST_NAME; 653 if(c=='.') 654 fcseek(-1); 655 if(n!=S_TILDE) 656 continue; 657 fcgetc(n); 658 if(n>0) 659 fcseek(-1); 660 if(n==LPAREN) 661 goto epat; 662 wordflags = ARG_MAC; 663 mode = ST_NORM; 664 continue; 665 case S_REG: 666 if(mode==ST_BEGIN) 667 { 668 /* skip new-line joining */ 669 if(c=='\\' && fcpeek(0)=='\n') 670 { 671 shp->inlineno++; 672 fcseek(1); 673 continue; 674 } 675 fcseek(-1); 676 if(!lexd.dolparen) 677 lexd.first = fcseek(0); 678 else if(lexd.docword) 679 lexd.docend = fcseek(0); 680 if(c=='[' && shlex.assignok>=SH_ASSIGN) 681 { 682 mode = ST_NAME; 683 continue; 684 } 685 } 686 mode = ST_NORM; 687 continue; 688 case S_LIT: 689 if(oldmode()==ST_NONE) /* in ((...)) */ 690 { 691 if((c=fcpeek(0))==LPAREN || c==RPAREN || c=='$' || c==LBRACE || c==RBRACE || c=='[' || c==']') 692 { 693 if(fcpeek(1)=='\'') 694 fcseek(2); 695 } 696 continue; 697 } 698 wordflags |= ARG_QUOTED; 699 if(mode==ST_DOL) 700 { 701 if(endchar()!='$') 702 goto err; 703 if(oldmode()==ST_QUOTE) /* $' within "" or `` */ 704 { 705 if(lexd.warn) 706 errormsg(SH_DICT,ERROR_warn(0),e_lexslash,shp->inlineno); 707 mode = ST_LIT; 708 } 709 } 710 if(mode!=ST_LIT) 711 { 712 if(lexd.warn && lex.last_quote && shp->inlineno > shlex.lastline) 713 errormsg(SH_DICT,ERROR_warn(0),e_lexlongquote,shlex.lastline,lex.last_quote); 714 lex.last_quote = 0; 715 shlex.lastline = shp->inlineno; 716 if(mode!=ST_DOL) 717 pushlevel('\'',mode); 718 mode = ST_LIT; 719 continue; 720 } 721 /* check for multi-line single-quoted string */ 722 else if(shp->inlineno > shlex.lastline) 723 lex.last_quote = '\''; 724 mode = oldmode(); 725 poplevel(); 726 break; 727 case S_ESC2: 728 /* \ inside '' */ 729 if(endchar()=='$') 730 { 731 fcgetc(n); 732 if(n=='\n') 733 shp->inlineno++; 734 } 735 continue; 736 case S_GRAVE: 737 if(lexd.warn && (mode!=ST_QUOTE || endchar()!='`')) 738 errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete1,shp->inlineno); 739 wordflags |=(ARG_MAC|ARG_EXP); 740 if(mode==ST_QUOTE) 741 ingrave = !ingrave; 742 /* FALL THRU */ 743 case S_QUOTE: 744 if(oldmode()==ST_NONE && lexd.arith) /* in ((...)) */ 745 continue; 746 if(n==S_QUOTE) 747 wordflags |=ARG_QUOTED; 748 if(mode!=ST_QUOTE) 749 { 750 if(c!='"' || mode!=ST_QNEST) 751 { 752 if(lexd.warn && lex.last_quote && shp->inlineno > shlex.lastline) 753 errormsg(SH_DICT,ERROR_warn(0),e_lexlongquote,shlex.lastline,lex.last_quote); 754 lex.last_quote=0; 755 shlex.lastline = shp->inlineno; 756 pushlevel(c,mode); 757 } 758 ingrave = (c=='`'); 759 mode = ST_QUOTE; 760 continue; 761 } 762 else if((n=endchar())==c) 763 { 764 if(shp->inlineno > shlex.lastline) 765 lex.last_quote = c; 766 mode = oldmode(); 767 poplevel(); 768 } 769 else if(c=='"' && n==RBRACE) 770 mode = ST_QNEST; 771 break; 772 case S_DOL: 773 /* don't check syntax inside `` */ 774 if(mode==ST_QUOTE && ingrave) 775 continue; 776 #if SHOPT_KIA 777 if(lexd.first) 778 lexd.kiaoff = fcseek(0)-lexd.first; 779 else 780 lexd.kiaoff = staktell()+fcseek(0)-fcfirst(); 781 #endif /* SHOPT_KIA */ 782 pushlevel('$',mode); 783 mode = ST_DOL; 784 continue; 785 case S_PAR: 786 wordflags |= ARG_MAC; 787 mode = oldmode(); 788 poplevel(); 789 fcseek(-1); 790 wordflags |= comsub(lp); 791 continue; 792 case S_RBRA: 793 if((n=endchar()) == '$') 794 goto err; 795 if(mode!=ST_QUOTE || n==RBRACE) 796 { 797 mode = oldmode(); 798 poplevel(); 799 } 800 break; 801 case S_EDOL: 802 /* end $identifier */ 803 #if SHOPT_KIA 804 if(shlex.kiafile) 805 refvar(0); 806 #endif /* SHOPT_KIA */ 807 if(lexd.warn && c==LBRACT) 808 errormsg(SH_DICT,ERROR_warn(0),e_lexusebrace,shp->inlineno); 809 fcseek(-1); 810 mode = oldmode(); 811 poplevel(); 812 break; 813 case S_DOT: 814 /* make sure next character is alpha */ 815 if(fcgetc(n)>0) 816 fcseek(-1); 817 if(isaletter(n) || n==LBRACT) 818 continue; 819 if(mode==ST_NAME) 820 { 821 if(n=='=') 822 continue; 823 break; 824 } 825 else if(n==RBRACE) 826 continue; 827 if(isastchar(n)) 828 continue; 829 goto err; 830 case S_SPC1: 831 wordflags |= ARG_MAC; 832 if(endchar()==RBRACE) 833 { 834 setchar(c); 835 continue; 836 } 837 /* FALL THRU */ 838 case S_ALP: 839 if(c=='.' && endchar()=='$') 840 goto err; 841 case S_SPC2: 842 case S_DIG: 843 wordflags |= ARG_MAC; 844 switch(endchar()) 845 { 846 case '$': 847 if(n==S_ALP) /* $identifier */ 848 mode = ST_DOLNAME; 849 else 850 { 851 mode = oldmode(); 852 poplevel(); 853 } 854 break; 855 #if SHOPT_TYPEDEF 856 case '@': 857 #endif /* SHOPT_TYPEDEF */ 858 case '!': 859 if(n!=S_ALP) 860 goto dolerr; 861 case '#': 862 case RBRACE: 863 if(n==S_ALP) 864 { 865 setchar(RBRACE); 866 if(c=='.') 867 fcseek(-1); 868 mode = ST_BRACE; 869 } 870 else 871 { 872 if(fcgetc(c)>0) 873 fcseek(-1); 874 if(state[c]==S_ALP) 875 goto err; 876 if(n==S_DIG) 877 setchar('0'); 878 else 879 setchar('!'); 880 } 881 break; 882 case '0': 883 if(n==S_DIG) 884 break; 885 default: 886 goto dolerr; 887 } 888 break; 889 dolerr: 890 case S_ERR: 891 if((n=endchar()) == '$') 892 goto err; 893 if(c=='*' || (n=sh_lexstates[ST_BRACE][c])!=S_MOD1 && n!=S_MOD2) 894 { 895 /* see whether inside `...` */ 896 mode = oldmode(); 897 poplevel(); 898 if((n = endchar()) != '`') 899 goto err; 900 pushlevel(RBRACE,mode); 901 } 902 else 903 setchar(RBRACE); 904 mode = ST_NESTED; 905 continue; 906 case S_MOD1: 907 if(oldmode()==ST_QUOTE || oldmode()==ST_NONE) 908 { 909 /* allow ' inside "${...}" */ 910 if(c==':' && fcgetc(n)>0) 911 { 912 n = state[n]; 913 fcseek(-1); 914 } 915 if(n==S_MOD1) 916 { 917 mode = ST_QUOTE; 918 continue; 919 } 920 } 921 /* FALL THRU */ 922 case S_MOD2: 923 #if SHOPT_KIA 924 if(shlex.kiafile) 925 refvar(1); 926 #endif /* SHOPT_KIA */ 927 if(c!=':' && fcgetc(n)>0) 928 { 929 if(n!=c) 930 c = 0; 931 if(!c || (fcgetc(n)>0)) 932 { 933 fcseek(-1); 934 if(n==LPAREN) 935 { 936 if(c!='%') 937 { 938 shlex.token = n; 939 sh_syntax(); 940 } 941 else if(lexd.warn) 942 errormsg(SH_DICT,ERROR_warn(0),e_lexquote,shp->inlineno,'%'); 943 } 944 } 945 } 946 mode = ST_NESTED; 947 continue; 948 case S_LBRA: 949 if((c=endchar()) == '$') 950 { 951 setchar(RBRACE); 952 if(fcgetc(c)>0) 953 fcseek(-1); 954 if(state[c]!=S_ERR && c!=RBRACE) 955 continue; 956 } 957 err: 958 n = endchar(); 959 mode = oldmode(); 960 poplevel(); 961 if(n!='$') 962 { 963 shlex.token = c; 964 sh_syntax(); 965 } 966 else 967 { 968 if(lexd.warn && c!='/' && sh_lexstates[ST_NORM][c]!=S_BREAK && (c!='"' || mode==ST_QUOTE)) 969 errormsg(SH_DICT,ERROR_warn(0),e_lexslash,shp->inlineno); 970 else if(c=='"' && mode!=ST_QUOTE) 971 wordflags |= ARG_MESSAGE; 972 fcseek(-1); 973 } 974 continue; 975 case S_META: 976 if(lexd.warn && endchar()==RBRACE) 977 errormsg(SH_DICT,ERROR_warn(0),e_lexusequote,shp->inlineno,c); 978 continue; 979 case S_PUSH: 980 pushlevel(RPAREN,mode); 981 mode = ST_NESTED; 982 continue; 983 case S_POP: 984 do_pop: 985 if(lexd.level <= inlevel) 986 break; 987 n = endchar(); 988 if(c==RBRACT && !(n==RBRACT || n==RPAREN)) 989 continue; 990 if((c==RBRACE||c==RPAREN) && n==RPAREN) 991 { 992 if(fcgetc(n)==LPAREN) 993 { 994 if(c!=RPAREN) 995 fcseek(-1); 996 continue; 997 } 998 if(n>0) 999 fcseek(-1); 1000 n = RPAREN; 1001 } 1002 if(c==';' && n!=';') 1003 { 1004 if(lexd.warn && n==RBRACE) 1005 errormsg(SH_DICT,ERROR_warn(0),e_lexusequote,shp->inlineno,c); 1006 continue; 1007 } 1008 if(mode==ST_QNEST) 1009 { 1010 if(lexd.warn) 1011 errormsg(SH_DICT,ERROR_warn(0),e_lexescape,shp->inlineno,c); 1012 continue; 1013 } 1014 mode = oldmode(); 1015 poplevel(); 1016 /* quotes in subscript need expansion */ 1017 if(mode==ST_NAME && (wordflags&ARG_QUOTED)) 1018 wordflags |= ARG_MAC; 1019 /* check for ((...)) */ 1020 if(n==1 && c==RPAREN) 1021 { 1022 if(fcgetc(n)==RPAREN) 1023 { 1024 if(mode==ST_NONE && !lexd.dolparen) 1025 goto breakloop; 1026 lex.reservok = 1; 1027 lex.skipword = 0; 1028 return(shlex.token=EXPRSYM); 1029 } 1030 /* backward compatibility */ 1031 if(lexd.dolparen) 1032 fcseek(-1); 1033 else 1034 { 1035 if(lexd.warn) 1036 errormsg(SH_DICT,ERROR_warn(0),e_lexnested,shp->inlineno); 1037 if(!(state=lexd.first)) 1038 state = fcfirst(); 1039 fcseek(state-fcseek(0)); 1040 if(shlex.arg) 1041 { 1042 shlex.arg = (struct argnod*)stakfreeze(1); 1043 setupalias(lp,shlex.arg->argval,NIL(Namval_t*)); 1044 } 1045 lexd.paren = 1; 1046 } 1047 return(shlex.token=LPAREN); 1048 } 1049 if(mode==ST_NONE) 1050 return(0); 1051 if(c!=n) 1052 { 1053 shlex.token = c; 1054 sh_syntax(); 1055 } 1056 if(c==RBRACE && (mode==ST_NAME||mode==ST_NORM)) 1057 goto epat; 1058 continue; 1059 case S_EQ: 1060 assignment = shlex.assignok; 1061 /* FALL THRU */ 1062 case S_COLON: 1063 if(assignment) 1064 { 1065 if((c=fcget())=='~') 1066 wordflags |= ARG_MAC; 1067 else if(c!=LPAREN && assignment==SH_COMPASSIGN) 1068 assignment = 0; 1069 fcseek(-1); 1070 } 1071 break; 1072 case S_LABEL: 1073 if(lex.reservok && !lex.incase) 1074 { 1075 c = fcget(); 1076 fcseek(-1); 1077 if(state[c]==S_BREAK) 1078 { 1079 assignment = -1; 1080 goto breakloop; 1081 } 1082 } 1083 break; 1084 case S_BRACT: 1085 /* check for possible subscript */ 1086 if((n=endchar())==RBRACT || n==RPAREN || 1087 (mode==ST_BRACE) || 1088 (oldmode()==ST_NONE) || 1089 (mode==ST_NAME && (shlex.assignok||lexd.level))) 1090 { 1091 pushlevel(RBRACT,mode); 1092 wordflags |= ARG_QUOTED; 1093 mode = ST_NESTED; 1094 continue; 1095 } 1096 wordflags |= ARG_EXP; 1097 break; 1098 case S_BRACE: 1099 { 1100 int isfirst; 1101 if(lexd.dolparen) 1102 break; 1103 isfirst = (lexd.first&&fcseek(0)==lexd.first+1); 1104 fcgetc(n); 1105 /* check for {} */ 1106 if(c==LBRACE && n==RBRACE) 1107 break; 1108 if(n>0) 1109 fcseek(-1); 1110 else if(lex.reservok) 1111 break; 1112 /* check for reserved word { or } */ 1113 if(lex.reservok && state[n]==S_BREAK && isfirst) 1114 break; 1115 if(sh_isoption(SH_BRACEEXPAND) && c==LBRACE && !assignment && state[n]!=S_BREAK 1116 && !lex.incase && !lex.intest 1117 && !lex.skipword) 1118 { 1119 wordflags |= ARG_EXP; 1120 } 1121 if(c==RBRACE && n==LPAREN) 1122 goto epat; 1123 break; 1124 } 1125 case S_PAT: 1126 wordflags |= ARG_EXP; 1127 /* FALL THRU */ 1128 case S_EPAT: 1129 epat: 1130 if(fcgetc(n)==LPAREN) 1131 { 1132 if(lex.incase==TEST_RE) 1133 { 1134 lex.incase++; 1135 pushlevel(RPAREN,ST_NORM); 1136 mode = ST_NESTED; 1137 } 1138 wordflags |= ARG_EXP; 1139 pushlevel(RPAREN,mode); 1140 mode = ST_NESTED; 1141 continue; 1142 } 1143 if(n>0) 1144 fcseek(-1); 1145 if(n=='=' && c=='+' && mode==ST_NAME) 1146 continue; 1147 break; 1148 } 1149 lex.comp_assign = 0; 1150 if(mode==ST_NAME) 1151 mode = ST_NORM; 1152 else if(mode==ST_NONE) 1153 return(0); 1154 } 1155 breakloop: 1156 if(lexd.dolparen) 1157 { 1158 lexd.balance = 0; 1159 if(lexd.docword) 1160 nested_here(lp); 1161 lexd.message = (wordflags&ARG_MESSAGE); 1162 return(shlex.token=0); 1163 } 1164 if(!(state=lexd.first)) 1165 state = fcfirst(); 1166 n = fcseek(0)-(char*)state; 1167 if(!shlex.arg) 1168 shlex.arg = (struct argnod*)stakseek(ARGVAL); 1169 if(n>0) 1170 stakwrite(state,n); 1171 /* add balancing character if necessary */ 1172 if(lexd.balance) 1173 { 1174 stakputc(lexd.balance); 1175 lexd.balance = 0; 1176 } 1177 stakputc(0); 1178 stakseek(staktell()-1); 1179 state = stakptr(ARGVAL); 1180 n = staktell()-ARGVAL; 1181 lexd.first=0; 1182 if(n==1) 1183 { 1184 /* check for numbered redirection */ 1185 n = state[0]; 1186 if((c=='<' || c=='>') && isadigit(n)) 1187 { 1188 c = sh_lex(); 1189 shlex.digits = (n-'0'); 1190 return(c); 1191 } 1192 if(n==LBRACT) 1193 c = 0; 1194 else if(n=='~') 1195 c = ARG_MAC; 1196 else 1197 c = (wordflags&ARG_EXP); 1198 n = 1; 1199 } 1200 else if(n>2 && state[0]=='{' && state[n-1]=='}' && !lex.intest && !lex.incase && (c=='<' || c== '>') && sh_isoption(SH_BRACEEXPAND)) 1201 { 1202 if(!strchr(state,',')) 1203 { 1204 stakseek(staktell()-1); 1205 shlex.arg = (struct argnod*)stakfreeze(1); 1206 return(shlex.token=IOVNAME); 1207 } 1208 c = wordflags; 1209 } 1210 else 1211 c = wordflags; 1212 if(assignment<0) 1213 { 1214 stakseek(staktell()-1); 1215 shlex.arg = (struct argnod*)stakfreeze(1); 1216 lex.reservok = 1; 1217 return(shlex.token=LABLSYM); 1218 } 1219 if(assignment || (lex.intest&&!lex.incase) || mode==ST_NONE) 1220 c &= ~ARG_EXP; 1221 if((c&ARG_EXP) && (c&ARG_QUOTED)) 1222 c |= ARG_MAC; 1223 if(mode==ST_NONE) 1224 { 1225 /* eliminate trailing )) */ 1226 stakseek(staktell()-2); 1227 } 1228 if(c&ARG_MESSAGE) 1229 { 1230 if(sh_isoption(SH_DICTIONARY)) 1231 shlex.arg = sh_endword(2); 1232 if(!sh_isoption(SH_NOEXEC)) 1233 { 1234 shlex.arg = sh_endword(1); 1235 c &= ~ARG_MESSAGE; 1236 } 1237 } 1238 if(c==0 || (c&(ARG_MAC|ARG_EXP)) || (lexd.warn && !lexd.docword)) 1239 { 1240 shlex.arg = (struct argnod*)stakfreeze(1); 1241 shlex.arg->argflag = (c?c:ARG_RAW); 1242 } 1243 else if(mode==ST_NONE) 1244 shlex.arg = sh_endword(-1); 1245 else 1246 shlex.arg = sh_endword(0); 1247 state = shlex.arg->argval; 1248 lex.comp_assign = assignment; 1249 if(assignment) 1250 shlex.arg->argflag |= ARG_ASSIGN; 1251 else if(!lex.skipword) 1252 shlex.assignok = 0; 1253 shlex.arg->argchn.cp = 0; 1254 shlex.arg->argnxt.ap = 0; 1255 if(mode==ST_NONE) 1256 return(shlex.token=EXPRSYM); 1257 if(lex.intest) 1258 { 1259 if(lex.testop1) 1260 { 1261 lex.testop1 = 0; 1262 if(n==2 && state[0]=='-' && state[2]==0 && 1263 strchr(test_opchars,state[1])) 1264 { 1265 if(lexd.warn && state[1]=='a') 1266 errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete2,shp->inlineno); 1267 shlex.digits = state[1]; 1268 shlex.token = TESTUNOP; 1269 } 1270 else if(n==1 && state[0]=='!' && state[1]==0) 1271 { 1272 lex.testop1 = 1; 1273 shlex.token = '!'; 1274 } 1275 else 1276 { 1277 lex.testop2 = 1; 1278 shlex.token = 0; 1279 } 1280 return(shlex.token); 1281 } 1282 lex.incase = 0; 1283 c = sh_lookup(state,shtab_testops); 1284 switch(c) 1285 { 1286 case TEST_END: 1287 lex.testop2 = lex.intest = 0; 1288 lex.reservok = 1; 1289 shlex.token = ETESTSYM; 1290 return(shlex.token); 1291 1292 case TEST_SEQ: 1293 if(lexd.warn && state[1]==0) 1294 errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete3,shp->inlineno); 1295 /* FALL THRU */ 1296 default: 1297 if(lex.testop2) 1298 { 1299 if(lexd.warn && (c&TEST_ARITH)) 1300 errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete4,shp->inlineno,state); 1301 if(c&TEST_PATTERN) 1302 lex.incase = 1; 1303 else if(c==TEST_REP) 1304 lex.incase = TEST_RE; 1305 lex.testop2 = 0; 1306 shlex.digits = c; 1307 shlex.token = TESTBINOP; 1308 return(shlex.token); 1309 } 1310 1311 case TEST_OR: case TEST_AND: 1312 case 0: 1313 return(shlex.token=0); 1314 } 1315 } 1316 if(lex.reservok /* && !lex.incase*/ && n<=2) 1317 { 1318 /* check for {, }, ! */ 1319 c = state[0]; 1320 if(n==1 && (c=='{' || c=='}' || c=='!')) 1321 { 1322 if(lexd.warn && c=='{' && lex.incase==2) 1323 errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete6,shp->inlineno); 1324 if(lex.incase==1 && c==RBRACE) 1325 lex.incase = 0; 1326 return(shlex.token=c); 1327 } 1328 else if(!lex.incase && c==LBRACT && state[1]==LBRACT) 1329 { 1330 lex.intest = lex.testop1 = 1; 1331 lex.testop2 = lex.reservok = 0; 1332 return(shlex.token=BTESTSYM); 1333 } 1334 } 1335 c = 0; 1336 if(!lex.skipword) 1337 { 1338 if(n>1 && lex.reservok==1 && mode==ST_NAME && 1339 (c=sh_lookup(state,shtab_reserved))) 1340 { 1341 if(lex.incase) 1342 { 1343 if(lex.incase >1) 1344 lex.incase = 1; 1345 else if(c==ESACSYM) 1346 lex.incase = 0; 1347 else 1348 c = 0; 1349 } 1350 else if(c==FORSYM || c==CASESYM || c==SELECTSYM || c==FUNCTSYM || c==NSPACESYM) 1351 { 1352 lex.skipword = 1; 1353 lex.incase = 2*(c==CASESYM); 1354 } 1355 else 1356 lex.skipword = 0; 1357 if(c==INSYM) 1358 lex.reservok = 0; 1359 else if(c==TIMESYM) 1360 { 1361 /* yech - POSIX requires time -p */ 1362 while(fcgetc(n)==' ' || n=='\t'); 1363 if(n>0) 1364 fcseek(-1); 1365 if(n=='-') 1366 c=0; 1367 } 1368 return(shlex.token=c); 1369 } 1370 if(!(wordflags&ARG_QUOTED) && (lex.reservok||shlex.aliasok)) 1371 { 1372 /* check for aliases */ 1373 Namval_t* np; 1374 if(!lex.incase && !assignment && fcpeek(0)!=LPAREN && 1375 (np=nv_search(state,shp->alias_tree,HASH_SCOPE)) 1376 && !nv_isattr(np,NV_NOEXPAND) 1377 #if KSHELL 1378 && (!sh_isstate(SH_NOALIAS) || nv_isattr(np,NV_NOFREE)) 1379 #endif /* KSHELL */ 1380 && (state=nv_getval(np))) 1381 { 1382 setupalias(lp,state,np); 1383 nv_onattr(np,NV_NOEXPAND); 1384 lex.reservok = 1; 1385 shlex.assignok |= lex.reservok; 1386 return(sh_lex()); 1387 } 1388 } 1389 lex.reservok = 0; 1390 } 1391 lex.skipword = lexd.docword = 0; 1392 return(shlex.token=c); 1393 } 1394 1395 /* 1396 * read to end of command substitution 1397 */ 1398 static int comsub(register Lex_t *lp) 1399 { 1400 register int n,c,count=1; 1401 register int line=shlex.sh->inlineno; 1402 char word[5]; 1403 int messages=0, assignok=shlex.assignok; 1404 struct lexstate save; 1405 save = lex; 1406 sh_lexopen(lp,shlex.sh,1); 1407 lexd.dolparen++; 1408 lex.incase=0; 1409 pushlevel(0,0); 1410 if(sh_lex()==LPAREN) 1411 { 1412 while(1) 1413 { 1414 /* look for case and esac */ 1415 n=0; 1416 while(1) 1417 { 1418 fcgetc(c); 1419 /* skip leading white space */ 1420 if(n==0 && !sh_lexstates[ST_BEGIN][c]) 1421 continue; 1422 if(n==4) 1423 break; 1424 if(sh_lexstates[ST_NAME][c]) 1425 goto skip; 1426 word[n++] = c; 1427 } 1428 if(sh_lexstates[ST_NAME][c]==S_BREAK) 1429 { 1430 if(memcmp(word,"case",4)==0) 1431 lex.incase=1; 1432 else if(memcmp(word,"esac",4)==0) 1433 lex.incase=0; 1434 } 1435 skip: 1436 if(c && (c!='#' || n==0)) 1437 fcseek(-1); 1438 if(c==RBRACE && lex.incase) 1439 lex.incase=0; 1440 switch(sh_lex()) 1441 { 1442 case LPAREN: case IPROCSYM: case OPROCSYM: 1443 if(!lex.incase) 1444 count++; 1445 break; 1446 case RPAREN: 1447 if(lex.incase) 1448 lex.incase=0; 1449 else if(--count<=0) 1450 goto done; 1451 break; 1452 case EOFSYM: 1453 shlex.lastline = line; 1454 shlex.lasttok = LPAREN; 1455 sh_syntax(); 1456 case IOSEEKSYM: 1457 if(fcgetc(c)!='#' && c>0) 1458 fcseek(-1); 1459 break; 1460 case IODOCSYM: 1461 sh_lex(); 1462 break; 1463 case 0: 1464 messages |= lexd.message; 1465 } 1466 } 1467 } 1468 done: 1469 poplevel(); 1470 shlex.lastline = line; 1471 lexd.dolparen--; 1472 lex = save; 1473 shlex.assignok = (endchar()==RBRACT?assignok:0); 1474 return(messages); 1475 } 1476 1477 /* 1478 * here-doc nested in $(...) 1479 * allocate ionode with delimiter filled in without disturbing stak 1480 */ 1481 static void nested_here(register Lex_t *lp) 1482 { 1483 register struct ionod *iop; 1484 register int n,offset; 1485 struct argnod *arg = shlex.arg; 1486 char *base; 1487 if(offset=staktell()) 1488 base = stakfreeze(0); 1489 n = fcseek(0)-lexd.docend; 1490 iop = newof(0,struct ionod,1,n+ARGVAL); 1491 iop->iolst = shlex.heredoc; 1492 stakseek(ARGVAL); 1493 stakwrite(lexd.docend,n); 1494 shlex.arg = sh_endword(0); 1495 iop->ioname = (char*)(iop+1); 1496 strcpy(iop->ioname,shlex.arg->argval); 1497 iop->iofile = (IODOC|IORAW); 1498 if(lexd.docword>1) 1499 iop->iofile |= IOSTRIP; 1500 shlex.heredoc = iop; 1501 shlex.arg = arg; 1502 lexd.docword = 0; 1503 if(offset) 1504 stakset(base,offset); 1505 else 1506 stakseek(0); 1507 } 1508 1509 /* 1510 * skip to <close> character 1511 * if <copy> is non,zero, then the characters are copied to the stack 1512 * <state> is the initial lexical state 1513 */ 1514 void sh_lexskip(int close, register int copy, int state) 1515 { 1516 register Lex_t *lp = (Lex_t*)sh.lex_context; 1517 register char *cp; 1518 lexd.nest = close; 1519 lexd.lex_state = state; 1520 lexd.noarg = 1; 1521 if(copy) 1522 fcnotify(lex_advance); 1523 else 1524 lexd.nocopy++; 1525 sh_lex(); 1526 lexd.noarg = 0; 1527 if(copy) 1528 { 1529 fcnotify(0); 1530 if(!(cp=lexd.first)) 1531 cp = fcfirst(); 1532 if((copy = fcseek(0)-cp) > 0) 1533 stakwrite(cp,copy); 1534 } 1535 else 1536 lexd.nocopy--; 1537 } 1538 1539 #if SHOPT_CRNL 1540 ssize_t _sfwrite(Sfio_t *sp, const Void_t *buff, size_t n) 1541 { 1542 const char *cp = (const char*)buff, *next=cp, *ep = cp + n; 1543 int m=0,k; 1544 while(next = (const char*)memchr(next,'\r',ep-next)) 1545 if(*++next=='\n') 1546 { 1547 if(k=next-cp-1) 1548 { 1549 if((k=sfwrite(sp,cp,k)) < 0) 1550 return(m>0?m:-1); 1551 m += k; 1552 } 1553 cp = next; 1554 } 1555 if((k=sfwrite(sp,cp,ep-cp)) < 0) 1556 return(m>0?m:-1); 1557 return(m+k); 1558 } 1559 # define sfwrite _sfwrite 1560 #endif /* SHOPT_CRNL */ 1561 1562 /* 1563 * read in here-document from script 1564 * quoted here documents, and here-documents without special chars are 1565 * noted with the IOQUOTE flag 1566 * returns 1 for complete here-doc, 0 for EOF 1567 */ 1568 1569 static int here_copy(Lex_t *lp,register struct ionod *iop) 1570 { 1571 register const char *state; 1572 register int c,n; 1573 register char *bufp,*cp; 1574 register Sfio_t *sp=shlex.sh->heredocs, *funlog; 1575 int stripcol=0,stripflg, nsave, special=0; 1576 if(funlog=shlex.sh->funlog) 1577 { 1578 if(fcfill()>0) 1579 fcseek(-1); 1580 shlex.sh->funlog = 0; 1581 } 1582 if(iop->iolst) 1583 here_copy(lp,iop->iolst); 1584 iop->iooffset = sfseek(sp,(off_t)0,SEEK_END); 1585 iop->iosize = 0; 1586 iop->iodelim=iop->ioname; 1587 /* check for and strip quoted characters in delimiter string */ 1588 if(stripflg=iop->iofile&IOSTRIP) 1589 { 1590 while(*iop->iodelim=='\t') 1591 iop->iodelim++; 1592 /* skip over leading tabs in document */ 1593 if(iop->iofile&IOLSEEK) 1594 { 1595 iop->iofile &= ~IOLSEEK; 1596 while(fcgetc(c)=='\t' || c==' ') 1597 { 1598 if(c==' ') 1599 stripcol++; 1600 else 1601 stripcol += 8 - stripcol%8; 1602 } 1603 } 1604 else 1605 while(fcgetc(c)=='\t'); 1606 if(c>0) 1607 fcseek(-1); 1608 } 1609 if(iop->iofile&IOQUOTE) 1610 state = sh_lexstates[ST_LIT]; 1611 else 1612 state = sh_lexstates[ST_QUOTE]; 1613 bufp = fcseek(0); 1614 n = S_NL; 1615 while(1) 1616 { 1617 if(n!=S_NL) 1618 { 1619 /* skip over regular characters */ 1620 while((n=STATE(state,c))==0); 1621 } 1622 if(n==S_EOF || !(c=fcget())) 1623 { 1624 if(!lexd.dolparen && (c=(fcseek(0)-1)-bufp)) 1625 { 1626 if(n==S_ESC) 1627 c--; 1628 if((c=sfwrite(sp,bufp,c))>0) 1629 iop->iosize += c; 1630 } 1631 if((c=lexfill())<=0) 1632 break; 1633 if(n==S_ESC) 1634 { 1635 #if SHOPT_CRNL 1636 if(c=='\r' && (c=fcget())!=NL) 1637 fcseek(-1); 1638 #endif /* SHOPT_CRNL */ 1639 if(c==NL) 1640 fcseek(1); 1641 else 1642 sfputc(sp,'\\'); 1643 } 1644 bufp = fcseek(-1); 1645 } 1646 else 1647 fcseek(-1); 1648 switch(n) 1649 { 1650 case S_NL: 1651 shlex.sh->inlineno++; 1652 if((stripcol && c==' ') || (stripflg && c=='\t')) 1653 { 1654 if(!lexd.dolparen) 1655 { 1656 /* write out line */ 1657 n = fcseek(0)-bufp; 1658 if((n=sfwrite(sp,bufp,n))>0) 1659 iop->iosize += n; 1660 } 1661 /* skip over tabs */ 1662 if(stripcol) 1663 { 1664 int col=0; 1665 do 1666 { 1667 fcgetc(c); 1668 if(c==' ') 1669 col++; 1670 else 1671 col += 8 - col%8; 1672 if(col>stripcol) 1673 break; 1674 } 1675 while (c==' ' || c=='\t'); 1676 } 1677 else while(c=='\t') 1678 fcgetc(c); 1679 if(c<=0) 1680 goto done; 1681 bufp = fcseek(-1); 1682 } 1683 if(c!=iop->iodelim[0]) 1684 break; 1685 cp = fcseek(0); 1686 nsave = n = 0; 1687 while(1) 1688 { 1689 if(!(c=fcget())) 1690 { 1691 if(!lexd.dolparen && (c=cp-bufp)) 1692 { 1693 if((c=sfwrite(sp,cp=bufp,c))>0) 1694 iop->iosize+=c; 1695 } 1696 nsave = n; 1697 if((c=lexfill())<=0) 1698 { 1699 c = iop->iodelim[n]==0; 1700 goto done; 1701 } 1702 } 1703 #if SHOPT_CRNL 1704 if(c=='\r' && (c=fcget())!=NL) 1705 { 1706 if(c) 1707 fcseek(-1); 1708 c='\r'; 1709 } 1710 #endif /* SHOPT_CRNL */ 1711 if(c==NL) 1712 shlex.sh->inlineno++; 1713 if(iop->iodelim[n]==0 && (c==NL||c==RPAREN)) 1714 { 1715 if(!lexd.dolparen && (n=cp-bufp)) 1716 { 1717 if((n=sfwrite(sp,bufp,n))>0) 1718 iop->iosize += n; 1719 } 1720 shlex.sh->inlineno--; 1721 if(c==RPAREN) 1722 fcseek(-1); 1723 goto done; 1724 } 1725 if(iop->iodelim[n++]!=c) 1726 { 1727 /* 1728 * The match for delimiter failed. 1729 * nsave>0 only when a buffer boundary 1730 * was crossed while checking the 1731 * delimiter 1732 */ 1733 if(!lexd.dolparen && nsave>0) 1734 { 1735 if((n=sfwrite(sp,bufp,nsave))>0) 1736 iop->iosize += n; 1737 bufp = fcfirst(); 1738 } 1739 if(c==NL) 1740 fcseek(-1); 1741 break; 1742 } 1743 } 1744 break; 1745 case S_ESC: 1746 n=1; 1747 #if SHOPT_CRNL 1748 if(c=='\r') 1749 { 1750 fcseek(1); 1751 if(c=fcget()) 1752 fcseek(-1); 1753 if(c==NL) 1754 n=2; 1755 else 1756 { 1757 special++; 1758 break; 1759 } 1760 } 1761 #endif /* SHOPT_CRNL */ 1762 if(c==NL) 1763 { 1764 /* new-line joining */ 1765 shlex.sh->inlineno++; 1766 if(!lexd.dolparen && (n=(fcseek(0)-bufp)-n)>0) 1767 { 1768 if((n=sfwrite(sp,bufp,n))>0) 1769 iop->iosize += n; 1770 bufp = fcseek(0)+1; 1771 } 1772 } 1773 else 1774 special++; 1775 fcget(); 1776 break; 1777 1778 case S_GRAVE: 1779 case S_DOL: 1780 special++; 1781 break; 1782 } 1783 n=0; 1784 } 1785 done: 1786 shlex.sh->funlog = funlog; 1787 if(lexd.dolparen) 1788 free((void*)iop); 1789 else if(!special) 1790 iop->iofile |= IOQUOTE; 1791 return(c); 1792 } 1793 1794 /* 1795 * generates string for given token 1796 */ 1797 static char *fmttoken(Lex_t *lp, register int sym, char *tok) 1798 { 1799 if(sym < 0) 1800 return((char*)sh_translate(e_lexzerobyte)); 1801 if(sym==0) 1802 return(shlex.arg?shlex.arg->argval:"?"); 1803 if(lex.intest && shlex.arg && *shlex.arg->argval) 1804 return(shlex.arg->argval); 1805 if(sym&SYMRES) 1806 { 1807 register const Shtable_t *tp=shtab_reserved; 1808 while(tp->sh_number && tp->sh_number!=sym) 1809 tp++; 1810 return((char*)tp->sh_name); 1811 } 1812 if(sym==EOFSYM) 1813 return((char*)sh_translate(e_endoffile)); 1814 if(sym==NL) 1815 return((char*)sh_translate(e_newline)); 1816 tok[0] = sym; 1817 if(sym&SYMREP) 1818 tok[1] = sym; 1819 else 1820 { 1821 switch(sym&SYMMASK) 1822 { 1823 case SYMAMP: 1824 sym = '&'; 1825 break; 1826 case SYMPIPE: 1827 sym = '|'; 1828 break; 1829 case SYMGT: 1830 sym = '>'; 1831 break; 1832 case SYMLPAR: 1833 sym = LPAREN; 1834 break; 1835 case SYMSHARP: 1836 sym = '#'; 1837 break; 1838 default: 1839 sym = 0; 1840 } 1841 tok[1] = sym; 1842 } 1843 tok[2] = 0; 1844 return(tok); 1845 } 1846 1847 /* 1848 * print a bad syntax message 1849 */ 1850 1851 void sh_syntax(void) 1852 { 1853 register Shell_t *shp = sh_getinterp(); 1854 register const char *cp = sh_translate(e_unexpected); 1855 register char *tokstr; 1856 register Lex_t *lp = (Lex_t*)shp->lex_context; 1857 register int tok = shlex.token; 1858 char tokbuf[3]; 1859 Sfio_t *sp; 1860 if((tok==EOFSYM) && shlex.lasttok) 1861 { 1862 tok = shlex.lasttok; 1863 cp = sh_translate(e_unmatched); 1864 } 1865 else 1866 shlex.lastline = shp->inlineno; 1867 tokstr = fmttoken(lp,tok,tokbuf); 1868 if((sp=fcfile()) || (shp->infd>=0 && (sp=shp->sftable[shp->infd]))) 1869 { 1870 /* clear out any pending input */ 1871 register Sfio_t *top; 1872 while(fcget()>0); 1873 fcclose(); 1874 while(top=sfstack(sp,SF_POPSTACK)) 1875 sfclose(top); 1876 } 1877 else 1878 fcclose(); 1879 shp->inlineno = shlex.inlineno; 1880 shp->st.firstline = shlex.firstline; 1881 #if KSHELL 1882 if(!sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_PROFILE)) 1883 #else 1884 if(shp->inlineno!=1) 1885 #endif 1886 errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax1,shlex.lastline,tokstr,cp); 1887 else 1888 errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax2,tokstr,cp); 1889 } 1890 1891 static char *stack_shift(register char *sp,char *dp) 1892 { 1893 register char *ep; 1894 register int offset = staktell(); 1895 register int left = offset-(sp-stakptr(0)); 1896 register int shift = (dp+1-sp); 1897 offset += shift; 1898 stakseek(offset); 1899 sp = stakptr(offset); 1900 ep = sp - shift; 1901 while(left--) 1902 *--sp = *--ep; 1903 return(sp); 1904 } 1905 1906 /* 1907 * Assumes that current word is unfrozen on top of the stak 1908 * If <mode> is zero, gets rid of quoting and consider argument as string 1909 * and returns pointer to frozen arg 1910 * If mode==1, just replace $"..." strings with international strings 1911 * The result is left on the stak 1912 * If mode==2, the each $"" string is printed on standard output 1913 */ 1914 struct argnod *sh_endword(int mode) 1915 { 1916 register const char *state = sh_lexstates[ST_NESTED]; 1917 register int n; 1918 register char *sp,*dp; 1919 register int inquote=0, inlit=0; /* set within quoted strings */ 1920 struct argnod* argp=0; 1921 char *ep=0, *xp=0; 1922 int bracket=0; 1923 stakputc(0); 1924 sp = stakptr(ARGVAL); 1925 #if SHOPT_MULTIBYTE 1926 if(mbwide()) 1927 { 1928 do 1929 { 1930 int len; 1931 switch(len = mbsize(sp)) 1932 { 1933 case -1: /* illegal multi-byte char */ 1934 case 0: 1935 case 1: 1936 n=state[*sp++]; 1937 break; 1938 default: 1939 /* 1940 * None of the state tables contain 1941 * entries for multibyte characters, 1942 * however, they should be treated 1943 * the same as any other alph 1944 * character. Therefore, we'll use 1945 * the state of the 'a' character. 1946 */ 1947 n=state['a']; 1948 sp += len; 1949 } 1950 } 1951 while(n == 0); 1952 } 1953 else 1954 #endif /* SHOPT_MULTIBYTE */ 1955 while((n=state[*sp++])==0); 1956 dp = sp; 1957 if(mode<0) 1958 inquote = 1; 1959 while(1) 1960 { 1961 switch(n) 1962 { 1963 case S_EOF: 1964 stakseek(dp-stakptr(0)); 1965 if(mode<=0) 1966 { 1967 argp = (struct argnod*)stakfreeze(0); 1968 argp->argflag = ARG_RAW|ARG_QUOTED; 1969 } 1970 return(argp); 1971 case S_LIT: 1972 if(!(inquote&1)) 1973 { 1974 inlit = !inlit; 1975 if(mode==0 || (mode<0 && bracket)) 1976 { 1977 dp--; 1978 if(ep) 1979 { 1980 *dp = 0; 1981 dp = ep+stresc(ep); 1982 } 1983 ep = 0; 1984 } 1985 } 1986 break; 1987 case S_QUOTE: 1988 if(mode<0 && !bracket) 1989 break; 1990 if(!inlit) 1991 { 1992 if(mode<=0) 1993 dp--; 1994 inquote = inquote^1; 1995 if(ep) 1996 { 1997 char *msg; 1998 if(mode==2) 1999 { 2000 sfprintf(sfstdout,"%.*s\n",dp-ep,ep); 2001 ep = 0; 2002 break; 2003 } 2004 *--dp = 0; 2005 #if ERROR_VERSION >= 20000317L 2006 msg = ERROR_translate(0,error_info.id,0,ep); 2007 #else 2008 # if ERROR_VERSION >= 20000101L 2009 msg = ERROR_translate(error_info.id,ep); 2010 # else 2011 msg = ERROR_translate(ep,2); 2012 # endif 2013 #endif 2014 n = strlen(msg); 2015 dp = ep+n; 2016 if(sp-dp <= 1) 2017 { 2018 sp = stack_shift(sp,dp); 2019 dp = sp-1; 2020 ep = dp-n; 2021 } 2022 memmove(ep,msg,n); 2023 *dp++ = '"'; 2024 } 2025 ep = 0; 2026 } 2027 break; 2028 case S_DOL: /* check for $'...' and $"..." */ 2029 if(inlit) 2030 break; 2031 if(*sp==LPAREN || *sp==LBRACE) 2032 { 2033 inquote <<= 1; 2034 break; 2035 } 2036 if(inquote&1) 2037 break; 2038 if(*sp=='\'' || *sp=='"') 2039 { 2040 if(*sp=='"') 2041 inquote |= 1; 2042 else 2043 inlit = 1; 2044 sp++; 2045 if((mode==0||(mode<0&&bracket)) || (inquote&1)) 2046 { 2047 if(mode==2) 2048 ep = dp++; 2049 else if(mode==1) 2050 (ep=dp)[-1] = '"'; 2051 else 2052 ep = --dp; 2053 } 2054 } 2055 break; 2056 case S_ESC: 2057 #if SHOPT_CRNL 2058 if(*sp=='\r' && sp[1]=='\n') 2059 sp++; 2060 #endif /* SHOPT_CRNL */ 2061 if(inlit || mode>0) 2062 { 2063 if(mode<0) 2064 { 2065 if(dp>=sp) 2066 { 2067 sp = stack_shift(sp,dp+1); 2068 dp = sp-2; 2069 } 2070 *dp++ = '\\'; 2071 } 2072 if(ep) 2073 *dp++ = *sp++; 2074 break; 2075 } 2076 n = *sp; 2077 #if SHOPT_DOS 2078 if(!(inquote&1) && sh_lexstates[ST_NORM][n]==0) 2079 break; 2080 #endif /* SHOPT_DOS */ 2081 if(!(inquote&1) || (sh_lexstates[ST_QUOTE][n] && n!=RBRACE)) 2082 { 2083 if(n=='\n') 2084 dp--; 2085 else 2086 dp[-1] = n; 2087 sp++; 2088 } 2089 break; 2090 case S_POP: 2091 if(sp[-1]!=RBRACT) 2092 break; 2093 if(!inlit && !(inquote&1)) 2094 { 2095 inquote >>= 1; 2096 if(xp) 2097 dp = sh_checkid(xp,dp); 2098 xp = 0; 2099 if(--bracket<=0 && mode<0) 2100 inquote = 1; 2101 } 2102 else if((inlit||inquote) && mode<0) 2103 { 2104 dp[-1] = '\\'; 2105 if(dp>=sp) 2106 { 2107 sp = stack_shift(sp,dp); 2108 dp = sp-1; 2109 } 2110 *dp++ = ']'; 2111 } 2112 break; 2113 case S_BRACT: 2114 if(dp[-2]=='.') 2115 xp = dp; 2116 if(mode<0) 2117 { 2118 if(inlit || (bracket&&inquote)) 2119 { 2120 dp[-1] = '\\'; 2121 if(dp>=sp) 2122 { 2123 sp = stack_shift(sp,dp); 2124 dp = sp-1; 2125 } 2126 *dp++ = '['; 2127 } 2128 else if(bracket++==0) 2129 inquote = 0; 2130 } 2131 break; 2132 } 2133 #if SHOPT_MULTIBYTE 2134 if(mbwide()) 2135 { 2136 do 2137 { 2138 int len; 2139 switch(len = mbsize(sp)) 2140 { 2141 case -1: /* illegal multi-byte char */ 2142 case 0: 2143 case 1: 2144 n=state[*dp++ = *sp++]; 2145 break; 2146 default: 2147 /* 2148 * None of the state tables contain 2149 * entries for multibyte characters, 2150 * however, they should be treated 2151 * the same as any other alph 2152 * character. Therefore, we'll use 2153 * the state of the 'a' character. 2154 */ 2155 while(len--) 2156 *dp++ = *sp++; 2157 n=state['a']; 2158 } 2159 } 2160 while(n == 0); 2161 } 2162 else 2163 #endif /* SHOPT_MULTIBYTE */ 2164 while((n=state[*dp++ = *sp++])==0); 2165 } 2166 } 2167 2168 struct alias 2169 { 2170 Sfdisc_t disc; 2171 Namval_t *np; 2172 int nextc; 2173 int line; 2174 char buf[2]; 2175 Lex_t *lp; 2176 }; 2177 2178 /* 2179 * This code gets called whenever an end of string is found with alias 2180 */ 2181 2182 #ifndef SF_ATEXIT 2183 # define SF_ATEXIT 0 2184 #endif 2185 /* 2186 * This code gets called whenever an end of string is found with alias 2187 */ 2188 #ifdef SF_BUFCONST 2189 static int alias_exceptf(Sfio_t *iop,int type,void *data, Sfdisc_t *handle) 2190 #else 2191 static int alias_exceptf(Sfio_t *iop,int type,Sfdisc_t *handle) 2192 #endif 2193 { 2194 register struct alias *ap = (struct alias*)handle; 2195 register Namval_t *np; 2196 register Lex_t *lp; 2197 if(type==0 || type==SF_ATEXIT || !ap) 2198 return(0); 2199 lp = ap->lp; 2200 np = ap->np; 2201 if(type!=SF_READ) 2202 { 2203 if(type==SF_CLOSING) 2204 { 2205 register Sfdisc_t *dp = sfdisc(iop,SF_POPDISC); 2206 if(dp!=handle) 2207 sfdisc(iop,dp); 2208 } 2209 else if(type==SF_FINAL) 2210 free((void*)ap); 2211 goto done; 2212 } 2213 if(ap->nextc) 2214 { 2215 /* if last character is a blank, then next work can be alias */ 2216 register int c = fcpeek(-1); 2217 if(isblank(c)) 2218 shlex.aliasok = 1; 2219 *ap->buf = ap->nextc; 2220 ap->nextc = 0; 2221 sfsetbuf(iop,ap->buf,1); 2222 return(1); 2223 } 2224 done: 2225 if(np) 2226 nv_offattr(np,NV_NOEXPAND); 2227 return(0); 2228 } 2229 2230 2231 static void setupalias(Lex_t *lp, const char *string,Namval_t *np) 2232 { 2233 register Sfio_t *iop, *base; 2234 struct alias *ap = (struct alias*)malloc(sizeof(struct alias)); 2235 ap->disc = alias_disc; 2236 ap->lp = lp; 2237 ap->buf[1] = 0; 2238 if(ap->np = np) 2239 { 2240 #if SHOPT_KIA 2241 if(shlex.kiafile) 2242 { 2243 unsigned long r; 2244 r=kiaentity(nv_name(np),-1,'p',0,0,shlex.current,'a',0,""); 2245 sfprintf(shlex.kiatmp,"p;%..64d;p;%..64d;%d;%d;e;\n",shlex.current,r,shlex.sh->inlineno,shlex.sh->inlineno); 2246 } 2247 #endif /* SHOPT_KIA */ 2248 if((ap->nextc=fcget())==0) 2249 ap->nextc = ' '; 2250 } 2251 else 2252 ap->nextc = 0; 2253 iop = sfopen(NIL(Sfio_t*),(char*)string,"s"); 2254 sfdisc(iop, &ap->disc); 2255 lexd.nocopy++; 2256 if(!(base=fcfile())) 2257 base = sfopen(NIL(Sfio_t*),fcseek(0),"s"); 2258 fcclose(); 2259 sfstack(base,iop); 2260 fcfopen(base); 2261 lexd.nocopy--; 2262 } 2263 2264 /* 2265 * grow storage stack for nested constructs by STACK_ARRAY 2266 */ 2267 static int stack_grow(Lex_t *lp) 2268 { 2269 lexd.lex_max += STACK_ARRAY; 2270 if(lexd.lex_match) 2271 lexd.lex_match = (int*)realloc((char*)lexd.lex_match,sizeof(int)*lexd.lex_max); 2272 else 2273 lexd.lex_match = (int*)malloc(sizeof(int)*STACK_ARRAY); 2274 return(lexd.lex_match!=0); 2275 } 2276 2277