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