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