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