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