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 errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete4,shp->inlineno,state);
1467 if(c&TEST_PATTERN)
1468 lp->lex.incase = 1;
1469 else if(c==TEST_REP)
1470 lp->lex.incase = TEST_RE;
1471 lp->lex.testop2 = 0;
1472 lp->digits = c;
1473 lp->token = TESTBINOP;
1474 return(lp->token);
1475 }
1476
1477 /* FALLTHROUGH */
1478 case TEST_OR: case TEST_AND:
1479 case 0:
1480 return(lp->token=0);
1481 }
1482 }
1483 if(lp->lex.reservok /* && !lp->lex.incase*/ && n<=2)
1484 {
1485 /* check for {, }, ! */
1486 c = state[0];
1487 if(n==1 && (c=='{' || c=='}' || c=='!'))
1488 {
1489 if(lp->lexd.warn && c=='{' && lp->lex.incase==2)
1490 errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete6,shp->inlineno);
1491 if(lp->lex.incase==1 && c==RBRACE)
1492 lp->lex.incase = 0;
1493 return(lp->token=c);
1494 }
1495 else if(!lp->lex.incase && c==LBRACT && state[1]==LBRACT)
1496 {
1497 lp->lex.intest = lp->lex.testop1 = 1;
1498 lp->lex.testop2 = lp->lex.reservok = 0;
1499 return(lp->token=BTESTSYM);
1500 }
1501 }
1502 c = 0;
1503 if(!lp->lex.skipword)
1504 {
1505 if(n>1 && lp->lex.reservok==1 && mode==ST_NAME &&
1506 (c=sh_lookup(state,shtab_reserved)))
1507 {
1508 if(lp->lex.incase)
1509 {
1510 if(lp->lex.incase >1)
1511 lp->lex.incase = 1;
1512 else if(c==ESACSYM)
1513 lp->lex.incase = 0;
1514 else
1515 c = 0;
1516 }
1517 else if(c==FORSYM || c==CASESYM || c==SELECTSYM || c==FUNCTSYM || c==NSPACESYM)
1518 {
1519 lp->lex.skipword = 1;
1520 lp->lex.incase = 2*(c==CASESYM);
1521 }
1522 else
1523 lp->lex.skipword = 0;
1524 if(c==INSYM)
1525 lp->lex.reservok = 0;
1526 else if(c==TIMESYM)
1527 {
1528 /* yech - POSIX requires time -p */
1529 while(fcgetc(n)==' ' || n=='\t');
1530 if(n>0)
1531 fcseek(-LEN);
1532 if(n=='-')
1533 c=0;
1534 }
1535 return(lp->token=c);
1536 }
1537 if(!(wordflags&ARG_QUOTED) && (lp->lex.reservok||lp->aliasok))
1538 {
1539 /* check for aliases */
1540 Namval_t* np;
1541 if(!lp->lex.incase && !assignment && fcpeek(0)!=LPAREN &&
1542 (np=nv_search(state,shp->alias_tree,HASH_SCOPE))
1543 && !nv_isattr(np,NV_NOEXPAND)
1544 #if KSHELL
1545 && (lp->aliasok!=2 || nv_isattr(np,BLT_DCL))
1546 && (!sh_isstate(SH_NOALIAS) || nv_isattr(np,NV_NOFREE))
1547 #endif /* KSHELL */
1548 && (state=nv_getval(np)))
1549 {
1550 setupalias(lp,state,np);
1551 nv_onattr(np,NV_NOEXPAND);
1552 lp->lex.reservok = 1;
1553 lp->assignok |= lp->lex.reservok;
1554 return(sh_lex(lp));
1555 }
1556 }
1557 lp->lex.reservok = 0;
1558 }
1559 lp->lex.skipword = lp->lexd.docword = 0;
1560 return(lp->token=c);
1561 }
1562
1563 /*
1564 * read to end of command substitution
1565 */
comsub(register Lex_t * lp,int endtok)1566 static int comsub(register Lex_t *lp, int endtok)
1567 {
1568 register int n,c,count=1;
1569 register int line=lp->sh->inlineno;
1570 char *first,*cp=fcseek(0),word[5];
1571 int off, messages=0, assignok=lp->assignok, csub;
1572 struct lexstate save;
1573 save = lp->lex;
1574 csub = lp->comsub;
1575 sh_lexopen(lp,lp->sh,1);
1576 lp->lexd.dolparen++;
1577 lp->lex.incase=0;
1578 pushlevel(lp,0,0);
1579 lp->comsub = (endtok==LBRACE);
1580 if(first=lp->lexd.first)
1581 off = cp-first;
1582 else
1583 off = cp-fcfirst();
1584 if(off<0)
1585 c=*cp, *cp=0;
1586 n = sh_lex(lp);
1587 if(off<0)
1588 *cp = c;
1589 if(n==endtok || off<0)
1590 {
1591 if(endtok==LPAREN && lp->lexd.paren)
1592 {
1593
1594 if(first==lp->lexd.first)
1595 {
1596 n = cp+1-(char*)fcseek(0);
1597 fcseek(n);
1598 }
1599 count++;
1600 lp->lexd.paren = 0;
1601 fcgetc(c);
1602 }
1603 while(1)
1604 {
1605 /* look for case and esac */
1606 n=0;
1607 while(1)
1608 {
1609 fcgetc(c);
1610 /* skip leading white space */
1611 if(n==0 && !sh_lexstates[ST_BEGIN][c])
1612 continue;
1613 if(n==4)
1614 break;
1615 if(sh_lexstates[ST_NAME][c])
1616 goto skip;
1617 word[n++] = c;
1618 }
1619 if(sh_lexstates[ST_NAME][c]==S_BREAK)
1620 {
1621 if(memcmp(word,"case",4)==0)
1622 lp->lex.incase=1;
1623 else if(memcmp(word,"esac",4)==0)
1624 lp->lex.incase=0;
1625 }
1626 skip:
1627 if(c && (c!='#' || n==0))
1628 fcseek(-LEN);
1629 if(c==RBRACE && lp->lex.incase)
1630 lp->lex.incase=0;
1631 c=sh_lex(lp);
1632 switch(c)
1633 {
1634 case LBRACE:
1635 if(endtok==LBRACE && !lp->lex.incase)
1636 {
1637 lp->comsub = 0;
1638 count++;
1639 }
1640 break;
1641 case RBRACE:
1642 rbrace:
1643 if(endtok==LBRACE && --count<=0)
1644 goto done;
1645 if(count==1)
1646 lp->comsub = endtok==LBRACE;
1647 break;
1648 case IPROCSYM: case OPROCSYM:
1649 case LPAREN:
1650 if(endtok==LPAREN && !lp->lex.incase)
1651 count++;
1652 break;
1653 case RPAREN:
1654 if(lp->lex.incase)
1655 lp->lex.incase=0;
1656 else if(endtok==LPAREN && --count<=0)
1657 goto done;
1658 break;
1659 case EOFSYM:
1660 lp->lastline = line;
1661 lp->lasttok = endtok;
1662 sh_syntax(lp);
1663 /* FALLTHROUGH */
1664 case IOSEEKSYM:
1665 if(fcgetc(c)!='#' && c>0)
1666 fcseek(-LEN);
1667 break;
1668 case IODOCSYM:
1669 lp->lexd.docextra = 0;
1670 sh_lex(lp);
1671 break;
1672 case 0:
1673 lp->lex.reservok = 0;
1674 messages |= lp->lexd.message;
1675 break;
1676 case ';':
1677 do
1678 fcgetc(c);
1679 while(!sh_lexstates[ST_BEGIN][c]);
1680 if(c==RBRACE && endtok==LBRACE)
1681 goto rbrace;
1682 if(c>0)
1683 fcseek(-LEN);
1684 /* fall through*/
1685 default:
1686 lp->lex.reservok = 1;
1687 }
1688 }
1689 }
1690 done:
1691 poplevel(lp);
1692 lp->comsub = csub;
1693 lp->lastline = line;
1694 lp->lexd.dolparen--;
1695 lp->lex = save;
1696 lp->assignok = (endchar(lp)==RBRACT?assignok:0);
1697 if(lp->heredoc)
1698 errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax5,lp->sh->inlineno,lp->heredoc->ioname);
1699 return(messages);
1700 }
1701
1702 /*
1703 * here-doc nested in $(...)
1704 * allocate ionode with delimiter filled in without disturbing stak
1705 */
nested_here(register Lex_t * lp)1706 static void nested_here(register Lex_t *lp)
1707 {
1708 register struct ionod *iop;
1709 register int n=0,offset;
1710 struct argnod *arg = lp->arg;
1711 Stk_t *stkp = lp->sh->stk;
1712 char *base;
1713 if(offset=stktell(stkp))
1714 base = stkfreeze(stkp,0);
1715 if(lp->lexd.docend)
1716 n = fcseek(0)-lp->lexd.docend;
1717 iop = newof(0,struct ionod,1,lp->lexd.docextra+n+ARGVAL);
1718 iop->iolst = lp->heredoc;
1719 stkseek(stkp,ARGVAL);
1720 if(lp->lexd.docextra)
1721 {
1722 sfseek(lp->sh->strbuf,(Sfoff_t)0, SEEK_SET);
1723 sfmove(lp->sh->strbuf,stkp,lp->lexd.docextra,-1);
1724 sfseek(lp->sh->strbuf,(Sfoff_t)0, SEEK_SET);
1725 }
1726 sfwrite(stkp,lp->lexd.docend,n);
1727 lp->arg = sh_endword(lp->sh,0);
1728 iop->ioname = (char*)(iop+1);
1729 strcpy(iop->ioname,lp->arg->argval);
1730 iop->iofile = (IODOC|IORAW);
1731 if(lp->lexd.docword>1)
1732 iop->iofile |= IOSTRIP;
1733 lp->heredoc = iop;
1734 lp->arg = arg;
1735 lp->lexd.docword = 0;
1736 if(offset)
1737 stkset(stkp,base,offset);
1738 else
1739 stkseek(stkp,0);
1740 }
1741
1742 /*
1743 * skip to <close> character
1744 * if <copy> is non,zero, then the characters are copied to the stack
1745 * <state> is the initial lexical state
1746 */
sh_lexskip(Lex_t * lp,int close,register int copy,int state)1747 void sh_lexskip(Lex_t *lp,int close, register int copy, int state)
1748 {
1749 register char *cp;
1750 lp->lexd.nest = close;
1751 lp->lexd.lex_state = state;
1752 lp->lexd.noarg = 1;
1753 if(copy)
1754 fcnotify(lex_advance,lp);
1755 else
1756 lp->lexd.nocopy++;
1757 sh_lex(lp);
1758 lp->lexd.noarg = 0;
1759 if(copy)
1760 {
1761 fcnotify(0,lp);
1762 if(!(cp=lp->lexd.first))
1763 cp = fcfirst();
1764 if((copy = fcseek(0)-cp) > 0)
1765 sfwrite(lp->sh->stk,cp,copy);
1766 }
1767 else
1768 lp->lexd.nocopy--;
1769 }
1770
1771 #if SHOPT_CRNL
_sfwrite(Sfio_t * sp,const Void_t * buff,size_t n)1772 ssize_t _sfwrite(Sfio_t *sp, const Void_t *buff, size_t n)
1773 {
1774 const char *cp = (const char*)buff, *next=cp, *ep = cp + n;
1775 int m=0,k;
1776 while(next = (const char*)memchr(next,'\r',ep-next))
1777 if(*++next=='\n')
1778 {
1779 if(k=next-cp-1)
1780 {
1781 if((k=sfwrite(sp,cp,k)) < 0)
1782 return(m>0?m:-1);
1783 m += k;
1784 }
1785 cp = next;
1786 }
1787 if((k=sfwrite(sp,cp,ep-cp)) < 0)
1788 return(m>0?m:-1);
1789 return(m+k);
1790 }
1791 # define sfwrite _sfwrite
1792 #endif /* SHOPT_CRNL */
1793
1794 /*
1795 * read in here-document from script
1796 * quoted here documents, and here-documents without special chars are
1797 * noted with the IOQUOTE flag
1798 * returns 1 for complete here-doc, 0 for EOF
1799 */
1800
here_copy(Lex_t * lp,register struct ionod * iop)1801 static int here_copy(Lex_t *lp,register struct ionod *iop)
1802 {
1803 register const char *state;
1804 register int c,n;
1805 register char *bufp,*cp;
1806 register Sfio_t *sp=lp->sh->heredocs, *funlog;
1807 int stripcol=0,stripflg, nsave, special=0;
1808 if(funlog=lp->sh->funlog)
1809 {
1810 if(fcfill()>0)
1811 fcseek(-LEN);
1812 lp->sh->funlog = 0;
1813 }
1814 if(iop->iolst)
1815 here_copy(lp,iop->iolst);
1816 iop->iooffset = sfseek(sp,(off_t)0,SEEK_END);
1817 iop->iosize = 0;
1818 iop->iodelim=iop->ioname;
1819 /* check for and strip quoted characters in delimiter string */
1820 if(stripflg=iop->iofile&IOSTRIP)
1821 {
1822 while(*iop->iodelim=='\t')
1823 iop->iodelim++;
1824 /* skip over leading tabs in document */
1825 if(iop->iofile&IOLSEEK)
1826 {
1827 iop->iofile &= ~IOLSEEK;
1828 while(fcgetc(c)=='\t' || c==' ')
1829 {
1830 if(c==' ')
1831 stripcol++;
1832 else
1833 stripcol += 8 - stripcol%8;
1834 }
1835 }
1836 else
1837 while(fcgetc(c)=='\t');
1838 if(c>0)
1839 fcseek(-LEN);
1840 }
1841 if(iop->iofile&IOQUOTE)
1842 state = sh_lexstates[ST_LIT];
1843 else
1844 state = sh_lexstates[ST_QUOTE];
1845 bufp = fcseek(0);
1846 n = S_NL;
1847 while(1)
1848 {
1849 if(n!=S_NL)
1850 {
1851 /* skip over regular characters */
1852 #if SHOPT_MULTIBYTE
1853 do
1854 {
1855 if(fcleft()< MB_LEN_MAX && mbsize(fcseek(0))<0)
1856 {
1857 n = S_EOF;
1858 LEN = -fcleft();
1859 break;
1860 }
1861 }
1862 #endif /* SHOPT_MULTIBYTE */
1863
1864 while((n=STATE(state,c))==0);
1865 }
1866 if(n==S_EOF || !(c=fcget()))
1867 {
1868 if(LEN < 0)
1869 c = fclast()-bufp;
1870 else
1871 c= (fcseek(0)-1)-bufp;
1872 if(!lp->lexd.dolparen && c)
1873 {
1874 if(n==S_ESC)
1875 c--;
1876 if(!lp->lexd.dolparen && (c=sfwrite(sp,bufp,c))>0)
1877 iop->iosize += c;
1878 }
1879 #if SHOPT_MULTIBYTE
1880 if(LEN==0)
1881 LEN=1;
1882 if(LEN < 0)
1883 {
1884 n = LEN;
1885 c = fcmbget(&LEN);
1886 LEN += n;
1887 }
1888 else
1889 #endif /* SHOPT_MULTIBYTE */
1890 c = lexfill(lp);
1891 if(c<0)
1892 break;
1893 if(n==S_ESC)
1894 {
1895 #if SHOPT_CRNL
1896 if(c=='\r' && (c=fcget())!=NL)
1897 fcseek(-LEN);
1898 #endif /* SHOPT_CRNL */
1899 if(c==NL)
1900 fcseek(1);
1901 else if(!lp->lexd.dolparen)
1902 {
1903 iop->iosize++;
1904 sfputc(sp,'\\');
1905 }
1906 }
1907 bufp = fcseek(-LEN);
1908 }
1909 else
1910 fcseek(-LEN);
1911 switch(n)
1912 {
1913 case S_NL:
1914 lp->sh->inlineno++;
1915 if((stripcol && c==' ') || (stripflg && c=='\t'))
1916 {
1917 if(!lp->lexd.dolparen)
1918 {
1919 /* write out line */
1920 n = fcseek(0)-bufp;
1921 if((n=sfwrite(sp,bufp,n))>0)
1922 iop->iosize += n;
1923 }
1924 /* skip over tabs */
1925 if(stripcol)
1926 {
1927 int col=0;
1928 do
1929 {
1930 fcgetc(c);
1931 if(c==' ')
1932 col++;
1933 else
1934 col += 8 - col%8;
1935 if(col>stripcol)
1936 break;
1937 }
1938 while (c==' ' || c=='\t');
1939 }
1940 else while(c=='\t')
1941 fcgetc(c);
1942 if(c<=0)
1943 goto done;
1944 bufp = fcseek(-LEN);
1945 }
1946 if(c!=iop->iodelim[0])
1947 break;
1948 cp = fcseek(0);
1949 nsave = n = 0;
1950 while(1)
1951 {
1952 if(!(c=fcget()))
1953 {
1954 if(!lp->lexd.dolparen && (c=cp-bufp))
1955 {
1956 if((c=sfwrite(sp,cp=bufp,c))>0)
1957 iop->iosize+=c;
1958 }
1959 nsave = n;
1960 if((c=lexfill(lp))<=0)
1961 {
1962 c = iop->iodelim[n]==0;
1963 goto done;
1964 }
1965 }
1966 #if SHOPT_CRNL
1967 if(c=='\r' && (c=fcget())!=NL)
1968 {
1969 if(c)
1970 fcseek(-LEN);
1971 c='\r';
1972 }
1973 #endif /* SHOPT_CRNL */
1974 if(c==NL)
1975 lp->sh->inlineno++;
1976 if(iop->iodelim[n]==0 && (c==NL||c==RPAREN))
1977 {
1978 if(!lp->lexd.dolparen && (n=cp-bufp))
1979 {
1980 if((n=sfwrite(sp,bufp,n))>0)
1981 iop->iosize += n;
1982 }
1983 lp->sh->inlineno--;
1984 if(c==RPAREN)
1985 fcseek(-LEN);
1986 goto done;
1987 }
1988 if(iop->iodelim[n++]!=c)
1989 {
1990 /*
1991 * The match for delimiter failed.
1992 * nsave>0 only when a buffer boundary
1993 * was crossed while checking the
1994 * delimiter
1995 */
1996 if(!lp->lexd.dolparen && nsave>0)
1997 {
1998 if((n=sfwrite(sp,iop->iodelim,nsave))>0)
1999 iop->iosize += n;
2000 bufp = fcfirst();
2001 }
2002 if(c==NL)
2003 fcseek(-LEN);
2004 break;
2005 }
2006 }
2007 break;
2008 case S_ESC:
2009 n=1;
2010 #if SHOPT_CRNL
2011 if(c=='\r')
2012 {
2013 fcseek(1);
2014 if(c=fcget())
2015 fcseek(-LEN);
2016 if(c==NL)
2017 n=2;
2018 else
2019 {
2020 special++;
2021 break;
2022 }
2023 }
2024 #endif /* SHOPT_CRNL */
2025 if(c==NL)
2026 {
2027 /* new-line joining */
2028 lp->sh->inlineno++;
2029 if(!lp->lexd.dolparen && (n=(fcseek(0)-bufp)-n)>=0)
2030 {
2031 if(n && (n=sfwrite(sp,bufp,n))>0)
2032 iop->iosize += n;
2033 bufp = fcseek(0)+1;
2034 }
2035 }
2036 else
2037 special++;
2038 fcget();
2039 break;
2040
2041 case S_GRAVE:
2042 case S_DOL:
2043 special++;
2044 break;
2045 }
2046 n=0;
2047 }
2048 done:
2049 lp->sh->funlog = funlog;
2050 if(lp->lexd.dolparen)
2051 free((void*)iop);
2052 else if(!special)
2053 iop->iofile |= IOQUOTE;
2054 return(c);
2055 }
2056
2057 /*
2058 * generates string for given token
2059 */
fmttoken(Lex_t * lp,register int sym,char * tok)2060 static char *fmttoken(Lex_t *lp, register int sym, char *tok)
2061 {
2062 int n=1;
2063 if(sym < 0)
2064 return((char*)sh_translate(e_lexzerobyte));
2065 if(sym==0)
2066 return(lp->arg?lp->arg->argval:"?");
2067 if(lp->lex.intest && lp->arg && *lp->arg->argval)
2068 return(lp->arg->argval);
2069 if(sym&SYMRES)
2070 {
2071 register const Shtable_t *tp=shtab_reserved;
2072 while(tp->sh_number && tp->sh_number!=sym)
2073 tp++;
2074 return((char*)tp->sh_name);
2075 }
2076 if(sym==EOFSYM)
2077 return((char*)sh_translate(e_endoffile));
2078 if(sym==NL)
2079 return((char*)sh_translate(e_newline));
2080 tok[0] = sym;
2081 if(sym&SYMREP)
2082 tok[n++] = sym;
2083 else
2084 {
2085 switch(sym&SYMMASK)
2086 {
2087 case SYMAMP:
2088 sym = '&';
2089 break;
2090 case SYMPIPE:
2091 sym = '|';
2092 break;
2093 case SYMGT:
2094 sym = '>';
2095 break;
2096 case SYMLPAR:
2097 sym = LPAREN;
2098 break;
2099 case SYMSHARP:
2100 sym = '#';
2101 break;
2102 case SYMSEMI:
2103 if(tok[0]=='<')
2104 tok[n++] = '>';
2105 sym = ';';
2106 break;
2107 default:
2108 sym = 0;
2109 }
2110 tok[n++] = sym;
2111 }
2112 tok[n] = 0;
2113 return(tok);
2114 }
2115
2116 /*
2117 * print a bad syntax message
2118 */
2119
sh_syntax(Lex_t * lp)2120 void sh_syntax(Lex_t *lp)
2121 {
2122 register Shell_t *shp = lp->sh;
2123 register const char *cp = sh_translate(e_unexpected);
2124 register char *tokstr;
2125 register int tok = lp->token;
2126 char tokbuf[3];
2127 Sfio_t *sp;
2128 if((tok==EOFSYM) && lp->lasttok)
2129 {
2130 tok = lp->lasttok;
2131 cp = sh_translate(e_unmatched);
2132 }
2133 else
2134 lp->lastline = shp->inlineno;
2135 tokstr = fmttoken(lp,tok,tokbuf);
2136 VALIDATE_FD(shp, shp->infd);
2137 if((sp=fcfile()) || (shp->infd>=0 && (sp=shp->sftable[shp->infd])))
2138 {
2139 /* clear out any pending input */
2140 register Sfio_t *top;
2141 while(fcget()>0);
2142 fcclose();
2143 while(top=sfstack(sp,SF_POPSTACK))
2144 sfclose(top);
2145 }
2146 else
2147 fcclose();
2148 shp->inlineno = lp->inlineno;
2149 shp->st.firstline = lp->firstline;
2150 #if KSHELL
2151 if(!sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_PROFILE))
2152 #else
2153 if(shp->inlineno!=1)
2154 #endif
2155 errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax1,lp->lastline,tokstr,cp);
2156 else
2157 errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax2,tokstr,cp);
2158 }
2159
stack_shift(Stk_t * stkp,register char * sp,char * dp)2160 static char *stack_shift(Stk_t *stkp, register char *sp,char *dp)
2161 {
2162 register char *ep;
2163 register int offset = stktell(stkp);
2164 register int left = offset-(sp-stkptr(stkp,0));
2165 register int shift = (dp+1-sp);
2166 offset += shift;
2167 stkseek(stkp,offset);
2168 sp = stkptr(stkp,offset);
2169 ep = sp - shift;
2170 while(left--)
2171 *--sp = *--ep;
2172 return(sp);
2173 }
2174
2175 /*
2176 * Assumes that current word is unfrozen on top of the stak
2177 * If <mode> is zero, gets rid of quoting and consider argument as string
2178 * and returns pointer to frozen arg
2179 * If mode==1, just replace $"..." strings with international strings
2180 * The result is left on the stak
2181 * If mode==2, the each $"" string is printed on standard output
2182 */
sh_endword(Shell_t * shp,int mode)2183 struct argnod *sh_endword(Shell_t *shp,int mode)
2184 {
2185 register const char *state = sh_lexstates[ST_NESTED];
2186 register int n;
2187 register char *sp,*dp;
2188 register int inquote=0, inlit=0; /* set within quoted strings */
2189 struct argnod* argp=0;
2190 char *ep=0, *xp=0;
2191 int bracket=0;
2192 Stk_t *stkp=shp->stk;
2193 sfputc(stkp,0);
2194 sp = stkptr(stkp,ARGVAL);
2195 #if SHOPT_MULTIBYTE
2196 if(mbwide())
2197 {
2198 do
2199 {
2200 int len;
2201 switch(len = mbsize(sp))
2202 {
2203 case -1: /* illegal multi-byte char */
2204 case 0:
2205 case 1:
2206 n=state[*sp++];
2207 break;
2208 default:
2209 /*
2210 * None of the state tables contain
2211 * entries for multibyte characters,
2212 * however, they should be treated
2213 * the same as any other alph
2214 * character. Therefore, we'll use
2215 * the state of the 'a' character.
2216 */
2217 n=state['a'];
2218 sp += len;
2219 }
2220 }
2221 while(n == 0);
2222 }
2223 else
2224 #endif /* SHOPT_MULTIBYTE */
2225 while((n=state[*sp++])==0);
2226 dp = sp;
2227 if(mode<0)
2228 inquote = 1;
2229 while(1)
2230 {
2231 switch(n)
2232 {
2233 case S_EOF:
2234 stkseek(stkp,dp-stkptr(stkp,0));
2235 if(mode<=0)
2236 {
2237 argp = (struct argnod*)stkfreeze(stkp,0);
2238 argp->argflag = ARG_RAW|ARG_QUOTED;
2239 }
2240 return(argp);
2241 case S_LIT:
2242 if(!(inquote&1))
2243 {
2244 inlit = !inlit;
2245 if(mode==0 || (mode<0 && bracket))
2246 {
2247 dp--;
2248 if(ep)
2249 {
2250 *dp = 0;
2251 stresc(ep);
2252 dp = ep+ strlen(ep);
2253 }
2254 ep = 0;
2255 }
2256 }
2257 break;
2258 case S_QUOTE:
2259 if(mode<0 && !bracket)
2260 break;
2261 if(!inlit)
2262 {
2263 if(mode<=0)
2264 dp--;
2265 inquote = inquote^1;
2266 if(ep)
2267 {
2268 char *msg;
2269 if(mode==2)
2270 {
2271 sfprintf(sfstdout,"%.*s\n",dp-ep,ep);
2272 ep = 0;
2273 break;
2274 }
2275 *--dp = 0;
2276 #if ERROR_VERSION >= 20000317L
2277 msg = ERROR_translate(0,error_info.id,0,ep);
2278 #else
2279 # if ERROR_VERSION >= 20000101L
2280 msg = ERROR_translate(error_info.id,ep);
2281 # else
2282 msg = ERROR_translate(ep,2);
2283 # endif
2284 #endif
2285 n = strlen(msg);
2286 dp = ep+n;
2287 if(sp-dp <= 1)
2288 {
2289 sp = stack_shift(stkp,sp,dp);
2290 dp = sp-1;
2291 ep = dp-n;
2292 }
2293 memmove(ep,msg,n);
2294 *dp++ = '"';
2295 }
2296 ep = 0;
2297 }
2298 break;
2299 case S_DOL: /* check for $'...' and $"..." */
2300 if(inlit)
2301 break;
2302 if(*sp==LPAREN || *sp==LBRACE)
2303 {
2304 inquote <<= 1;
2305 break;
2306 }
2307 if(inquote&1)
2308 break;
2309 if(*sp=='\'' || *sp=='"')
2310 {
2311 if(*sp=='"')
2312 inquote |= 1;
2313 else
2314 inlit = 1;
2315 sp++;
2316 if((mode==0||(mode<0&&bracket)) || (inquote&1))
2317 {
2318 if(mode==2)
2319 ep = dp++;
2320 else if(mode==1)
2321 (ep=dp)[-1] = '"';
2322 else
2323 ep = --dp;
2324 }
2325 }
2326 break;
2327 case S_ESC:
2328 #if SHOPT_CRNL
2329 if(*sp=='\r' && sp[1]=='\n')
2330 sp++;
2331 #endif /* SHOPT_CRNL */
2332 if(inlit || mode>0)
2333 {
2334 if(mode<0)
2335 {
2336 if(dp>=sp)
2337 {
2338 sp = stack_shift(stkp,sp,dp+1);
2339 dp = sp-2;
2340 }
2341 *dp++ = '\\';
2342 }
2343 if(ep)
2344 *dp++ = *sp++;
2345 break;
2346 }
2347 n = *sp;
2348 #if SHOPT_DOS
2349 if(!(inquote&1) && sh_lexstates[ST_NORM][n]==0)
2350 break;
2351 #endif /* SHOPT_DOS */
2352 if(!(inquote&1) || (sh_lexstates[ST_QUOTE][n] && n!=RBRACE))
2353 {
2354 if(n=='\n')
2355 dp--;
2356 else
2357 dp[-1] = n;
2358 sp++;
2359 }
2360 break;
2361 case S_POP:
2362 if(sp[-1]!=RBRACT)
2363 break;
2364 if(!inlit && !(inquote&1))
2365 {
2366 inquote >>= 1;
2367 if(xp)
2368 dp = sh_checkid(xp,dp);
2369 xp = 0;
2370 if(--bracket<=0 && mode<0)
2371 inquote = 1;
2372 }
2373 else if((inlit||inquote) && mode<0)
2374 {
2375 dp[-1] = '\\';
2376 if(dp>=sp)
2377 {
2378 sp = stack_shift(stkp,sp,dp);
2379 dp = sp-1;
2380 }
2381 *dp++ = ']';
2382 }
2383 break;
2384 case S_BRACT:
2385 if(dp[-2]=='.')
2386 xp = dp;
2387 if(mode<0)
2388 {
2389 if(inlit || (bracket&&inquote))
2390 {
2391 dp[-1] = '\\';
2392 if(dp>=sp)
2393 {
2394 sp = stack_shift(stkp,sp,dp);
2395 dp = sp-1;
2396 }
2397 *dp++ = '[';
2398 }
2399 else if(bracket++==0)
2400 inquote = 0;
2401 }
2402 break;
2403 }
2404 #if SHOPT_MULTIBYTE
2405 if(mbwide())
2406 {
2407 do
2408 {
2409 int len;
2410 switch(len = mbsize(sp))
2411 {
2412 case -1: /* illegal multi-byte char */
2413 case 0:
2414 case 1:
2415 n=state[*dp++ = *sp++];
2416 break;
2417 default:
2418 /*
2419 * None of the state tables contain
2420 * entries for multibyte characters,
2421 * however, they should be treated
2422 * the same as any other alph
2423 * character. Therefore, we'll use
2424 * the state of the 'a' character.
2425 */
2426 while(len--)
2427 *dp++ = *sp++;
2428 n=state['a'];
2429 }
2430 }
2431 while(n == 0);
2432 }
2433 else
2434 #endif /* SHOPT_MULTIBYTE */
2435 while((n=state[*dp++ = *sp++])==0);
2436 }
2437 }
2438
2439 struct alias
2440 {
2441 Sfdisc_t disc;
2442 Namval_t *np;
2443 int nextc;
2444 int line;
2445 char buf[2];
2446 Lex_t *lp;
2447 };
2448
2449 /*
2450 * This code gets called whenever an end of string is found with alias
2451 */
2452
2453 #ifndef SF_ATEXIT
2454 # define SF_ATEXIT 0
2455 #endif
2456 /*
2457 * This code gets called whenever an end of string is found with alias
2458 */
2459 #ifdef SF_BUFCONST
alias_exceptf(Sfio_t * iop,int type,void * data,Sfdisc_t * handle)2460 static int alias_exceptf(Sfio_t *iop,int type,void *data, Sfdisc_t *handle)
2461 #else
2462 static int alias_exceptf(Sfio_t *iop,int type,Sfdisc_t *handle)
2463 #endif
2464 {
2465 register struct alias *ap = (struct alias*)handle;
2466 register Namval_t *np;
2467 register Lex_t *lp;
2468 if(type==0 || type==SF_ATEXIT || !ap)
2469 return(0);
2470 lp = ap->lp;
2471 np = ap->np;
2472 if(type!=SF_READ)
2473 {
2474 if(type==SF_CLOSING)
2475 {
2476 register Sfdisc_t *dp = sfdisc(iop,SF_POPDISC);
2477 if(dp!=handle)
2478 sfdisc(iop,dp);
2479 }
2480 else if(type==SF_FINAL)
2481 free((void*)ap);
2482 goto done;
2483 }
2484 if(ap->nextc)
2485 {
2486 /* if last character is a blank, then next work can be alias */
2487 register int c = fcpeek(-1);
2488 if(isblank(c))
2489 lp->aliasok = 1;
2490 *ap->buf = ap->nextc;
2491 ap->nextc = 0;
2492 sfsetbuf(iop,ap->buf,1);
2493 return(1);
2494 }
2495 done:
2496 if(np)
2497 nv_offattr(np,NV_NOEXPAND);
2498 return(0);
2499 }
2500
2501
setupalias(Lex_t * lp,const char * string,Namval_t * np)2502 static void setupalias(Lex_t *lp, const char *string,Namval_t *np)
2503 {
2504 register Sfio_t *iop, *base;
2505 struct alias *ap = (struct alias*)malloc(sizeof(struct alias));
2506 ap->disc = alias_disc;
2507 ap->lp = lp;
2508 ap->buf[1] = 0;
2509 if(ap->np = np)
2510 {
2511 #if SHOPT_KIA
2512 if(lp->kiafile)
2513 {
2514 unsigned long r;
2515 r=kiaentity(lp,nv_name(np),-1,'p',0,0,lp->current,'a',0,"");
2516 sfprintf(lp->kiatmp,"p;%..64d;p;%..64d;%d;%d;e;\n",lp->current,r,lp->sh->inlineno,lp->sh->inlineno);
2517 }
2518 #endif /* SHOPT_KIA */
2519 if((ap->nextc=fcget())==0)
2520 ap->nextc = ' ';
2521 }
2522 else
2523 ap->nextc = 0;
2524 iop = sfopen(NIL(Sfio_t*),(char*)string,"s");
2525 sfdisc(iop, &ap->disc);
2526 lp->lexd.nocopy++;
2527 if(!(base=fcfile()))
2528 base = sfopen(NIL(Sfio_t*),fcseek(0),"s");
2529 fcclose();
2530 sfstack(base,iop);
2531 fcfopen(base);
2532 lp->lexd.nocopy--;
2533 }
2534
2535 /*
2536 * grow storage stack for nested constructs by STACK_ARRAY
2537 */
stack_grow(Lex_t * lp)2538 static int stack_grow(Lex_t *lp)
2539 {
2540 lp->lexd.lex_max += STACK_ARRAY;
2541 if(lp->lexd.lex_match)
2542 lp->lexd.lex_match = (int*)realloc((char*)lp->lexd.lex_match,sizeof(int)*lp->lexd.lex_max);
2543 else
2544 lp->lexd.lex_match = (int*)malloc(sizeof(int)*STACK_ARRAY);
2545 return(lp->lexd.lex_match!=0);
2546 }
2547
2548