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