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 if(lp->lexd.warn) 1086 errormsg(SH_DICT,ERROR_warn(0),e_lexnested,shp->inlineno); 1087 if(!(state=lp->lexd.first)) 1088 state = fcfirst(); 1089 fcseek(state-fcseek(0)); 1090 if(lp->arg) 1091 { 1092 lp->arg = (struct argnod*)stkfreeze(stkp,1); 1093 setupalias(lp,lp->arg->argval,NIL(Namval_t*)); 1094 } 1095 lp->lexd.paren = 1; 1096 } 1097 return(lp->token=LPAREN); 1098 } 1099 if(mode==ST_NONE) 1100 return(0); 1101 if(c!=n) 1102 { 1103 lp->token = c; 1104 sh_syntax(lp); 1105 } 1106 if(c==RBRACE && (mode==ST_NAME||mode==ST_NORM)) 1107 goto epat; 1108 continue; 1109 case S_EQ: 1110 assignment = lp->assignok; 1111 /* FALL THRU */ 1112 case S_COLON: 1113 if(assignment) 1114 { 1115 if((c=fcget())=='~') 1116 wordflags |= ARG_MAC; 1117 else if(c!=LPAREN && assignment==SH_COMPASSIGN) 1118 assignment = 0; 1119 fcseek(-1); 1120 } 1121 break; 1122 case S_LABEL: 1123 if(lp->lex.reservok && !lp->lex.incase) 1124 { 1125 c = fcget(); 1126 fcseek(-1); 1127 if(state[c]==S_BREAK) 1128 { 1129 assignment = -1; 1130 goto breakloop; 1131 } 1132 } 1133 break; 1134 case S_BRACT: 1135 /* check for possible subscript */ 1136 if((n=endchar(lp))==RBRACT || n==RPAREN || 1137 (mode==ST_BRACE) || 1138 (oldmode(lp)==ST_NONE) || 1139 (mode==ST_NAME && (lp->assignok||lp->lexd.level))) 1140 { 1141 if(mode==ST_NAME) 1142 { 1143 fcgetc(n); 1144 if(n>0) 1145 { 1146 if(n==']') 1147 errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax1, shp->inlineno, "[]", "empty subscript"); 1148 fcseek(-1); 1149 } 1150 } 1151 pushlevel(lp,RBRACT,mode); 1152 wordflags |= ARG_QUOTED; 1153 mode = ST_NESTED; 1154 continue; 1155 } 1156 wordflags |= ARG_EXP; 1157 break; 1158 case S_BRACE: 1159 { 1160 int isfirst; 1161 if(lp->lexd.dolparen) 1162 { 1163 if(mode==ST_BEGIN && (lp->lex.reservok||lp->comsub)) 1164 { 1165 fcgetc(n); 1166 if(n>0) 1167 fcseek(-1); 1168 else 1169 n = '\n'; 1170 if(n==RBRACT || sh_lexstates[ST_NORM][n]) 1171 return(lp->token=c); 1172 } 1173 break; 1174 } 1175 else if(mode==ST_BEGIN) 1176 { 1177 if(lp->comsub && c==RBRACE) 1178 return(lp->token=c); 1179 goto do_reg; 1180 } 1181 isfirst = (lp->lexd.first&&fcseek(0)==lp->lexd.first+1); 1182 fcgetc(n); 1183 /* check for {} */ 1184 if(c==LBRACE && n==RBRACE) 1185 break; 1186 if(n>0) 1187 fcseek(-1); 1188 else if(lp->lex.reservok) 1189 break; 1190 /* check for reserved word { or } */ 1191 if(lp->lex.reservok && state[n]==S_BREAK && isfirst) 1192 break; 1193 if(sh_isoption(SH_BRACEEXPAND) && c==LBRACE && !assignment && state[n]!=S_BREAK 1194 && !lp->lex.incase && !lp->lex.intest 1195 && !lp->lex.skipword) 1196 { 1197 wordflags |= ARG_EXP; 1198 } 1199 if(c==RBRACE && n==LPAREN) 1200 goto epat; 1201 break; 1202 } 1203 case S_PAT: 1204 wordflags |= ARG_EXP; 1205 /* FALL THRU */ 1206 case S_EPAT: 1207 epat: 1208 if(fcgetc(n)==LPAREN) 1209 { 1210 if(lp->lex.incase==TEST_RE) 1211 { 1212 lp->lex.incase++; 1213 pushlevel(lp,RPAREN,ST_NORM); 1214 mode = ST_NESTED; 1215 } 1216 wordflags |= ARG_EXP; 1217 pushlevel(lp,RPAREN,mode); 1218 mode = ST_NESTED; 1219 continue; 1220 } 1221 if(n>0) 1222 fcseek(-1); 1223 if(n=='=' && c=='+' && mode==ST_NAME) 1224 continue; 1225 break; 1226 } 1227 lp->comp_assign = 0; 1228 if(mode==ST_NAME) 1229 mode = ST_NORM; 1230 else if(mode==ST_NONE) 1231 return(0); 1232 } 1233 breakloop: 1234 if(lp->lexd.nocopy) 1235 { 1236 lp->lexd.balance = 0; 1237 return(0); 1238 } 1239 if(lp->lexd.dolparen) 1240 { 1241 lp->lexd.balance = 0; 1242 if(lp->lexd.docword) 1243 nested_here(lp); 1244 lp->lexd.message = (wordflags&ARG_MESSAGE); 1245 return(lp->token=0); 1246 } 1247 if(!(state=lp->lexd.first)) 1248 state = fcfirst(); 1249 n = fcseek(0)-(char*)state; 1250 if(!lp->arg) 1251 lp->arg = (struct argnod*)stkseek(stkp,ARGVAL); 1252 if(n>0) 1253 sfwrite(stkp,state,n); 1254 /* add balancing character if necessary */ 1255 if(lp->lexd.balance) 1256 { 1257 sfputc(stkp,lp->lexd.balance); 1258 lp->lexd.balance = 0; 1259 } 1260 sfputc(stkp,0); 1261 stkseek(stkp,stktell(stkp)-1); 1262 state = stkptr(stkp,ARGVAL); 1263 n = stktell(stkp)-ARGVAL; 1264 lp->lexd.first=0; 1265 if(n==1) 1266 { 1267 /* check for numbered redirection */ 1268 n = state[0]; 1269 if((c=='<' || c=='>') && isadigit(n)) 1270 { 1271 c = sh_lex(lp); 1272 lp->digits = (n-'0'); 1273 return(c); 1274 } 1275 if(n==LBRACT) 1276 c = 0; 1277 else if(n==RBRACE && lp->comsub) 1278 return(lp->token=n); 1279 else if(n=='~') 1280 c = ARG_MAC; 1281 else 1282 c = (wordflags&ARG_EXP); 1283 n = 1; 1284 } 1285 else if(n>2 && state[0]=='{' && state[n-1]=='}' && !lp->lex.intest && !lp->lex.incase && (c=='<' || c== '>') && sh_isoption(SH_BRACEEXPAND)) 1286 { 1287 if(!strchr(state,',')) 1288 { 1289 stkseek(stkp,stktell(stkp)-1); 1290 lp->arg = (struct argnod*)stkfreeze(stkp,1); 1291 return(lp->token=IOVNAME); 1292 } 1293 c = wordflags; 1294 } 1295 else 1296 c = wordflags; 1297 if(assignment<0) 1298 { 1299 stkseek(stkp,stktell(stkp)-1); 1300 lp->arg = (struct argnod*)stkfreeze(stkp,1); 1301 lp->lex.reservok = 1; 1302 return(lp->token=LABLSYM); 1303 } 1304 if(assignment || (lp->lex.intest&&!lp->lex.incase) || mode==ST_NONE) 1305 c &= ~ARG_EXP; 1306 if((c&ARG_EXP) && (c&ARG_QUOTED)) 1307 c |= ARG_MAC; 1308 if(mode==ST_NONE) 1309 { 1310 /* eliminate trailing )) */ 1311 stkseek(stkp,stktell(stkp)-2); 1312 } 1313 if(c&ARG_MESSAGE) 1314 { 1315 if(sh_isoption(SH_DICTIONARY)) 1316 lp->arg = sh_endword(shp,2); 1317 if(!sh_isoption(SH_NOEXEC)) 1318 { 1319 lp->arg = sh_endword(shp,1); 1320 c &= ~ARG_MESSAGE; 1321 } 1322 } 1323 if(c==0 || (c&(ARG_MAC|ARG_EXP)) || (lp->lexd.warn && !lp->lexd.docword)) 1324 { 1325 lp->arg = (struct argnod*)stkfreeze(stkp,1); 1326 lp->arg->argflag = (c?c:ARG_RAW); 1327 } 1328 else if(mode==ST_NONE) 1329 lp->arg = sh_endword(shp,-1); 1330 else 1331 lp->arg = sh_endword(shp,0); 1332 state = lp->arg->argval; 1333 lp->comp_assign = assignment; 1334 if(assignment) 1335 lp->arg->argflag |= ARG_ASSIGN; 1336 else if(!lp->lex.skipword) 1337 lp->assignok = 0; 1338 lp->arg->argchn.cp = 0; 1339 lp->arg->argnxt.ap = 0; 1340 if(mode==ST_NONE) 1341 return(lp->token=EXPRSYM); 1342 if(lp->lex.intest) 1343 { 1344 if(lp->lex.testop1) 1345 { 1346 lp->lex.testop1 = 0; 1347 if(n==2 && state[0]=='-' && state[2]==0 && 1348 strchr(test_opchars,state[1])) 1349 { 1350 if(lp->lexd.warn && state[1]=='a') 1351 errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete2,shp->inlineno); 1352 lp->digits = state[1]; 1353 lp->token = TESTUNOP; 1354 } 1355 else if(n==1 && state[0]=='!' && state[1]==0) 1356 { 1357 lp->lex.testop1 = 1; 1358 lp->token = '!'; 1359 } 1360 else 1361 { 1362 lp->lex.testop2 = 1; 1363 lp->token = 0; 1364 } 1365 return(lp->token); 1366 } 1367 lp->lex.incase = 0; 1368 c = sh_lookup(state,shtab_testops); 1369 switch(c) 1370 { 1371 case TEST_END: 1372 lp->lex.testop2 = lp->lex.intest = 0; 1373 lp->lex.reservok = 1; 1374 lp->token = ETESTSYM; 1375 return(lp->token); 1376 1377 case TEST_SEQ: 1378 if(lp->lexd.warn && state[1]==0) 1379 errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete3,shp->inlineno); 1380 /* FALL THRU */ 1381 default: 1382 if(lp->lex.testop2) 1383 { 1384 if(lp->lexd.warn && (c&TEST_ARITH)) 1385 errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete4,shp->inlineno,state); 1386 if(c&TEST_PATTERN) 1387 lp->lex.incase = 1; 1388 else if(c==TEST_REP) 1389 lp->lex.incase = TEST_RE; 1390 lp->lex.testop2 = 0; 1391 lp->digits = c; 1392 lp->token = TESTBINOP; 1393 return(lp->token); 1394 } 1395 1396 case TEST_OR: case TEST_AND: 1397 case 0: 1398 return(lp->token=0); 1399 } 1400 } 1401 if(lp->lex.reservok /* && !lp->lex.incase*/ && n<=2) 1402 { 1403 /* check for {, }, ! */ 1404 c = state[0]; 1405 if(n==1 && (c=='{' || c=='}' || c=='!')) 1406 { 1407 if(lp->lexd.warn && c=='{' && lp->lex.incase==2) 1408 errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete6,shp->inlineno); 1409 if(lp->lex.incase==1 && c==RBRACE) 1410 lp->lex.incase = 0; 1411 return(lp->token=c); 1412 } 1413 else if(!lp->lex.incase && c==LBRACT && state[1]==LBRACT) 1414 { 1415 lp->lex.intest = lp->lex.testop1 = 1; 1416 lp->lex.testop2 = lp->lex.reservok = 0; 1417 return(lp->token=BTESTSYM); 1418 } 1419 } 1420 c = 0; 1421 if(!lp->lex.skipword) 1422 { 1423 if(n>1 && lp->lex.reservok==1 && mode==ST_NAME && 1424 (c=sh_lookup(state,shtab_reserved))) 1425 { 1426 if(lp->lex.incase) 1427 { 1428 if(lp->lex.incase >1) 1429 lp->lex.incase = 1; 1430 else if(c==ESACSYM) 1431 lp->lex.incase = 0; 1432 else 1433 c = 0; 1434 } 1435 else if(c==FORSYM || c==CASESYM || c==SELECTSYM || c==FUNCTSYM || c==NSPACESYM) 1436 { 1437 lp->lex.skipword = 1; 1438 lp->lex.incase = 2*(c==CASESYM); 1439 } 1440 else 1441 lp->lex.skipword = 0; 1442 if(c==INSYM) 1443 lp->lex.reservok = 0; 1444 else if(c==TIMESYM) 1445 { 1446 /* yech - POSIX requires time -p */ 1447 while(fcgetc(n)==' ' || n=='\t'); 1448 if(n>0) 1449 fcseek(-1); 1450 if(n=='-') 1451 c=0; 1452 } 1453 return(lp->token=c); 1454 } 1455 if(!(wordflags&ARG_QUOTED) && (lp->lex.reservok||lp->aliasok)) 1456 { 1457 /* check for aliases */ 1458 Namval_t* np; 1459 if(!lp->lex.incase && !assignment && fcpeek(0)!=LPAREN && 1460 (np=nv_search(state,shp->alias_tree,HASH_SCOPE)) 1461 && !nv_isattr(np,NV_NOEXPAND) 1462 #if KSHELL 1463 && (!sh_isstate(SH_NOALIAS) || nv_isattr(np,NV_NOFREE)) 1464 #endif /* KSHELL */ 1465 && (state=nv_getval(np))) 1466 { 1467 setupalias(lp,state,np); 1468 nv_onattr(np,NV_NOEXPAND); 1469 lp->lex.reservok = 1; 1470 lp->assignok |= lp->lex.reservok; 1471 return(sh_lex(lp)); 1472 } 1473 } 1474 lp->lex.reservok = 0; 1475 } 1476 lp->lex.skipword = lp->lexd.docword = 0; 1477 return(lp->token=c); 1478 } 1479 1480 /* 1481 * read to end of command substitution 1482 */ 1483 static int comsub(register Lex_t *lp, int endtok) 1484 { 1485 register int n,c,count=1; 1486 register int line=lp->sh->inlineno; 1487 char word[5]; 1488 int off, messages=0, assignok=lp->assignok, csub; 1489 struct lexstate save; 1490 save = lp->lex; 1491 csub = lp->comsub; 1492 sh_lexopen(lp,lp->sh,1); 1493 lp->lexd.dolparen++; 1494 lp->lex.incase=0; 1495 pushlevel(lp,0,0); 1496 lp->comsub = (endtok==LBRACE); 1497 off = fcseek(0) - lp->lexd.first; 1498 if(sh_lex(lp)==endtok) 1499 { 1500 if(endtok==LPAREN && fcseek(0)==lp->lexd.first) 1501 { 1502 count++; 1503 lp->lexd.paren = 0; 1504 fcseek(off+2); 1505 } 1506 while(1) 1507 { 1508 /* look for case and esac */ 1509 n=0; 1510 while(1) 1511 { 1512 fcgetc(c); 1513 /* skip leading white space */ 1514 if(n==0 && !sh_lexstates[ST_BEGIN][c]) 1515 continue; 1516 if(n==4) 1517 break; 1518 if(sh_lexstates[ST_NAME][c]) 1519 goto skip; 1520 word[n++] = c; 1521 } 1522 if(sh_lexstates[ST_NAME][c]==S_BREAK) 1523 { 1524 if(memcmp(word,"case",4)==0) 1525 lp->lex.incase=1; 1526 else if(memcmp(word,"esac",4)==0) 1527 lp->lex.incase=0; 1528 } 1529 skip: 1530 if(c && (c!='#' || n==0)) 1531 fcseek(-1); 1532 if(c==RBRACE && lp->lex.incase) 1533 lp->lex.incase=0; 1534 switch(c=sh_lex(lp)) 1535 { 1536 case LBRACE: 1537 if(endtok==LBRACE && !lp->lex.incase) 1538 { 1539 lp->comsub = 0; 1540 count++; 1541 } 1542 break; 1543 case RBRACE: 1544 rbrace: 1545 if(endtok==LBRACE && --count<=0) 1546 goto done; 1547 lp->comsub = (count==1); 1548 break; 1549 case IPROCSYM: case OPROCSYM: 1550 case LPAREN: 1551 if(endtok==LPAREN && !lp->lex.incase) 1552 count++; 1553 break; 1554 case RPAREN: 1555 if(lp->lex.incase) 1556 lp->lex.incase=0; 1557 else if(endtok==LPAREN && --count<=0) 1558 goto done; 1559 break; 1560 case EOFSYM: 1561 lp->lastline = line; 1562 lp->lasttok = endtok; 1563 sh_syntax(lp); 1564 case IOSEEKSYM: 1565 if(fcgetc(c)!='#' && c>0) 1566 fcseek(-1); 1567 break; 1568 case IODOCSYM: 1569 lp->lexd.docextra = 0; 1570 sh_lex(lp); 1571 break; 1572 case 0: 1573 lp->lex.reservok = 0; 1574 messages |= lp->lexd.message; 1575 break; 1576 case ';': 1577 fcgetc(c); 1578 if(c==RBRACE && endtok==LBRACE) 1579 goto rbrace; 1580 if(c>0) 1581 fcseek(-1); 1582 /* fall through*/ 1583 default: 1584 lp->lex.reservok = 1; 1585 } 1586 } 1587 } 1588 done: 1589 poplevel(lp); 1590 lp->comsub = csub; 1591 lp->lastline = line; 1592 lp->lexd.dolparen--; 1593 lp->lex = save; 1594 lp->assignok = (endchar(lp)==RBRACT?assignok:0); 1595 return(messages); 1596 } 1597 1598 /* 1599 * here-doc nested in $(...) 1600 * allocate ionode with delimiter filled in without disturbing stak 1601 */ 1602 static void nested_here(register Lex_t *lp) 1603 { 1604 register struct ionod *iop; 1605 register int n,offset; 1606 struct argnod *arg = lp->arg; 1607 Stk_t *stkp = lp->sh->stk; 1608 char *base; 1609 if(offset=stktell(stkp)) 1610 base = stkfreeze(stkp,0); 1611 n = fcseek(0)-lp->lexd.docend; 1612 iop = newof(0,struct ionod,1,lp->lexd.docextra+n+ARGVAL); 1613 iop->iolst = lp->heredoc; 1614 stkseek(stkp,ARGVAL); 1615 if(lp->lexd.docextra) 1616 { 1617 sfseek(lp->sh->strbuf,(Sfoff_t)0, SEEK_SET); 1618 sfmove(lp->sh->strbuf,stkp,lp->lexd.docextra,-1); 1619 } 1620 sfwrite(stkp,lp->lexd.docend,n); 1621 lp->arg = sh_endword(lp->sh,0); 1622 iop->ioname = (char*)(iop+1); 1623 strcpy(iop->ioname,lp->arg->argval); 1624 iop->iofile = (IODOC|IORAW); 1625 if(lp->lexd.docword>1) 1626 iop->iofile |= IOSTRIP; 1627 lp->heredoc = iop; 1628 lp->arg = arg; 1629 lp->lexd.docword = 0; 1630 if(offset) 1631 stkset(stkp,base,offset); 1632 else 1633 stkseek(stkp,0); 1634 } 1635 1636 /* 1637 * skip to <close> character 1638 * if <copy> is non,zero, then the characters are copied to the stack 1639 * <state> is the initial lexical state 1640 */ 1641 void sh_lexskip(Lex_t *lp,int close, register int copy, int state) 1642 { 1643 register char *cp; 1644 lp->lexd.nest = close; 1645 lp->lexd.lex_state = state; 1646 lp->lexd.noarg = 1; 1647 if(copy) 1648 fcnotify(lex_advance,lp); 1649 else 1650 lp->lexd.nocopy++; 1651 sh_lex(lp); 1652 lp->lexd.noarg = 0; 1653 if(copy) 1654 { 1655 fcnotify(0,lp); 1656 if(!(cp=lp->lexd.first)) 1657 cp = fcfirst(); 1658 if((copy = fcseek(0)-cp) > 0) 1659 sfwrite(lp->sh->stk,cp,copy); 1660 } 1661 else 1662 lp->lexd.nocopy--; 1663 } 1664 1665 #if SHOPT_CRNL 1666 ssize_t _sfwrite(Sfio_t *sp, const Void_t *buff, size_t n) 1667 { 1668 const char *cp = (const char*)buff, *next=cp, *ep = cp + n; 1669 int m=0,k; 1670 while(next = (const char*)memchr(next,'\r',ep-next)) 1671 if(*++next=='\n') 1672 { 1673 if(k=next-cp-1) 1674 { 1675 if((k=sfwrite(sp,cp,k)) < 0) 1676 return(m>0?m:-1); 1677 m += k; 1678 } 1679 cp = next; 1680 } 1681 if((k=sfwrite(sp,cp,ep-cp)) < 0) 1682 return(m>0?m:-1); 1683 return(m+k); 1684 } 1685 # define sfwrite _sfwrite 1686 #endif /* SHOPT_CRNL */ 1687 1688 /* 1689 * read in here-document from script 1690 * quoted here documents, and here-documents without special chars are 1691 * noted with the IOQUOTE flag 1692 * returns 1 for complete here-doc, 0 for EOF 1693 */ 1694 1695 static int here_copy(Lex_t *lp,register struct ionod *iop) 1696 { 1697 register const char *state; 1698 register int c,n; 1699 register char *bufp,*cp; 1700 register Sfio_t *sp=lp->sh->heredocs, *funlog; 1701 int stripcol=0,stripflg, nsave, special=0; 1702 if(funlog=lp->sh->funlog) 1703 { 1704 if(fcfill()>0) 1705 fcseek(-1); 1706 lp->sh->funlog = 0; 1707 } 1708 if(iop->iolst) 1709 here_copy(lp,iop->iolst); 1710 iop->iooffset = sfseek(sp,(off_t)0,SEEK_END); 1711 iop->iosize = 0; 1712 iop->iodelim=iop->ioname; 1713 /* check for and strip quoted characters in delimiter string */ 1714 if(stripflg=iop->iofile&IOSTRIP) 1715 { 1716 while(*iop->iodelim=='\t') 1717 iop->iodelim++; 1718 /* skip over leading tabs in document */ 1719 if(iop->iofile&IOLSEEK) 1720 { 1721 iop->iofile &= ~IOLSEEK; 1722 while(fcgetc(c)=='\t' || c==' ') 1723 { 1724 if(c==' ') 1725 stripcol++; 1726 else 1727 stripcol += 8 - stripcol%8; 1728 } 1729 } 1730 else 1731 while(fcgetc(c)=='\t'); 1732 if(c>0) 1733 fcseek(-1); 1734 } 1735 if(iop->iofile&IOQUOTE) 1736 state = sh_lexstates[ST_LIT]; 1737 else 1738 state = sh_lexstates[ST_QUOTE]; 1739 bufp = fcseek(0); 1740 n = S_NL; 1741 while(1) 1742 { 1743 if(n!=S_NL) 1744 { 1745 /* skip over regular characters */ 1746 while((n=STATE(state,c))==0); 1747 } 1748 if(n==S_EOF || !(c=fcget())) 1749 { 1750 if(!lp->lexd.dolparen && (c=(fcseek(0)-1)-bufp)) 1751 { 1752 if(n==S_ESC) 1753 c--; 1754 if((c=sfwrite(sp,bufp,c))>0) 1755 iop->iosize += c; 1756 } 1757 if((c=lexfill(lp))<=0) 1758 break; 1759 if(n==S_ESC) 1760 { 1761 #if SHOPT_CRNL 1762 if(c=='\r' && (c=fcget())!=NL) 1763 fcseek(-1); 1764 #endif /* SHOPT_CRNL */ 1765 if(c==NL) 1766 fcseek(1); 1767 else 1768 sfputc(sp,'\\'); 1769 } 1770 bufp = fcseek(-1); 1771 } 1772 else 1773 fcseek(-1); 1774 switch(n) 1775 { 1776 case S_NL: 1777 lp->sh->inlineno++; 1778 if((stripcol && c==' ') || (stripflg && c=='\t')) 1779 { 1780 if(!lp->lexd.dolparen) 1781 { 1782 /* write out line */ 1783 n = fcseek(0)-bufp; 1784 if((n=sfwrite(sp,bufp,n))>0) 1785 iop->iosize += n; 1786 } 1787 /* skip over tabs */ 1788 if(stripcol) 1789 { 1790 int col=0; 1791 do 1792 { 1793 fcgetc(c); 1794 if(c==' ') 1795 col++; 1796 else 1797 col += 8 - col%8; 1798 if(col>stripcol) 1799 break; 1800 } 1801 while (c==' ' || c=='\t'); 1802 } 1803 else while(c=='\t') 1804 fcgetc(c); 1805 if(c<=0) 1806 goto done; 1807 bufp = fcseek(-1); 1808 } 1809 if(c!=iop->iodelim[0]) 1810 break; 1811 cp = fcseek(0); 1812 nsave = n = 0; 1813 while(1) 1814 { 1815 if(!(c=fcget())) 1816 { 1817 if(!lp->lexd.dolparen && (c=cp-bufp)) 1818 { 1819 if((c=sfwrite(sp,cp=bufp,c))>0) 1820 iop->iosize+=c; 1821 } 1822 nsave = n; 1823 if((c=lexfill(lp))<=0) 1824 { 1825 c = iop->iodelim[n]==0; 1826 goto done; 1827 } 1828 } 1829 #if SHOPT_CRNL 1830 if(c=='\r' && (c=fcget())!=NL) 1831 { 1832 if(c) 1833 fcseek(-1); 1834 c='\r'; 1835 } 1836 #endif /* SHOPT_CRNL */ 1837 if(c==NL) 1838 lp->sh->inlineno++; 1839 if(iop->iodelim[n]==0 && (c==NL||c==RPAREN)) 1840 { 1841 if(!lp->lexd.dolparen && (n=cp-bufp)) 1842 { 1843 if((n=sfwrite(sp,bufp,n))>0) 1844 iop->iosize += n; 1845 } 1846 lp->sh->inlineno--; 1847 if(c==RPAREN) 1848 fcseek(-1); 1849 goto done; 1850 } 1851 if(iop->iodelim[n++]!=c) 1852 { 1853 /* 1854 * The match for delimiter failed. 1855 * nsave>0 only when a buffer boundary 1856 * was crossed while checking the 1857 * delimiter 1858 */ 1859 if(!lp->lexd.dolparen && nsave>0) 1860 { 1861 if((n=sfwrite(sp,bufp,nsave))>0) 1862 iop->iosize += n; 1863 bufp = fcfirst(); 1864 } 1865 if(c==NL) 1866 fcseek(-1); 1867 break; 1868 } 1869 } 1870 break; 1871 case S_ESC: 1872 n=1; 1873 #if SHOPT_CRNL 1874 if(c=='\r') 1875 { 1876 fcseek(1); 1877 if(c=fcget()) 1878 fcseek(-1); 1879 if(c==NL) 1880 n=2; 1881 else 1882 { 1883 special++; 1884 break; 1885 } 1886 } 1887 #endif /* SHOPT_CRNL */ 1888 if(c==NL) 1889 { 1890 /* new-line joining */ 1891 lp->sh->inlineno++; 1892 if(!lp->lexd.dolparen && (n=(fcseek(0)-bufp)-n)>=0) 1893 { 1894 if(n && (n=sfwrite(sp,bufp,n))>0) 1895 iop->iosize += n; 1896 bufp = fcseek(0)+1; 1897 } 1898 } 1899 else 1900 special++; 1901 fcget(); 1902 break; 1903 1904 case S_GRAVE: 1905 case S_DOL: 1906 special++; 1907 break; 1908 } 1909 n=0; 1910 } 1911 done: 1912 lp->sh->funlog = funlog; 1913 if(lp->lexd.dolparen) 1914 free((void*)iop); 1915 else if(!special) 1916 iop->iofile |= IOQUOTE; 1917 return(c); 1918 } 1919 1920 /* 1921 * generates string for given token 1922 */ 1923 static char *fmttoken(Lex_t *lp, register int sym, char *tok) 1924 { 1925 int n=1; 1926 if(sym < 0) 1927 return((char*)sh_translate(e_lexzerobyte)); 1928 if(sym==0) 1929 return(lp->arg?lp->arg->argval:"?"); 1930 if(lp->lex.intest && lp->arg && *lp->arg->argval) 1931 return(lp->arg->argval); 1932 if(sym&SYMRES) 1933 { 1934 register const Shtable_t *tp=shtab_reserved; 1935 while(tp->sh_number && tp->sh_number!=sym) 1936 tp++; 1937 return((char*)tp->sh_name); 1938 } 1939 if(sym==EOFSYM) 1940 return((char*)sh_translate(e_endoffile)); 1941 if(sym==NL) 1942 return((char*)sh_translate(e_newline)); 1943 tok[0] = sym; 1944 if(sym&SYMREP) 1945 tok[n++] = sym; 1946 else 1947 { 1948 switch(sym&SYMMASK) 1949 { 1950 case SYMAMP: 1951 sym = '&'; 1952 break; 1953 case SYMPIPE: 1954 sym = '|'; 1955 break; 1956 case SYMGT: 1957 sym = '>'; 1958 break; 1959 case SYMLPAR: 1960 sym = LPAREN; 1961 break; 1962 case SYMSHARP: 1963 sym = '#'; 1964 break; 1965 case SYMSEMI: 1966 if(tok[0]=='<') 1967 tok[n++] = '>'; 1968 sym = ';'; 1969 break; 1970 default: 1971 sym = 0; 1972 } 1973 tok[n++] = sym; 1974 } 1975 tok[n] = 0; 1976 return(tok); 1977 } 1978 1979 /* 1980 * print a bad syntax message 1981 */ 1982 1983 void sh_syntax(Lex_t *lp) 1984 { 1985 register Shell_t *shp = lp->sh; 1986 register const char *cp = sh_translate(e_unexpected); 1987 register char *tokstr; 1988 register int tok = lp->token; 1989 char tokbuf[3]; 1990 Sfio_t *sp; 1991 if((tok==EOFSYM) && lp->lasttok) 1992 { 1993 tok = lp->lasttok; 1994 cp = sh_translate(e_unmatched); 1995 } 1996 else 1997 lp->lastline = shp->inlineno; 1998 tokstr = fmttoken(lp,tok,tokbuf); 1999 if((sp=fcfile()) || (shp->infd>=0 && (sp=shp->sftable[shp->infd]))) 2000 { 2001 /* clear out any pending input */ 2002 register Sfio_t *top; 2003 while(fcget()>0); 2004 fcclose(); 2005 while(top=sfstack(sp,SF_POPSTACK)) 2006 sfclose(top); 2007 } 2008 else 2009 fcclose(); 2010 shp->inlineno = lp->inlineno; 2011 shp->st.firstline = lp->firstline; 2012 #if KSHELL 2013 if(!sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_PROFILE)) 2014 #else 2015 if(shp->inlineno!=1) 2016 #endif 2017 errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax1,lp->lastline,tokstr,cp); 2018 else 2019 errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax2,tokstr,cp); 2020 } 2021 2022 static char *stack_shift(Stk_t *stkp, register char *sp,char *dp) 2023 { 2024 register char *ep; 2025 register int offset = stktell(stkp); 2026 register int left = offset-(sp-stkptr(stkp,0)); 2027 register int shift = (dp+1-sp); 2028 offset += shift; 2029 stkseek(stkp,offset); 2030 sp = stkptr(stkp,offset); 2031 ep = sp - shift; 2032 while(left--) 2033 *--sp = *--ep; 2034 return(sp); 2035 } 2036 2037 /* 2038 * Assumes that current word is unfrozen on top of the stak 2039 * If <mode> is zero, gets rid of quoting and consider argument as string 2040 * and returns pointer to frozen arg 2041 * If mode==1, just replace $"..." strings with international strings 2042 * The result is left on the stak 2043 * If mode==2, the each $"" string is printed on standard output 2044 */ 2045 struct argnod *sh_endword(Shell_t *shp,int mode) 2046 { 2047 register const char *state = sh_lexstates[ST_NESTED]; 2048 register int n; 2049 register char *sp,*dp; 2050 register int inquote=0, inlit=0; /* set within quoted strings */ 2051 struct argnod* argp=0; 2052 char *ep=0, *xp=0; 2053 int bracket=0; 2054 Stk_t *stkp=shp->stk; 2055 sfputc(stkp,0); 2056 sp = stkptr(stkp,ARGVAL); 2057 #if SHOPT_MULTIBYTE 2058 if(mbwide()) 2059 { 2060 do 2061 { 2062 int len; 2063 switch(len = mbsize(sp)) 2064 { 2065 case -1: /* illegal multi-byte char */ 2066 case 0: 2067 case 1: 2068 n=state[*sp++]; 2069 break; 2070 default: 2071 /* 2072 * None of the state tables contain 2073 * entries for multibyte characters, 2074 * however, they should be treated 2075 * the same as any other alph 2076 * character. Therefore, we'll use 2077 * the state of the 'a' character. 2078 */ 2079 n=state['a']; 2080 sp += len; 2081 } 2082 } 2083 while(n == 0); 2084 } 2085 else 2086 #endif /* SHOPT_MULTIBYTE */ 2087 while((n=state[*sp++])==0); 2088 dp = sp; 2089 if(mode<0) 2090 inquote = 1; 2091 while(1) 2092 { 2093 switch(n) 2094 { 2095 case S_EOF: 2096 stkseek(stkp,dp-stkptr(stkp,0)); 2097 if(mode<=0) 2098 { 2099 argp = (struct argnod*)stkfreeze(stkp,0); 2100 argp->argflag = ARG_RAW|ARG_QUOTED; 2101 } 2102 return(argp); 2103 case S_LIT: 2104 if(!(inquote&1)) 2105 { 2106 inlit = !inlit; 2107 if(mode==0 || (mode<0 && bracket)) 2108 { 2109 dp--; 2110 if(ep) 2111 { 2112 *dp = 0; 2113 dp = ep+stresc(ep); 2114 } 2115 ep = 0; 2116 } 2117 } 2118 break; 2119 case S_QUOTE: 2120 if(mode<0 && !bracket) 2121 break; 2122 if(!inlit) 2123 { 2124 if(mode<=0) 2125 dp--; 2126 inquote = inquote^1; 2127 if(ep) 2128 { 2129 char *msg; 2130 if(mode==2) 2131 { 2132 sfprintf(sfstdout,"%.*s\n",dp-ep,ep); 2133 ep = 0; 2134 break; 2135 } 2136 *--dp = 0; 2137 #if ERROR_VERSION >= 20000317L 2138 msg = ERROR_translate(0,error_info.id,0,ep); 2139 #else 2140 # if ERROR_VERSION >= 20000101L 2141 msg = ERROR_translate(error_info.id,ep); 2142 # else 2143 msg = ERROR_translate(ep,2); 2144 # endif 2145 #endif 2146 n = strlen(msg); 2147 dp = ep+n; 2148 if(sp-dp <= 1) 2149 { 2150 sp = stack_shift(stkp,sp,dp); 2151 dp = sp-1; 2152 ep = dp-n; 2153 } 2154 memmove(ep,msg,n); 2155 *dp++ = '"'; 2156 } 2157 ep = 0; 2158 } 2159 break; 2160 case S_DOL: /* check for $'...' and $"..." */ 2161 if(inlit) 2162 break; 2163 if(*sp==LPAREN || *sp==LBRACE) 2164 { 2165 inquote <<= 1; 2166 break; 2167 } 2168 if(inquote&1) 2169 break; 2170 if(*sp=='\'' || *sp=='"') 2171 { 2172 if(*sp=='"') 2173 inquote |= 1; 2174 else 2175 inlit = 1; 2176 sp++; 2177 if((mode==0||(mode<0&&bracket)) || (inquote&1)) 2178 { 2179 if(mode==2) 2180 ep = dp++; 2181 else if(mode==1) 2182 (ep=dp)[-1] = '"'; 2183 else 2184 ep = --dp; 2185 } 2186 } 2187 break; 2188 case S_ESC: 2189 #if SHOPT_CRNL 2190 if(*sp=='\r' && sp[1]=='\n') 2191 sp++; 2192 #endif /* SHOPT_CRNL */ 2193 if(inlit || mode>0) 2194 { 2195 if(mode<0) 2196 { 2197 if(dp>=sp) 2198 { 2199 sp = stack_shift(stkp,sp,dp+1); 2200 dp = sp-2; 2201 } 2202 *dp++ = '\\'; 2203 } 2204 if(ep) 2205 *dp++ = *sp++; 2206 break; 2207 } 2208 n = *sp; 2209 #if SHOPT_DOS 2210 if(!(inquote&1) && sh_lexstates[ST_NORM][n]==0) 2211 break; 2212 #endif /* SHOPT_DOS */ 2213 if(!(inquote&1) || (sh_lexstates[ST_QUOTE][n] && n!=RBRACE)) 2214 { 2215 if(n=='\n') 2216 dp--; 2217 else 2218 dp[-1] = n; 2219 sp++; 2220 } 2221 break; 2222 case S_POP: 2223 if(sp[-1]!=RBRACT) 2224 break; 2225 if(!inlit && !(inquote&1)) 2226 { 2227 inquote >>= 1; 2228 if(xp) 2229 dp = sh_checkid(xp,dp); 2230 xp = 0; 2231 if(--bracket<=0 && mode<0) 2232 inquote = 1; 2233 } 2234 else if((inlit||inquote) && mode<0) 2235 { 2236 dp[-1] = '\\'; 2237 if(dp>=sp) 2238 { 2239 sp = stack_shift(stkp,sp,dp); 2240 dp = sp-1; 2241 } 2242 *dp++ = ']'; 2243 } 2244 break; 2245 case S_BRACT: 2246 if(dp[-2]=='.') 2247 xp = dp; 2248 if(mode<0) 2249 { 2250 if(inlit || (bracket&&inquote)) 2251 { 2252 dp[-1] = '\\'; 2253 if(dp>=sp) 2254 { 2255 sp = stack_shift(stkp,sp,dp); 2256 dp = sp-1; 2257 } 2258 *dp++ = '['; 2259 } 2260 else if(bracket++==0) 2261 inquote = 0; 2262 } 2263 break; 2264 } 2265 #if SHOPT_MULTIBYTE 2266 if(mbwide()) 2267 { 2268 do 2269 { 2270 int len; 2271 switch(len = mbsize(sp)) 2272 { 2273 case -1: /* illegal multi-byte char */ 2274 case 0: 2275 case 1: 2276 n=state[*dp++ = *sp++]; 2277 break; 2278 default: 2279 /* 2280 * None of the state tables contain 2281 * entries for multibyte characters, 2282 * however, they should be treated 2283 * the same as any other alph 2284 * character. Therefore, we'll use 2285 * the state of the 'a' character. 2286 */ 2287 while(len--) 2288 *dp++ = *sp++; 2289 n=state['a']; 2290 } 2291 } 2292 while(n == 0); 2293 } 2294 else 2295 #endif /* SHOPT_MULTIBYTE */ 2296 while((n=state[*dp++ = *sp++])==0); 2297 } 2298 } 2299 2300 struct alias 2301 { 2302 Sfdisc_t disc; 2303 Namval_t *np; 2304 int nextc; 2305 int line; 2306 char buf[2]; 2307 Lex_t *lp; 2308 }; 2309 2310 /* 2311 * This code gets called whenever an end of string is found with alias 2312 */ 2313 2314 #ifndef SF_ATEXIT 2315 # define SF_ATEXIT 0 2316 #endif 2317 /* 2318 * This code gets called whenever an end of string is found with alias 2319 */ 2320 #ifdef SF_BUFCONST 2321 static int alias_exceptf(Sfio_t *iop,int type,void *data, Sfdisc_t *handle) 2322 #else 2323 static int alias_exceptf(Sfio_t *iop,int type,Sfdisc_t *handle) 2324 #endif 2325 { 2326 register struct alias *ap = (struct alias*)handle; 2327 register Namval_t *np; 2328 register Lex_t *lp; 2329 if(type==0 || type==SF_ATEXIT || !ap) 2330 return(0); 2331 lp = ap->lp; 2332 np = ap->np; 2333 if(type!=SF_READ) 2334 { 2335 if(type==SF_CLOSING) 2336 { 2337 register Sfdisc_t *dp = sfdisc(iop,SF_POPDISC); 2338 if(dp!=handle) 2339 sfdisc(iop,dp); 2340 } 2341 else if(type==SF_FINAL) 2342 free((void*)ap); 2343 goto done; 2344 } 2345 if(ap->nextc) 2346 { 2347 /* if last character is a blank, then next work can be alias */ 2348 register int c = fcpeek(-1); 2349 if(isblank(c)) 2350 lp->aliasok = 1; 2351 *ap->buf = ap->nextc; 2352 ap->nextc = 0; 2353 sfsetbuf(iop,ap->buf,1); 2354 return(1); 2355 } 2356 done: 2357 if(np) 2358 nv_offattr(np,NV_NOEXPAND); 2359 return(0); 2360 } 2361 2362 2363 static void setupalias(Lex_t *lp, const char *string,Namval_t *np) 2364 { 2365 register Sfio_t *iop, *base; 2366 struct alias *ap = (struct alias*)malloc(sizeof(struct alias)); 2367 ap->disc = alias_disc; 2368 ap->lp = lp; 2369 ap->buf[1] = 0; 2370 if(ap->np = np) 2371 { 2372 #if SHOPT_KIA 2373 if(lp->kiafile) 2374 { 2375 unsigned long r; 2376 r=kiaentity(lp,nv_name(np),-1,'p',0,0,lp->current,'a',0,""); 2377 sfprintf(lp->kiatmp,"p;%..64d;p;%..64d;%d;%d;e;\n",lp->current,r,lp->sh->inlineno,lp->sh->inlineno); 2378 } 2379 #endif /* SHOPT_KIA */ 2380 if((ap->nextc=fcget())==0) 2381 ap->nextc = ' '; 2382 } 2383 else 2384 ap->nextc = 0; 2385 iop = sfopen(NIL(Sfio_t*),(char*)string,"s"); 2386 sfdisc(iop, &ap->disc); 2387 lp->lexd.nocopy++; 2388 if(!(base=fcfile())) 2389 base = sfopen(NIL(Sfio_t*),fcseek(0),"s"); 2390 fcclose(); 2391 sfstack(base,iop); 2392 fcfopen(base); 2393 lp->lexd.nocopy--; 2394 } 2395 2396 /* 2397 * grow storage stack for nested constructs by STACK_ARRAY 2398 */ 2399 static int stack_grow(Lex_t *lp) 2400 { 2401 lp->lexd.lex_max += STACK_ARRAY; 2402 if(lp->lexd.lex_match) 2403 lp->lexd.lex_match = (int*)realloc((char*)lp->lexd.lex_match,sizeof(int)*lp->lexd.lex_max); 2404 else 2405 lp->lexd.lex_match = (int*)malloc(sizeof(int)*STACK_ARRAY); 2406 return(lp->lexd.lex_match!=0); 2407 } 2408 2409