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