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