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