1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4b30d1939SAndy Fiddaman * Copyright (c) 1982-2012 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6b30d1939SAndy Fiddaman * Eclipse Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10b30d1939SAndy Fiddaman * http://www.eclipse.org/org/documents/epl-v10.html *
11b30d1939SAndy Fiddaman * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * David Korn <dgk@research.att.com> *
18da2e3ebdSchin * *
19da2e3ebdSchin ***********************************************************************/
20da2e3ebdSchin #pragma prototyped
21da2e3ebdSchin /*
22da2e3ebdSchin * KornShell lexical analyzer
23da2e3ebdSchin *
24da2e3ebdSchin * Written by David Korn
25da2e3ebdSchin * AT&T Labs
26da2e3ebdSchin *
27da2e3ebdSchin */
28b30d1939SAndy Fiddaman /*
29b30d1939SAndy Fiddaman * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
30b30d1939SAndy Fiddaman */
31da2e3ebdSchin
32da2e3ebdSchin #include <ast.h>
33da2e3ebdSchin #include <stak.h>
34da2e3ebdSchin #include <fcin.h>
35da2e3ebdSchin #include <nval.h>
36da2e3ebdSchin #include "FEATURE/options"
37da2e3ebdSchin
38da2e3ebdSchin #if KSHELL
39da2e3ebdSchin # include "defs.h"
40da2e3ebdSchin #else
41da2e3ebdSchin # include <shell.h>
42da2e3ebdSchin # define nv_getval(np) ((np)->nvalue)
43da2e3ebdSchin Shell_t sh = {1};
44da2e3ebdSchin #endif /* KSHELL */
45da2e3ebdSchin
46da2e3ebdSchin #include "argnod.h"
47da2e3ebdSchin #include "test.h"
48da2e3ebdSchin #include "lexstates.h"
49da2e3ebdSchin #include "io.h"
50da2e3ebdSchin
51da2e3ebdSchin #define TEST_RE 3
52da2e3ebdSchin #define SYNBAD 3 /* exit value for syntax errors */
53da2e3ebdSchin #define STACK_ARRAY 3 /* size of depth match stack growth */
54da2e3ebdSchin
55da2e3ebdSchin #if _lib_iswblank < 0 /* set in lexstates.h to enable this code */
56da2e3ebdSchin
57da2e3ebdSchin int
local_iswblank(wchar_t wc)58da2e3ebdSchin local_iswblank(wchar_t wc)
59da2e3ebdSchin {
60da2e3ebdSchin static int initialized;
61da2e3ebdSchin static wctype_t wt;
62da2e3ebdSchin
63da2e3ebdSchin if (!initialized)
64da2e3ebdSchin {
65da2e3ebdSchin initialized = 1;
66da2e3ebdSchin wt = wctype("blank");
67da2e3ebdSchin }
68da2e3ebdSchin return(iswctype(wc, wt));
69da2e3ebdSchin }
70da2e3ebdSchin
71da2e3ebdSchin #endif
72da2e3ebdSchin
73da2e3ebdSchin /*
74da2e3ebdSchin * This structure allows for arbitrary depth nesting of (...), {...}, [...]
75da2e3ebdSchin */
76da2e3ebdSchin struct lexstate
77da2e3ebdSchin {
78da2e3ebdSchin char incase; /* 1 for case pattern, 2 after case */
79da2e3ebdSchin char intest; /* 1 inside [[...]] */
80da2e3ebdSchin char testop1; /* 1 when unary test op legal */
81da2e3ebdSchin char testop2; /* 1 when binary test op legal */
82da2e3ebdSchin char reservok; /* >0 for reserved word legal */
83da2e3ebdSchin char skipword; /* next word can't be reserved */
84da2e3ebdSchin char last_quote; /* last multi-line quote character */
85b30d1939SAndy Fiddaman char nestedbrace; /* ${var op {...}} */
86da2e3ebdSchin };
87da2e3ebdSchin
88da2e3ebdSchin struct lexdata
89da2e3ebdSchin {
90da2e3ebdSchin char nocopy;
91da2e3ebdSchin char paren;
92da2e3ebdSchin char dolparen;
93da2e3ebdSchin char nest;
94da2e3ebdSchin char docword;
95b30d1939SAndy Fiddaman char nested_tilde;
96da2e3ebdSchin char *docend;
97da2e3ebdSchin char noarg;
98da2e3ebdSchin char balance;
99da2e3ebdSchin char warn;
100da2e3ebdSchin char message;
101da2e3ebdSchin char arith;
102da2e3ebdSchin char *first;
103da2e3ebdSchin int level;
104da2e3ebdSchin int lastc;
105da2e3ebdSchin int lex_max;
106da2e3ebdSchin int *lex_match;
107da2e3ebdSchin int lex_state;
10834f9b3eeSRoland Mainz int docextra;
109da2e3ebdSchin #if SHOPT_KIA
110da2e3ebdSchin off_t kiaoff;
111da2e3ebdSchin #endif
112da2e3ebdSchin };
113da2e3ebdSchin
114da2e3ebdSchin #define _SHLEX_PRIVATE \
1157c2fbfb3SApril Chin struct lexdata lexd; \
1167c2fbfb3SApril Chin struct lexstate lex;
117da2e3ebdSchin
118da2e3ebdSchin #include "shlex.h"
119da2e3ebdSchin
120da2e3ebdSchin
1217c2fbfb3SApril Chin #define pushlevel(lp,c,s) ((lp->lexd.level>=lp->lexd.lex_max?stack_grow(lp):1) &&\
1227c2fbfb3SApril Chin ((lp->lexd.lex_match[lp->lexd.level++]=lp->lexd.lastc),\
1237c2fbfb3SApril Chin lp->lexd.lastc=(((s)<<CHAR_BIT)|(c))))
1247c2fbfb3SApril Chin #define oldmode(lp) (lp->lexd.lastc>>CHAR_BIT)
1257c2fbfb3SApril Chin #define endchar(lp) (lp->lexd.lastc&0xff)
1267c2fbfb3SApril Chin #define setchar(lp,c) (lp->lexd.lastc = ((lp->lexd.lastc&~0xff)|(c)))
1277c2fbfb3SApril Chin #define poplevel(lp) (lp->lexd.lastc=lp->lexd.lex_match[--lp->lexd.level])
128da2e3ebdSchin
129da2e3ebdSchin static char *fmttoken(Lex_t*, int, char*);
130da2e3ebdSchin #ifdef SF_BUFCONST
131da2e3ebdSchin static int alias_exceptf(Sfio_t*, int, void*, Sfdisc_t*);
132da2e3ebdSchin #else
133da2e3ebdSchin static int alias_exceptf(Sfio_t*, int, Sfdisc_t*);
134da2e3ebdSchin #endif
135da2e3ebdSchin static void setupalias(Lex_t*,const char*, Namval_t*);
1367c2fbfb3SApril Chin static int comsub(Lex_t*,int);
137da2e3ebdSchin static void nested_here(Lex_t*);
138da2e3ebdSchin static int here_copy(Lex_t*, struct ionod*);
139da2e3ebdSchin static int stack_grow(Lex_t*);
140da2e3ebdSchin static const Sfdisc_t alias_disc = { NULL, NULL, NULL, alias_exceptf, NULL };
141da2e3ebdSchin
142da2e3ebdSchin #if SHOPT_KIA
143da2e3ebdSchin
refvar(Lex_t * lp,int type)1447c2fbfb3SApril Chin static void refvar(Lex_t *lp, int type)
145da2e3ebdSchin {
1467c2fbfb3SApril Chin register Shell_t *shp = lp->sh;
1477c2fbfb3SApril Chin register Stk_t *stkp = shp->stk;
1487c2fbfb3SApril Chin off_t off = (fcseek(0)-(type+1))-(lp->lexd.first?lp->lexd.first:fcfirst());
149da2e3ebdSchin unsigned long r;
1507c2fbfb3SApril Chin if(lp->lexd.first)
151da2e3ebdSchin {
1527c2fbfb3SApril Chin off = (fcseek(0)-(type+1)) - lp->lexd.first;
1537c2fbfb3SApril Chin r=kiaentity(lp,lp->lexd.first+lp->lexd.kiaoff+type,off-lp->lexd.kiaoff,'v',-1,-1,lp->current,'v',0,"");
154da2e3ebdSchin }
155da2e3ebdSchin else
156da2e3ebdSchin {
1577c2fbfb3SApril Chin int n,offset = stktell(stkp);
158da2e3ebdSchin char *savptr,*begin;
159da2e3ebdSchin off = offset + (fcseek(0)-(type+1)) - fcfirst();
1607c2fbfb3SApril Chin if(lp->lexd.kiaoff < offset)
161da2e3ebdSchin {
162da2e3ebdSchin /* variable starts on stak, copy remainder */
163da2e3ebdSchin if(off>offset)
1647c2fbfb3SApril Chin sfwrite(stkp,fcfirst()+type,off-offset);
1657c2fbfb3SApril Chin n = stktell(stkp)-lp->lexd.kiaoff;
1667c2fbfb3SApril Chin begin = stkptr(stkp,lp->lexd.kiaoff);
167da2e3ebdSchin }
168da2e3ebdSchin else
169da2e3ebdSchin {
170da2e3ebdSchin /* variable in data buffer */
1717c2fbfb3SApril Chin begin = fcfirst()+(type+lp->lexd.kiaoff-offset);
1727c2fbfb3SApril Chin n = off-lp->lexd.kiaoff;
173da2e3ebdSchin }
1747c2fbfb3SApril Chin savptr = stkfreeze(stkp,0);
1757c2fbfb3SApril Chin r=kiaentity(lp,begin,n,'v',-1,-1,lp->current,'v',0,"");
1767c2fbfb3SApril Chin stkset(stkp,savptr,offset);
177da2e3ebdSchin }
1787c2fbfb3SApril Chin sfprintf(lp->kiatmp,"p;%..64d;v;%..64d;%d;%d;r;\n",lp->current,r,shp->inlineno,shp->inlineno);
179da2e3ebdSchin }
180da2e3ebdSchin #endif /* SHOPT_KIA */
181da2e3ebdSchin
182da2e3ebdSchin /*
183da2e3ebdSchin * This routine gets called when reading across a buffer boundary
184da2e3ebdSchin * If lexd.nocopy is off, then current token is saved on the stack
185da2e3ebdSchin */
lex_advance(Sfio_t * iop,const char * buff,register int size,void * context)1867c2fbfb3SApril Chin static void lex_advance(Sfio_t *iop, const char *buff, register int size, void *context)
187da2e3ebdSchin {
1887c2fbfb3SApril Chin register Lex_t *lp = (Lex_t*)context;
1897c2fbfb3SApril Chin register Shell_t *shp = lp->sh;
1907c2fbfb3SApril Chin register Sfio_t *log= shp->funlog;
1917c2fbfb3SApril Chin Stk_t *stkp = shp->stk;
192da2e3ebdSchin #if KSHELL
193da2e3ebdSchin /* write to history file and to stderr if necessary */
194da2e3ebdSchin if(iop && !sfstacked(iop))
195da2e3ebdSchin {
196b30d1939SAndy Fiddaman if(sh_isstate(SH_HISTORY) && shp->gd->hist_ptr)
197b30d1939SAndy Fiddaman log = shp->gd->hist_ptr->histfp;
198da2e3ebdSchin sfwrite(log, (void*)buff, size);
199da2e3ebdSchin if(sh_isstate(SH_VERBOSE))
200da2e3ebdSchin sfwrite(sfstderr, buff, size);
201da2e3ebdSchin }
202da2e3ebdSchin #endif
2037c2fbfb3SApril Chin if(lp->lexd.nocopy)
204da2e3ebdSchin return;
205b30d1939SAndy Fiddaman if(lp->lexd.dolparen && lp->lexd.docword && lp->lexd.docend)
20634f9b3eeSRoland Mainz {
20734f9b3eeSRoland Mainz int n = size - (lp->lexd.docend-(char*)buff);
20834f9b3eeSRoland Mainz sfwrite(shp->strbuf,lp->lexd.docend,n);
20934f9b3eeSRoland Mainz lp->lexd.docextra += n;
210b30d1939SAndy Fiddaman if(sffileno(iop)>=0)
211b30d1939SAndy Fiddaman lp->lexd.docend = sfsetbuf(iop,(Void_t*)iop,0);
212b30d1939SAndy Fiddaman else
213b30d1939SAndy Fiddaman lp->lexd.docend = fcfirst();
21434f9b3eeSRoland Mainz }
2157c2fbfb3SApril Chin if(lp->lexd.first)
216da2e3ebdSchin {
2177c2fbfb3SApril Chin size -= (lp->lexd.first-(char*)buff);
2187c2fbfb3SApril Chin buff = lp->lexd.first;
2197c2fbfb3SApril Chin if(!lp->lexd.noarg)
2207c2fbfb3SApril Chin lp->arg = (struct argnod*)stkseek(stkp,ARGVAL);
221da2e3ebdSchin #if SHOPT_KIA
2227c2fbfb3SApril Chin lp->lexd.kiaoff += ARGVAL;
223da2e3ebdSchin #endif /* SHOPT_KIA */
224da2e3ebdSchin }
2257c2fbfb3SApril Chin if(size>0 && (lp->arg||lp->lexd.noarg))
226da2e3ebdSchin {
2277c2fbfb3SApril Chin sfwrite(stkp,buff,size);
2287c2fbfb3SApril Chin lp->lexd.first = 0;
229da2e3ebdSchin }
230da2e3ebdSchin }
231da2e3ebdSchin
232da2e3ebdSchin /*
233da2e3ebdSchin * fill up another input buffer
234da2e3ebdSchin * preserves lexical state
235da2e3ebdSchin */
lexfill(Lex_t * lp)2367c2fbfb3SApril Chin static int lexfill(Lex_t *lp)
237da2e3ebdSchin {
238da2e3ebdSchin register int c;
2397c2fbfb3SApril Chin Lex_t savelex;
240da2e3ebdSchin struct argnod *ap;
24134f9b3eeSRoland Mainz int aok,docextra;
2427c2fbfb3SApril Chin savelex = *lp;
2437c2fbfb3SApril Chin ap = lp->arg;
244da2e3ebdSchin c = fcfill();
245da2e3ebdSchin if(ap)
2467c2fbfb3SApril Chin lp->arg = ap;
24734f9b3eeSRoland Mainz docextra = lp->lexd.docextra;
2487c2fbfb3SApril Chin lp->lex = savelex.lex;
2497c2fbfb3SApril Chin lp->lexd = savelex.lexd;
2507c2fbfb3SApril Chin if(fcfile() || c)
2517c2fbfb3SApril Chin lp->lexd.first = 0;
2527c2fbfb3SApril Chin aok= lp->aliasok;
2537c2fbfb3SApril Chin ap = lp->arg;
2547c2fbfb3SApril Chin memcpy(lp, &savelex, offsetof(Lex_t,lexd));
2557c2fbfb3SApril Chin lp->arg = ap;
2567c2fbfb3SApril Chin lp->aliasok = aok;
25734f9b3eeSRoland Mainz if(lp->lexd.docword && docextra)
25834f9b3eeSRoland Mainz {
25934f9b3eeSRoland Mainz lp->lexd.docextra = docextra;
26034f9b3eeSRoland Mainz lp->lexd.docend = fcseek(0)-1;
26134f9b3eeSRoland Mainz }
262da2e3ebdSchin return(c);
263da2e3ebdSchin }
264da2e3ebdSchin
265da2e3ebdSchin /*
266da2e3ebdSchin * mode=1 for reinitialization
267da2e3ebdSchin */
sh_lexopen(Lex_t * lp,Shell_t * sp,int mode)268da2e3ebdSchin Lex_t *sh_lexopen(Lex_t *lp, Shell_t *sp, int mode)
269da2e3ebdSchin {
270da2e3ebdSchin if(!lp)
271da2e3ebdSchin {
272da2e3ebdSchin lp = (Lex_t*)newof(0,Lex_t,1,0);
2737c2fbfb3SApril Chin lp->sh = sp;
274da2e3ebdSchin }
2757c2fbfb3SApril Chin fcnotify(lex_advance,lp);
2767c2fbfb3SApril Chin lp->lex.intest = lp->lex.incase = lp->lex.skipword = lp->lexd.warn = 0;
2777c2fbfb3SApril Chin lp->comp_assign = 0;
2787c2fbfb3SApril Chin lp->lex.reservok = 1;
279da2e3ebdSchin if(!sh_isoption(SH_DICTIONARY) && sh_isoption(SH_NOEXEC))
2807c2fbfb3SApril Chin lp->lexd.warn=1;
281da2e3ebdSchin if(!mode)
282da2e3ebdSchin {
2837c2fbfb3SApril Chin lp->lexd.noarg = lp->lexd.level= lp->lexd.dolparen = lp->lexd.balance = 0;
2847c2fbfb3SApril Chin lp->lexd.nocopy = lp->lexd.docword = lp->lexd.nest = lp->lexd.paren = 0;
2853e14f97fSRoger A. Faulkner lp->lexd.lex_state = lp->lexd.lastc=0;
286b30d1939SAndy Fiddaman lp->lexd.docend = 0;
287b30d1939SAndy Fiddaman lp->lexd.nested_tilde = 0;
288da2e3ebdSchin }
2897c2fbfb3SApril Chin lp->comsub = 0;
290da2e3ebdSchin return(lp);
291da2e3ebdSchin }
292da2e3ebdSchin
293da2e3ebdSchin #ifdef DBUG
2947c2fbfb3SApril Chin extern int lextoken(Lex_t*);
sh_lex(Lex_t * lp)2957c2fbfb3SApril Chin int sh_lex(Lex_t *lp)
296da2e3ebdSchin {
2977c2fbfb3SApril Chin Shell_t *shp = lp->sh;
298da2e3ebdSchin register int flag;
299da2e3ebdSchin char *quoted, *macro, *split, *expand;
300da2e3ebdSchin char tokstr[3];
301b30d1939SAndy Fiddaman register int tok = lextoken(lp);
302da2e3ebdSchin quoted = macro = split = expand = "";
3037c2fbfb3SApril Chin if(tok==0 && (flag=lp->arg->argflag))
304da2e3ebdSchin {
305da2e3ebdSchin if(flag&ARG_MAC)
306da2e3ebdSchin macro = "macro:";
307da2e3ebdSchin if(flag&ARG_EXP)
308da2e3ebdSchin expand = "expand:";
309da2e3ebdSchin if(flag&ARG_QUOTED)
310da2e3ebdSchin quoted = "quoted:";
311da2e3ebdSchin }
312b30d1939SAndy Fiddaman sfprintf(sfstderr,"%d: line %d: %o:%s%s%s%s %s\n",getpid(),shp->inlineno,tok,quoted,
313da2e3ebdSchin macro, split, expand, fmttoken(lp,tok,tokstr));
314da2e3ebdSchin return(tok);
315da2e3ebdSchin }
316da2e3ebdSchin #define sh_lex lextoken
317da2e3ebdSchin #endif
318da2e3ebdSchin
319da2e3ebdSchin /*
320da2e3ebdSchin * Get the next word and put it on the top of the stak
3217c2fbfb3SApril Chin * A pointer to the current word is stored in lp->arg
322da2e3ebdSchin * Returns the token type
323da2e3ebdSchin */
sh_lex(Lex_t * lp)3247c2fbfb3SApril Chin int sh_lex(Lex_t* lp)
325da2e3ebdSchin {
3267c2fbfb3SApril Chin register Shell_t *shp = lp->sh;
327da2e3ebdSchin register const char *state;
3287c2fbfb3SApril Chin register int n, c, mode=ST_BEGIN, wordflags=0;
3297c2fbfb3SApril Chin Stk_t *stkp = shp->stk;
3307c2fbfb3SApril Chin int inlevel=lp->lexd.level, assignment=0, ingrave=0;
331b30d1939SAndy Fiddaman int epatchar=0;
332da2e3ebdSchin Sfio_t *sp;
333da2e3ebdSchin #if SHOPT_MULTIBYTE
334da2e3ebdSchin LEN=1;
335da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
3367c2fbfb3SApril Chin if(lp->lexd.paren)
337da2e3ebdSchin {
3387c2fbfb3SApril Chin lp->lexd.paren = 0;
3397c2fbfb3SApril Chin return(lp->token=LPAREN);
340da2e3ebdSchin }
341b30d1939SAndy Fiddaman if(lp->noreserv)
342b30d1939SAndy Fiddaman {
343b30d1939SAndy Fiddaman lp->lex.reservok = 0;
344b30d1939SAndy Fiddaman while((fcgetc(c)) && c==' ' || c== '\t' || c=='\n');
345b30d1939SAndy Fiddaman fcseek(-LEN);
346b30d1939SAndy Fiddaman if(c=='[')
347b30d1939SAndy Fiddaman lp->assignok = SH_ASSIGN;
348b30d1939SAndy Fiddaman }
3497c2fbfb3SApril Chin if(lp->lex.incase)
3507c2fbfb3SApril Chin lp->assignok = 0;
351da2e3ebdSchin else
3527c2fbfb3SApril Chin lp->assignok |= lp->lex.reservok;
3537c2fbfb3SApril Chin if(lp->comp_assign==2)
3547c2fbfb3SApril Chin lp->comp_assign = lp->lex.reservok = 0;
3557c2fbfb3SApril Chin lp->lexd.arith = (lp->lexd.nest==1);
3567c2fbfb3SApril Chin if(lp->lexd.nest)
357da2e3ebdSchin {
3587c2fbfb3SApril Chin pushlevel(lp,lp->lexd.nest,ST_NONE);
3597c2fbfb3SApril Chin lp->lexd.nest = 0;
3607c2fbfb3SApril Chin mode = lp->lexd.lex_state;
361da2e3ebdSchin }
3627c2fbfb3SApril Chin else if(lp->lexd.docword)
363da2e3ebdSchin {
364da2e3ebdSchin if(fcgetc(c)=='-' || c=='#')
365da2e3ebdSchin {
3667c2fbfb3SApril Chin lp->lexd.docword++;
3677c2fbfb3SApril Chin lp->digits=(c=='#'?3:1);
368da2e3ebdSchin }
369da2e3ebdSchin else if(c=='<')
370da2e3ebdSchin {
3717c2fbfb3SApril Chin lp->digits=2;
3727c2fbfb3SApril Chin lp->lexd.docword=0;
373da2e3ebdSchin }
374da2e3ebdSchin else if(c>0)
375b30d1939SAndy Fiddaman fcseek(-LEN);
376da2e3ebdSchin }
3777c2fbfb3SApril Chin if(!lp->lexd.dolparen)
378da2e3ebdSchin {
3797c2fbfb3SApril Chin lp->arg = 0;
380da2e3ebdSchin if(mode!=ST_BEGIN)
3817c2fbfb3SApril Chin lp->lexd.first = fcseek(0);
382da2e3ebdSchin else
3837c2fbfb3SApril Chin lp->lexd.first = 0;
384da2e3ebdSchin }
3857c2fbfb3SApril Chin lp->lastline = lp->sh->inlineno;
386da2e3ebdSchin while(1)
387da2e3ebdSchin {
388da2e3ebdSchin /* skip over characters in the current state */
389da2e3ebdSchin state = sh_lexstates[mode];
390da2e3ebdSchin while((n=STATE(state,c))==0);
391da2e3ebdSchin switch(n)
392da2e3ebdSchin {
393da2e3ebdSchin case S_BREAK:
394b30d1939SAndy Fiddaman fcseek(-LEN);
395da2e3ebdSchin goto breakloop;
396da2e3ebdSchin case S_EOF:
397da2e3ebdSchin sp = fcfile();
3987c2fbfb3SApril Chin if((n=lexfill(lp)) > 0)
399da2e3ebdSchin {
400da2e3ebdSchin fcseek(-1);
401da2e3ebdSchin continue;
402da2e3ebdSchin }
403da2e3ebdSchin /* check for zero byte in file */
404da2e3ebdSchin if(n==0 && fcfile())
405da2e3ebdSchin {
406da2e3ebdSchin if(shp->readscript)
407da2e3ebdSchin {
408da2e3ebdSchin char *cp = error_info.id;
409da2e3ebdSchin errno = ENOEXEC;
410da2e3ebdSchin error_info.id = shp->readscript;
411da2e3ebdSchin errormsg(SH_DICT,ERROR_system(ERROR_NOEXEC),e_exec,cp);
412da2e3ebdSchin }
413da2e3ebdSchin else
414da2e3ebdSchin {
4157c2fbfb3SApril Chin lp->token = -1;
4167c2fbfb3SApril Chin sh_syntax(lp);
417da2e3ebdSchin }
418da2e3ebdSchin }
419da2e3ebdSchin /* end-of-file */
420da2e3ebdSchin if(mode==ST_BEGIN)
4217c2fbfb3SApril Chin return(lp->token=EOFSYM);
4227c2fbfb3SApril Chin if(mode >ST_NORM && lp->lexd.level>0)
423da2e3ebdSchin {
4247c2fbfb3SApril Chin switch(c=endchar(lp))
425da2e3ebdSchin {
426da2e3ebdSchin case '$':
427da2e3ebdSchin if(mode==ST_LIT)
428da2e3ebdSchin {
429da2e3ebdSchin c = '\'';
430da2e3ebdSchin break;
431da2e3ebdSchin }
4327c2fbfb3SApril Chin mode = oldmode(lp);
4337c2fbfb3SApril Chin poplevel(lp);
434da2e3ebdSchin continue;
435da2e3ebdSchin case RBRACT:
436da2e3ebdSchin c = LBRACT;
437da2e3ebdSchin break;
438da2e3ebdSchin case 1: /* for ((...)) */
439da2e3ebdSchin case RPAREN:
440da2e3ebdSchin c = LPAREN;
441da2e3ebdSchin break;
442da2e3ebdSchin default:
443da2e3ebdSchin c = LBRACE;
444da2e3ebdSchin break;
445da2e3ebdSchin case '"': case '`': case '\'':
4467c2fbfb3SApril Chin lp->lexd.balance = c;
447da2e3ebdSchin break;
448da2e3ebdSchin }
449da2e3ebdSchin if(sp && !(sfset(sp,0,0)&SF_STRING))
450da2e3ebdSchin {
4517c2fbfb3SApril Chin lp->lasttok = c;
4527c2fbfb3SApril Chin lp->token = EOFSYM;
4537c2fbfb3SApril Chin sh_syntax(lp);
454da2e3ebdSchin }
4557c2fbfb3SApril Chin lp->lexd.balance = c;
456da2e3ebdSchin }
457da2e3ebdSchin goto breakloop;
458da2e3ebdSchin case S_COM:
459da2e3ebdSchin /* skip one or more comment line(s) */
4607c2fbfb3SApril Chin lp->lex.reservok = !lp->lex.intest;
4617c2fbfb3SApril Chin if((n=lp->lexd.nocopy) && lp->lexd.dolparen)
4627c2fbfb3SApril Chin lp->lexd.nocopy--;
463da2e3ebdSchin do
464da2e3ebdSchin {
465da2e3ebdSchin while(fcgetc(c)>0 && c!='\n');
4667c2fbfb3SApril Chin if(c<=0 || lp->heredoc)
467b30d1939SAndy Fiddaman {
468b30d1939SAndy Fiddaman shp->inlineno++;
469da2e3ebdSchin break;
470b30d1939SAndy Fiddaman }
471da2e3ebdSchin while(shp->inlineno++,fcpeek(0)=='\n')
472da2e3ebdSchin fcseek(1);
473da2e3ebdSchin while(state[c=fcpeek(0)]==0)
474da2e3ebdSchin fcseek(1);
475da2e3ebdSchin }
476da2e3ebdSchin while(c=='#');
4777c2fbfb3SApril Chin lp->lexd.nocopy = n;
478da2e3ebdSchin if(c<0)
4797c2fbfb3SApril Chin return(lp->token=EOFSYM);
480da2e3ebdSchin n = S_NLTOK;
481da2e3ebdSchin shp->inlineno--;
482da2e3ebdSchin /* FALL THRU */
483da2e3ebdSchin case S_NLTOK:
484da2e3ebdSchin /* check for here-document */
4857c2fbfb3SApril Chin if(lp->heredoc)
486da2e3ebdSchin {
4877c2fbfb3SApril Chin if(!lp->lexd.dolparen)
4887c2fbfb3SApril Chin lp->lexd.nocopy++;
489da2e3ebdSchin c = shp->inlineno;
4907c2fbfb3SApril Chin if(here_copy(lp,lp->heredoc)<=0 && lp->lasttok)
491da2e3ebdSchin {
4927c2fbfb3SApril Chin lp->lasttok = IODOCSYM;
4937c2fbfb3SApril Chin lp->token = EOFSYM;
4947c2fbfb3SApril Chin lp->lastline = c;
4957c2fbfb3SApril Chin sh_syntax(lp);
496da2e3ebdSchin }
4977c2fbfb3SApril Chin if(!lp->lexd.dolparen)
4987c2fbfb3SApril Chin lp->lexd.nocopy--;
4997c2fbfb3SApril Chin lp->heredoc = 0;
500da2e3ebdSchin }
5017c2fbfb3SApril Chin lp->lex.reservok = !lp->lex.intest;
5027c2fbfb3SApril Chin lp->lex.skipword = 0;
5035ae8bd53SToomas Soome /* FALLTHROUGH */
504da2e3ebdSchin case S_NL:
505da2e3ebdSchin /* skip over new-lines */
5067c2fbfb3SApril Chin lp->lex.last_quote = 0;
507da2e3ebdSchin while(shp->inlineno++,fcget()=='\n');
508b30d1939SAndy Fiddaman fcseek(-LEN);
509da2e3ebdSchin if(n==S_NLTOK)
510da2e3ebdSchin {
5117c2fbfb3SApril Chin lp->comp_assign = 0;
5127c2fbfb3SApril Chin return(lp->token='\n');
513da2e3ebdSchin }
5145ae8bd53SToomas Soome /* FALLTHROUGH */
515da2e3ebdSchin case S_BLNK:
5167c2fbfb3SApril Chin if(lp->lex.incase<=TEST_RE)
517da2e3ebdSchin continue;
518da2e3ebdSchin /* implicit RPAREN for =~ test operator */
5197c2fbfb3SApril Chin if(inlevel+1==lp->lexd.level)
520da2e3ebdSchin {
5217c2fbfb3SApril Chin if(lp->lex.intest)
522b30d1939SAndy Fiddaman fcseek(-LEN);
523da2e3ebdSchin c = RPAREN;
524da2e3ebdSchin goto do_pop;
525da2e3ebdSchin }
526da2e3ebdSchin continue;
527da2e3ebdSchin case S_OP:
528da2e3ebdSchin /* return operator token */
529da2e3ebdSchin if(c=='<' || c=='>')
530da2e3ebdSchin {
5317c2fbfb3SApril Chin if(lp->lex.testop2)
5327c2fbfb3SApril Chin lp->lex.testop2 = 0;
533da2e3ebdSchin else
534da2e3ebdSchin {
5357c2fbfb3SApril Chin lp->digits = (c=='>');
5367c2fbfb3SApril Chin lp->lex.skipword = 1;
5377c2fbfb3SApril Chin lp->aliasok = lp->lex.reservok;
538b30d1939SAndy Fiddaman if(lp->lex.incase<2)
539b30d1939SAndy Fiddaman lp->lex.reservok = 0;
540da2e3ebdSchin }
541da2e3ebdSchin }
542da2e3ebdSchin else
543da2e3ebdSchin {
5447c2fbfb3SApril Chin lp->lex.reservok = !lp->lex.intest;
545da2e3ebdSchin if(c==RPAREN)
546da2e3ebdSchin {
5477c2fbfb3SApril Chin if(!lp->lexd.dolparen)
5487c2fbfb3SApril Chin lp->lex.incase = 0;
5497c2fbfb3SApril Chin return(lp->token=c);
550da2e3ebdSchin }
5517c2fbfb3SApril Chin lp->lex.testop1 = lp->lex.intest;
552da2e3ebdSchin }
553da2e3ebdSchin if(fcgetc(n)>0)
554b30d1939SAndy Fiddaman fcseek(-LEN);
555da2e3ebdSchin if(state[n]==S_OP || n=='#')
556da2e3ebdSchin {
557da2e3ebdSchin if(n==c)
558da2e3ebdSchin {
559da2e3ebdSchin if(c=='<')
5607c2fbfb3SApril Chin lp->lexd.docword=1;
561da2e3ebdSchin else if(n==LPAREN)
562da2e3ebdSchin {
563b30d1939SAndy Fiddaman if(lp->lex.intest)
564b30d1939SAndy Fiddaman return(c);
5657c2fbfb3SApril Chin lp->lexd.nest=1;
5667c2fbfb3SApril Chin lp->lastline = shp->inlineno;
5677c2fbfb3SApril Chin lp->lexd.lex_state = ST_NESTED;
568da2e3ebdSchin fcseek(1);
5697c2fbfb3SApril Chin return(sh_lex(lp));
570da2e3ebdSchin }
571da2e3ebdSchin c |= SYMREP;
572da2e3ebdSchin }
573da2e3ebdSchin else if(c=='(' || c==')')
5747c2fbfb3SApril Chin return(lp->token=c);
575da2e3ebdSchin else if(c=='&')
576da2e3ebdSchin {
57734f9b3eeSRoland Mainz if(!sh_isoption(SH_POSIX) && n=='>' && (sh_isoption(SH_BASH) || sh_isstate(SH_PROFILE)))
578da2e3ebdSchin {
57934f9b3eeSRoland Mainz if(!sh_isoption(SH_BASH) && !lp->nonstandard)
58034f9b3eeSRoland Mainz {
58134f9b3eeSRoland Mainz lp->nonstandard = 1;
58234f9b3eeSRoland Mainz errormsg(SH_DICT,ERROR_warn(0),e_lexnonstandard,shp->inlineno);
58334f9b3eeSRoland Mainz }
5847c2fbfb3SApril Chin lp->digits = -1;
585da2e3ebdSchin c = '>';
586da2e3ebdSchin }
587b30d1939SAndy Fiddaman else if(n=='|')
588b30d1939SAndy Fiddaman c |= SYMPIPE;
589da2e3ebdSchin else
590da2e3ebdSchin n = 0;
591da2e3ebdSchin }
592da2e3ebdSchin else if(n=='&')
593da2e3ebdSchin c |= SYMAMP;
594da2e3ebdSchin else if(c!='<' && c!='>')
595da2e3ebdSchin n = 0;
596da2e3ebdSchin else if(n==LPAREN)
597da2e3ebdSchin {
598da2e3ebdSchin c |= SYMLPAR;
5997c2fbfb3SApril Chin lp->lex.reservok = 1;
6007c2fbfb3SApril Chin lp->lex.skipword = 0;
601da2e3ebdSchin }
602da2e3ebdSchin else if(n=='|')
603da2e3ebdSchin c |= SYMPIPE;
604da2e3ebdSchin else if(c=='<' && n=='>')
60534f9b3eeSRoland Mainz {
60634f9b3eeSRoland Mainz lp->digits = 1;
607da2e3ebdSchin c = IORDWRSYM;
60834f9b3eeSRoland Mainz fcgetc(n);
60934f9b3eeSRoland Mainz if(fcgetc(n)==';')
61034f9b3eeSRoland Mainz {
61134f9b3eeSRoland Mainz lp->token = c = IORDWRSYMT;
61234f9b3eeSRoland Mainz if(lp->inexec)
61334f9b3eeSRoland Mainz sh_syntax(lp);
61434f9b3eeSRoland Mainz }
61534f9b3eeSRoland Mainz else if(n>0)
616b30d1939SAndy Fiddaman fcseek(-LEN);
61734f9b3eeSRoland Mainz n= 0;
61834f9b3eeSRoland Mainz }
619da2e3ebdSchin else if(n=='#' && (c=='<'||c=='>'))
620da2e3ebdSchin c |= SYMSHARP;
6217c2fbfb3SApril Chin else if(n==';' && c=='>')
6227c2fbfb3SApril Chin {
6237c2fbfb3SApril Chin c |= SYMSEMI;
6247c2fbfb3SApril Chin if(lp->inexec)
6257c2fbfb3SApril Chin {
6267c2fbfb3SApril Chin lp->token = c;
6277c2fbfb3SApril Chin sh_syntax(lp);
6287c2fbfb3SApril Chin }
6297c2fbfb3SApril Chin }
630da2e3ebdSchin else
631da2e3ebdSchin n = 0;
632da2e3ebdSchin if(n)
633da2e3ebdSchin {
634da2e3ebdSchin fcseek(1);
6357c2fbfb3SApril Chin lp->lex.incase = (c==BREAKCASESYM || c==FALLTHRUSYM);
636da2e3ebdSchin }
637da2e3ebdSchin else
638da2e3ebdSchin {
63934f9b3eeSRoland Mainz if(lp->lexd.warn && (n=fcpeek(0))!=RPAREN && n!=' ' && n!='\t')
640da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),e_lexspace,shp->inlineno,c,n);
641da2e3ebdSchin }
642da2e3ebdSchin }
6437c2fbfb3SApril Chin if(c==LPAREN && lp->comp_assign && !lp->lex.intest && !lp->lex.incase)
6447c2fbfb3SApril Chin lp->comp_assign = 2;
645da2e3ebdSchin else
6467c2fbfb3SApril Chin lp->comp_assign = 0;
6477c2fbfb3SApril Chin return(lp->token=c);
648da2e3ebdSchin case S_ESC:
649da2e3ebdSchin /* check for \<new-line> */
650da2e3ebdSchin fcgetc(n);
651da2e3ebdSchin c=2;
652da2e3ebdSchin #if SHOPT_CRNL
653da2e3ebdSchin if(n=='\r')
654da2e3ebdSchin {
655da2e3ebdSchin if(fcgetc(n)=='\n')
656da2e3ebdSchin c=3;
657da2e3ebdSchin else
658da2e3ebdSchin {
659da2e3ebdSchin n='\r';
660b30d1939SAndy Fiddaman fcseek(-LEN);
661da2e3ebdSchin }
662da2e3ebdSchin }
663da2e3ebdSchin #endif /* SHOPT_CRNL */
664da2e3ebdSchin if(n=='\n')
665da2e3ebdSchin {
666da2e3ebdSchin Sfio_t *sp;
667da2e3ebdSchin struct argnod *ap;
668da2e3ebdSchin shp->inlineno++;
669da2e3ebdSchin /* synchronize */
670da2e3ebdSchin if(!(sp=fcfile()))
671da2e3ebdSchin state=fcseek(0);
672da2e3ebdSchin fcclose();
6737c2fbfb3SApril Chin ap = lp->arg;
674da2e3ebdSchin if(sp)
675da2e3ebdSchin fcfopen(sp);
676da2e3ebdSchin else
677da2e3ebdSchin fcsopen((char*)state);
678da2e3ebdSchin /* remove \new-line */
6797c2fbfb3SApril Chin n = stktell(stkp)-c;
6807c2fbfb3SApril Chin stkseek(stkp,n);
6817c2fbfb3SApril Chin lp->arg = ap;
682da2e3ebdSchin if(n<=ARGVAL)
683da2e3ebdSchin {
684da2e3ebdSchin mode = 0;
6857c2fbfb3SApril Chin lp->lexd.first = 0;
686da2e3ebdSchin }
687da2e3ebdSchin continue;
688da2e3ebdSchin }
689da2e3ebdSchin wordflags |= ARG_QUOTED;
690da2e3ebdSchin if(mode==ST_DOL)
691da2e3ebdSchin goto err;
692da2e3ebdSchin #ifndef STR_MAXIMAL
6937c2fbfb3SApril Chin else if(mode==ST_NESTED && lp->lexd.warn &&
6947c2fbfb3SApril Chin endchar(lp)==RBRACE &&
695da2e3ebdSchin sh_lexstates[ST_DOL][n]==S_DIG
696da2e3ebdSchin )
697da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),e_lexfuture,shp->inlineno,n);
698da2e3ebdSchin #endif /* STR_MAXIMAL */
699da2e3ebdSchin break;
700da2e3ebdSchin case S_NAME:
7017c2fbfb3SApril Chin if(!lp->lex.skipword)
7027c2fbfb3SApril Chin lp->lex.reservok *= 2;
703da2e3ebdSchin /* FALL THRU */
704da2e3ebdSchin case S_TILDE:
705b30d1939SAndy Fiddaman if(c=='~' && mode==ST_NESTED)
706b30d1939SAndy Fiddaman {
707b30d1939SAndy Fiddaman if(endchar(lp)==RBRACE)
708b30d1939SAndy Fiddaman {
709b30d1939SAndy Fiddaman lp->lexd.nested_tilde++;
710b30d1939SAndy Fiddaman goto tilde;
711b30d1939SAndy Fiddaman }
712b30d1939SAndy Fiddaman continue;
713b30d1939SAndy Fiddaman }
714b30d1939SAndy Fiddaman /* FALLTHROUGH */
715da2e3ebdSchin case S_RES:
7167c2fbfb3SApril Chin if(!lp->lexd.dolparen)
7177c2fbfb3SApril Chin lp->lexd.first = fcseek(0)-LEN;
7187c2fbfb3SApril Chin else if(lp->lexd.docword)
7197c2fbfb3SApril Chin lp->lexd.docend = fcseek(0)-LEN;
720da2e3ebdSchin mode = ST_NAME;
721da2e3ebdSchin if(c=='.')
722b30d1939SAndy Fiddaman fcseek(-LEN);
723da2e3ebdSchin if(n!=S_TILDE)
724da2e3ebdSchin continue;
725b30d1939SAndy Fiddaman tilde:
726da2e3ebdSchin fcgetc(n);
727da2e3ebdSchin if(n>0)
7287c2fbfb3SApril Chin {
729b30d1939SAndy Fiddaman if(c=='~' && n==LPAREN)
730b30d1939SAndy Fiddaman {
731b30d1939SAndy Fiddaman if(lp->lexd.nested_tilde)
732b30d1939SAndy Fiddaman lp->lexd.nested_tilde++;
733b30d1939SAndy Fiddaman else if(lp->lex.incase)
734b30d1939SAndy Fiddaman lp->lex.incase = TEST_RE;
735b30d1939SAndy Fiddaman }
736b30d1939SAndy Fiddaman fcseek(-LEN);
737b30d1939SAndy Fiddaman if(lp->lexd.nested_tilde)
738b30d1939SAndy Fiddaman {
739b30d1939SAndy Fiddaman lp->lexd.nested_tilde--;
740b30d1939SAndy Fiddaman continue;
741b30d1939SAndy Fiddaman }
7427c2fbfb3SApril Chin }
743da2e3ebdSchin if(n==LPAREN)
744da2e3ebdSchin goto epat;
745da2e3ebdSchin wordflags = ARG_MAC;
746da2e3ebdSchin mode = ST_NORM;
747da2e3ebdSchin continue;
748da2e3ebdSchin case S_REG:
749da2e3ebdSchin if(mode==ST_BEGIN)
750da2e3ebdSchin {
7517c2fbfb3SApril Chin do_reg:
752da2e3ebdSchin /* skip new-line joining */
753da2e3ebdSchin if(c=='\\' && fcpeek(0)=='\n')
754da2e3ebdSchin {
755da2e3ebdSchin shp->inlineno++;
756da2e3ebdSchin fcseek(1);
757da2e3ebdSchin continue;
758da2e3ebdSchin }
759b30d1939SAndy Fiddaman fcseek(-LEN);
7607c2fbfb3SApril Chin if(!lp->lexd.dolparen)
7617c2fbfb3SApril Chin lp->lexd.first = fcseek(0);
7627c2fbfb3SApril Chin else if(lp->lexd.docword)
7637c2fbfb3SApril Chin lp->lexd.docend = fcseek(0);
7647c2fbfb3SApril Chin if(c=='[' && lp->assignok>=SH_ASSIGN)
765da2e3ebdSchin {
766da2e3ebdSchin mode = ST_NAME;
767da2e3ebdSchin continue;
768da2e3ebdSchin }
769da2e3ebdSchin }
770da2e3ebdSchin mode = ST_NORM;
771da2e3ebdSchin continue;
772da2e3ebdSchin case S_LIT:
7737c2fbfb3SApril Chin if(oldmode(lp)==ST_NONE && !lp->lexd.noarg) /* in ((...)) */
774da2e3ebdSchin {
775da2e3ebdSchin if((c=fcpeek(0))==LPAREN || c==RPAREN || c=='$' || c==LBRACE || c==RBRACE || c=='[' || c==']')
776da2e3ebdSchin {
777da2e3ebdSchin if(fcpeek(1)=='\'')
778da2e3ebdSchin fcseek(2);
779da2e3ebdSchin }
780da2e3ebdSchin continue;
781da2e3ebdSchin }
782da2e3ebdSchin wordflags |= ARG_QUOTED;
783da2e3ebdSchin if(mode==ST_DOL)
784da2e3ebdSchin {
7857c2fbfb3SApril Chin if(endchar(lp)!='$')
786da2e3ebdSchin goto err;
7877c2fbfb3SApril Chin if(oldmode(lp)==ST_QUOTE) /* $' within "" or `` */
788da2e3ebdSchin {
7897c2fbfb3SApril Chin if(lp->lexd.warn)
790da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),e_lexslash,shp->inlineno);
791da2e3ebdSchin mode = ST_LIT;
792da2e3ebdSchin }
793da2e3ebdSchin }
794da2e3ebdSchin if(mode!=ST_LIT)
795da2e3ebdSchin {
796b30d1939SAndy Fiddaman if(lp->lexd.warn && lp->lex.last_quote && shp->inlineno > lp->lastline && fcpeek(-2)!='$')
7977c2fbfb3SApril Chin errormsg(SH_DICT,ERROR_warn(0),e_lexlongquote,lp->lastline,lp->lex.last_quote);
7987c2fbfb3SApril Chin lp->lex.last_quote = 0;
7997c2fbfb3SApril Chin lp->lastline = shp->inlineno;
800da2e3ebdSchin if(mode!=ST_DOL)
8017c2fbfb3SApril Chin pushlevel(lp,'\'',mode);
802da2e3ebdSchin mode = ST_LIT;
803da2e3ebdSchin continue;
804da2e3ebdSchin }
805da2e3ebdSchin /* check for multi-line single-quoted string */
8067c2fbfb3SApril Chin else if(shp->inlineno > lp->lastline)
8077c2fbfb3SApril Chin lp->lex.last_quote = '\'';
8087c2fbfb3SApril Chin mode = oldmode(lp);
8097c2fbfb3SApril Chin poplevel(lp);
810da2e3ebdSchin break;
811da2e3ebdSchin case S_ESC2:
812da2e3ebdSchin /* \ inside '' */
8137c2fbfb3SApril Chin if(endchar(lp)=='$')
814da2e3ebdSchin {
815da2e3ebdSchin fcgetc(n);
816da2e3ebdSchin if(n=='\n')
817da2e3ebdSchin shp->inlineno++;
818da2e3ebdSchin }
819da2e3ebdSchin continue;
820da2e3ebdSchin case S_GRAVE:
8217c2fbfb3SApril Chin if(lp->lexd.warn && (mode!=ST_QUOTE || endchar(lp)!='`'))
822da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete1,shp->inlineno);
823da2e3ebdSchin wordflags |=(ARG_MAC|ARG_EXP);
824da2e3ebdSchin if(mode==ST_QUOTE)
825da2e3ebdSchin ingrave = !ingrave;
826da2e3ebdSchin /* FALL THRU */
827da2e3ebdSchin case S_QUOTE:
8287c2fbfb3SApril Chin if(oldmode(lp)==ST_NONE && lp->lexd.arith) /* in ((...)) */
8297c2fbfb3SApril Chin {
8307c2fbfb3SApril Chin if(n!=S_GRAVE || fcpeek(0)=='\'')
8317c2fbfb3SApril Chin continue;
8327c2fbfb3SApril Chin }
833da2e3ebdSchin if(n==S_QUOTE)
834da2e3ebdSchin wordflags |=ARG_QUOTED;
835da2e3ebdSchin if(mode!=ST_QUOTE)
836da2e3ebdSchin {
837da2e3ebdSchin if(c!='"' || mode!=ST_QNEST)
838da2e3ebdSchin {
8397c2fbfb3SApril Chin if(lp->lexd.warn && lp->lex.last_quote && shp->inlineno > lp->lastline)
8407c2fbfb3SApril Chin errormsg(SH_DICT,ERROR_warn(0),e_lexlongquote,lp->lastline,lp->lex.last_quote);
8417c2fbfb3SApril Chin lp->lex.last_quote=0;
8427c2fbfb3SApril Chin lp->lastline = shp->inlineno;
8437c2fbfb3SApril Chin pushlevel(lp,c,mode);
844da2e3ebdSchin }
84534f9b3eeSRoland Mainz ingrave ^= (c=='`');
846da2e3ebdSchin mode = ST_QUOTE;
847da2e3ebdSchin continue;
848da2e3ebdSchin }
8497c2fbfb3SApril Chin else if((n=endchar(lp))==c)
850da2e3ebdSchin {
8517c2fbfb3SApril Chin if(shp->inlineno > lp->lastline)
8527c2fbfb3SApril Chin lp->lex.last_quote = c;
8537c2fbfb3SApril Chin mode = oldmode(lp);
8547c2fbfb3SApril Chin poplevel(lp);
855da2e3ebdSchin }
856da2e3ebdSchin else if(c=='"' && n==RBRACE)
857da2e3ebdSchin mode = ST_QNEST;
858da2e3ebdSchin break;
859da2e3ebdSchin case S_DOL:
860da2e3ebdSchin /* don't check syntax inside `` */
861da2e3ebdSchin if(mode==ST_QUOTE && ingrave)
862da2e3ebdSchin continue;
863da2e3ebdSchin #if SHOPT_KIA
8647c2fbfb3SApril Chin if(lp->lexd.first)
8657c2fbfb3SApril Chin lp->lexd.kiaoff = fcseek(0)-lp->lexd.first;
866da2e3ebdSchin else
8677c2fbfb3SApril Chin lp->lexd.kiaoff = stktell(stkp)+fcseek(0)-fcfirst();
868da2e3ebdSchin #endif /* SHOPT_KIA */
8697c2fbfb3SApril Chin pushlevel(lp,'$',mode);
870da2e3ebdSchin mode = ST_DOL;
871da2e3ebdSchin continue;
872da2e3ebdSchin case S_PAR:
8737c2fbfb3SApril Chin do_comsub:
874da2e3ebdSchin wordflags |= ARG_MAC;
8757c2fbfb3SApril Chin mode = oldmode(lp);
8767c2fbfb3SApril Chin poplevel(lp);
877b30d1939SAndy Fiddaman fcseek(-LEN);
878b30d1939SAndy Fiddaman n = lp->digits;
8797c2fbfb3SApril Chin wordflags |= comsub(lp,c);
880b30d1939SAndy Fiddaman lp->digits = n;
881da2e3ebdSchin continue;
882da2e3ebdSchin case S_RBRA:
8837c2fbfb3SApril Chin if((n=endchar(lp)) == '$')
884da2e3ebdSchin goto err;
885da2e3ebdSchin if(mode!=ST_QUOTE || n==RBRACE)
886da2e3ebdSchin {
8877c2fbfb3SApril Chin mode = oldmode(lp);
8887c2fbfb3SApril Chin poplevel(lp);
889da2e3ebdSchin }
890da2e3ebdSchin break;
891da2e3ebdSchin case S_EDOL:
892da2e3ebdSchin /* end $identifier */
893da2e3ebdSchin #if SHOPT_KIA
8947c2fbfb3SApril Chin if(lp->kiafile)
8957c2fbfb3SApril Chin refvar(lp,0);
896da2e3ebdSchin #endif /* SHOPT_KIA */
8977c2fbfb3SApril Chin if(lp->lexd.warn && c==LBRACT && !lp->lex.intest && !lp->lexd.arith && oldmode(lp)!= ST_NESTED)
898da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),e_lexusebrace,shp->inlineno);
899b30d1939SAndy Fiddaman fcseek(-LEN);
9007c2fbfb3SApril Chin mode = oldmode(lp);
9017c2fbfb3SApril Chin poplevel(lp);
902da2e3ebdSchin break;
903da2e3ebdSchin case S_DOT:
904da2e3ebdSchin /* make sure next character is alpha */
905da2e3ebdSchin if(fcgetc(n)>0)
9067c2fbfb3SApril Chin {
9077c2fbfb3SApril Chin if(n=='.')
9087c2fbfb3SApril Chin fcgetc(n);
9097c2fbfb3SApril Chin if(n>0)
910b30d1939SAndy Fiddaman fcseek(-LEN);
9117c2fbfb3SApril Chin }
912da2e3ebdSchin if(isaletter(n) || n==LBRACT)
913da2e3ebdSchin continue;
914da2e3ebdSchin if(mode==ST_NAME)
915da2e3ebdSchin {
916da2e3ebdSchin if(n=='=')
917da2e3ebdSchin continue;
918da2e3ebdSchin break;
919da2e3ebdSchin }
920da2e3ebdSchin else if(n==RBRACE)
921da2e3ebdSchin continue;
922da2e3ebdSchin if(isastchar(n))
923da2e3ebdSchin continue;
924da2e3ebdSchin goto err;
925da2e3ebdSchin case S_SPC1:
926da2e3ebdSchin wordflags |= ARG_MAC;
9277c2fbfb3SApril Chin if(endchar(lp)==RBRACE)
928da2e3ebdSchin {
9297c2fbfb3SApril Chin setchar(lp,c);
930da2e3ebdSchin continue;
931da2e3ebdSchin }
932da2e3ebdSchin /* FALL THRU */
933da2e3ebdSchin case S_ALP:
9347c2fbfb3SApril Chin if(c=='.' && endchar(lp)=='$')
935da2e3ebdSchin goto err;
9365ae8bd53SToomas Soome /* FALLTHROUGH */
937da2e3ebdSchin case S_SPC2:
938da2e3ebdSchin case S_DIG:
939da2e3ebdSchin wordflags |= ARG_MAC;
9407c2fbfb3SApril Chin switch(endchar(lp))
941da2e3ebdSchin {
942da2e3ebdSchin case '$':
943da2e3ebdSchin if(n==S_ALP) /* $identifier */
944da2e3ebdSchin mode = ST_DOLNAME;
945da2e3ebdSchin else
946da2e3ebdSchin {
9477c2fbfb3SApril Chin mode = oldmode(lp);
9487c2fbfb3SApril Chin poplevel(lp);
949da2e3ebdSchin }
950da2e3ebdSchin break;
9515ae8bd53SToomas Soome /* FALLTHROUGH */
952da2e3ebdSchin #if SHOPT_TYPEDEF
953da2e3ebdSchin case '@':
954da2e3ebdSchin #endif /* SHOPT_TYPEDEF */
955da2e3ebdSchin case '!':
956da2e3ebdSchin if(n!=S_ALP)
957da2e3ebdSchin goto dolerr;
9585ae8bd53SToomas Soome /* FALLTHROUGH */
959da2e3ebdSchin case '#':
960b30d1939SAndy Fiddaman if(c=='#')
961b30d1939SAndy Fiddaman n = S_ALP;
962b30d1939SAndy Fiddaman /* FALLTHROUGH */
963da2e3ebdSchin case RBRACE:
964da2e3ebdSchin if(n==S_ALP)
965da2e3ebdSchin {
9667c2fbfb3SApril Chin setchar(lp,RBRACE);
967da2e3ebdSchin if(c=='.')
968b30d1939SAndy Fiddaman fcseek(-LEN);
969da2e3ebdSchin mode = ST_BRACE;
970da2e3ebdSchin }
971da2e3ebdSchin else
972da2e3ebdSchin {
973da2e3ebdSchin if(fcgetc(c)>0)
974b30d1939SAndy Fiddaman fcseek(-LEN);
975da2e3ebdSchin if(state[c]==S_ALP)
976da2e3ebdSchin goto err;
977da2e3ebdSchin if(n==S_DIG)
9787c2fbfb3SApril Chin setchar(lp,'0');
979da2e3ebdSchin else
9807c2fbfb3SApril Chin setchar(lp,'!');
981da2e3ebdSchin }
982da2e3ebdSchin break;
983da2e3ebdSchin case '0':
984da2e3ebdSchin if(n==S_DIG)
985da2e3ebdSchin break;
986da2e3ebdSchin default:
987da2e3ebdSchin goto dolerr;
988da2e3ebdSchin }
989da2e3ebdSchin break;
990da2e3ebdSchin dolerr:
991da2e3ebdSchin case S_ERR:
9927c2fbfb3SApril Chin if((n=endchar(lp)) == '$')
993da2e3ebdSchin goto err;
994da2e3ebdSchin if(c=='*' || (n=sh_lexstates[ST_BRACE][c])!=S_MOD1 && n!=S_MOD2)
995da2e3ebdSchin {
996da2e3ebdSchin /* see whether inside `...` */
9977c2fbfb3SApril Chin mode = oldmode(lp);
9987c2fbfb3SApril Chin poplevel(lp);
9997c2fbfb3SApril Chin if((n = endchar(lp)) != '`')
1000da2e3ebdSchin goto err;
10017c2fbfb3SApril Chin pushlevel(lp,RBRACE,mode);
1002da2e3ebdSchin }
1003da2e3ebdSchin else
10047c2fbfb3SApril Chin setchar(lp,RBRACE);
1005da2e3ebdSchin mode = ST_NESTED;
1006da2e3ebdSchin continue;
1007da2e3ebdSchin case S_MOD1:
10087c2fbfb3SApril Chin if(oldmode(lp)==ST_QUOTE || oldmode(lp)==ST_NONE)
1009da2e3ebdSchin {
1010da2e3ebdSchin /* allow ' inside "${...}" */
1011da2e3ebdSchin if(c==':' && fcgetc(n)>0)
1012da2e3ebdSchin {
1013da2e3ebdSchin n = state[n];
1014b30d1939SAndy Fiddaman fcseek(-LEN);
1015da2e3ebdSchin }
1016da2e3ebdSchin if(n==S_MOD1)
1017da2e3ebdSchin {
1018da2e3ebdSchin mode = ST_QUOTE;
1019da2e3ebdSchin continue;
1020da2e3ebdSchin }
1021da2e3ebdSchin }
1022da2e3ebdSchin /* FALL THRU */
1023da2e3ebdSchin case S_MOD2:
1024da2e3ebdSchin #if SHOPT_KIA
10257c2fbfb3SApril Chin if(lp->kiafile)
10267c2fbfb3SApril Chin refvar(lp,1);
1027da2e3ebdSchin #endif /* SHOPT_KIA */
1028da2e3ebdSchin if(c!=':' && fcgetc(n)>0)
1029da2e3ebdSchin {
1030da2e3ebdSchin if(n!=c)
1031da2e3ebdSchin c = 0;
1032da2e3ebdSchin if(!c || (fcgetc(n)>0))
1033da2e3ebdSchin {
1034b30d1939SAndy Fiddaman fcseek(-LEN);
1035da2e3ebdSchin if(n==LPAREN)
1036da2e3ebdSchin {
1037da2e3ebdSchin if(c!='%')
1038da2e3ebdSchin {
10397c2fbfb3SApril Chin lp->token = n;
10407c2fbfb3SApril Chin sh_syntax(lp);
1041da2e3ebdSchin }
10427c2fbfb3SApril Chin else if(lp->lexd.warn)
1043da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),e_lexquote,shp->inlineno,'%');
1044da2e3ebdSchin }
1045da2e3ebdSchin }
1046da2e3ebdSchin }
1047b30d1939SAndy Fiddaman lp->lex.nestedbrace = 0;
1048da2e3ebdSchin mode = ST_NESTED;
1049da2e3ebdSchin continue;
1050da2e3ebdSchin case S_LBRA:
10517c2fbfb3SApril Chin if((c=endchar(lp)) == '$')
1052da2e3ebdSchin {
1053da2e3ebdSchin if(fcgetc(c)>0)
1054b30d1939SAndy Fiddaman fcseek(-LEN);
10557c2fbfb3SApril Chin setchar(lp,RBRACE);
1056da2e3ebdSchin if(state[c]!=S_ERR && c!=RBRACE)
1057da2e3ebdSchin continue;
10587c2fbfb3SApril Chin if((n=sh_lexstates[ST_BEGIN][c])==0 || n==S_OP || n==S_NLTOK)
10597c2fbfb3SApril Chin {
10607c2fbfb3SApril Chin c = LBRACE;
10617c2fbfb3SApril Chin goto do_comsub;
10627c2fbfb3SApril Chin }
1063da2e3ebdSchin }
1064da2e3ebdSchin err:
1065b30d1939SAndy Fiddaman if(iswalpha(c))
1066b30d1939SAndy Fiddaman continue;
10677c2fbfb3SApril Chin n = endchar(lp);
10687c2fbfb3SApril Chin mode = oldmode(lp);
10697c2fbfb3SApril Chin poplevel(lp);
1070da2e3ebdSchin if(n!='$')
1071da2e3ebdSchin {
10727c2fbfb3SApril Chin lp->token = c;
10737c2fbfb3SApril Chin sh_syntax(lp);
1074da2e3ebdSchin }
1075da2e3ebdSchin else
1076da2e3ebdSchin {
10777c2fbfb3SApril Chin if(lp->lexd.warn && c!='/' && sh_lexstates[ST_NORM][c]!=S_BREAK && (c!='"' || mode==ST_QUOTE))
1078da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),e_lexslash,shp->inlineno);
107934f9b3eeSRoland Mainz else if(c=='"' && mode!=ST_QUOTE && !ingrave)
1080da2e3ebdSchin wordflags |= ARG_MESSAGE;
1081b30d1939SAndy Fiddaman fcseek(-LEN);
1082da2e3ebdSchin }
1083da2e3ebdSchin continue;
1084da2e3ebdSchin case S_META:
1085b30d1939SAndy Fiddaman if(lp->lexd.warn && endchar(lp)==RBRACE && !lp->lexd.nested_tilde)
1086da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),e_lexusequote,shp->inlineno,c);
1087da2e3ebdSchin continue;
1088da2e3ebdSchin case S_PUSH:
1089b30d1939SAndy Fiddaman fcgetc(n);
1090b30d1939SAndy Fiddaman if(n==RPAREN)
1091b30d1939SAndy Fiddaman continue;
1092b30d1939SAndy Fiddaman else
1093b30d1939SAndy Fiddaman fcseek(-LEN);
10947c2fbfb3SApril Chin pushlevel(lp,RPAREN,mode);
1095da2e3ebdSchin mode = ST_NESTED;
1096da2e3ebdSchin continue;
1097da2e3ebdSchin case S_POP:
1098da2e3ebdSchin do_pop:
1099b30d1939SAndy Fiddaman if(c==RBRACE && mode==ST_NESTED && lp->lex.nestedbrace)
1100b30d1939SAndy Fiddaman {
1101b30d1939SAndy Fiddaman lp->lex.nestedbrace--;
1102b30d1939SAndy Fiddaman continue;
1103b30d1939SAndy Fiddaman }
11047c2fbfb3SApril Chin if(lp->lexd.level <= inlevel)
1105da2e3ebdSchin break;
11067c2fbfb3SApril Chin if(lp->lexd.level==inlevel+1 && lp->lex.incase>=TEST_RE && !lp->lex.intest)
11077c2fbfb3SApril Chin {
1108b30d1939SAndy Fiddaman fcseek(-LEN);
11097c2fbfb3SApril Chin goto breakloop;
11107c2fbfb3SApril Chin }
11117c2fbfb3SApril Chin n = endchar(lp);
1112da2e3ebdSchin if(c==RBRACT && !(n==RBRACT || n==RPAREN))
1113da2e3ebdSchin continue;
1114da2e3ebdSchin if((c==RBRACE||c==RPAREN) && n==RPAREN)
1115da2e3ebdSchin {
1116da2e3ebdSchin if(fcgetc(n)==LPAREN)
1117da2e3ebdSchin {
1118da2e3ebdSchin if(c!=RPAREN)
1119b30d1939SAndy Fiddaman fcseek(-LEN);
1120da2e3ebdSchin continue;
1121da2e3ebdSchin }
1122da2e3ebdSchin if(n>0)
1123b30d1939SAndy Fiddaman fcseek(-LEN);
1124da2e3ebdSchin n = RPAREN;
1125da2e3ebdSchin }
1126b30d1939SAndy Fiddaman if(c==RBRACE)
1127b30d1939SAndy Fiddaman lp->lexd.nested_tilde = 0;
1128da2e3ebdSchin if(c==';' && n!=';')
1129da2e3ebdSchin {
11307c2fbfb3SApril Chin if(lp->lexd.warn && n==RBRACE)
1131da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),e_lexusequote,shp->inlineno,c);
1132da2e3ebdSchin continue;
1133da2e3ebdSchin }
1134da2e3ebdSchin if(mode==ST_QNEST)
1135da2e3ebdSchin {
11367c2fbfb3SApril Chin if(lp->lexd.warn)
1137da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),e_lexescape,shp->inlineno,c);
1138da2e3ebdSchin continue;
1139da2e3ebdSchin }
11407c2fbfb3SApril Chin mode = oldmode(lp);
11417c2fbfb3SApril Chin poplevel(lp);
1142b30d1939SAndy Fiddaman if(epatchar!='~')
1143b30d1939SAndy Fiddaman epatchar = '@';
1144da2e3ebdSchin /* quotes in subscript need expansion */
1145da2e3ebdSchin if(mode==ST_NAME && (wordflags&ARG_QUOTED))
1146da2e3ebdSchin wordflags |= ARG_MAC;
1147da2e3ebdSchin /* check for ((...)) */
1148da2e3ebdSchin if(n==1 && c==RPAREN)
1149da2e3ebdSchin {
1150da2e3ebdSchin if(fcgetc(n)==RPAREN)
1151da2e3ebdSchin {
11527c2fbfb3SApril Chin if(mode==ST_NONE && !lp->lexd.dolparen)
1153da2e3ebdSchin goto breakloop;
11547c2fbfb3SApril Chin lp->lex.reservok = 1;
11557c2fbfb3SApril Chin lp->lex.skipword = 0;
11567c2fbfb3SApril Chin return(lp->token=EXPRSYM);
1157da2e3ebdSchin }
1158da2e3ebdSchin /* backward compatibility */
1159da2e3ebdSchin {
11607c2fbfb3SApril Chin if(lp->lexd.warn)
1161da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),e_lexnested,shp->inlineno);
11627c2fbfb3SApril Chin if(!(state=lp->lexd.first))
1163da2e3ebdSchin state = fcfirst();
1164b30d1939SAndy Fiddaman else
1165da2e3ebdSchin {
1166b30d1939SAndy Fiddaman n = state-fcseek(0);
1167b30d1939SAndy Fiddaman fcseek(n);
1168da2e3ebdSchin }
11697c2fbfb3SApril Chin lp->lexd.paren = 1;
1170da2e3ebdSchin }
11717c2fbfb3SApril Chin return(lp->token=LPAREN);
1172da2e3ebdSchin }
1173da2e3ebdSchin if(mode==ST_NONE)
1174da2e3ebdSchin return(0);
1175da2e3ebdSchin if(c!=n)
1176da2e3ebdSchin {
11777c2fbfb3SApril Chin lp->token = c;
11787c2fbfb3SApril Chin sh_syntax(lp);
1179da2e3ebdSchin }
1180da2e3ebdSchin if(c==RBRACE && (mode==ST_NAME||mode==ST_NORM))
1181da2e3ebdSchin goto epat;
1182da2e3ebdSchin continue;
1183da2e3ebdSchin case S_EQ:
11847c2fbfb3SApril Chin assignment = lp->assignok;
1185da2e3ebdSchin /* FALL THRU */
1186da2e3ebdSchin case S_COLON:
1187da2e3ebdSchin if(assignment)
1188da2e3ebdSchin {
1189b30d1939SAndy Fiddaman if(fcgetc(c)=='~')
1190da2e3ebdSchin wordflags |= ARG_MAC;
1191da2e3ebdSchin else if(c!=LPAREN && assignment==SH_COMPASSIGN)
1192da2e3ebdSchin assignment = 0;
1193b30d1939SAndy Fiddaman if(c!=EOF)
1194b30d1939SAndy Fiddaman fcseek(-LEN);
1195da2e3ebdSchin }
1196da2e3ebdSchin break;
1197da2e3ebdSchin case S_LABEL:
11987c2fbfb3SApril Chin if(lp->lex.reservok && !lp->lex.incase)
1199da2e3ebdSchin {
1200da2e3ebdSchin c = fcget();
1201b30d1939SAndy Fiddaman fcseek(-LEN);
1202da2e3ebdSchin if(state[c]==S_BREAK)
1203da2e3ebdSchin {
1204da2e3ebdSchin assignment = -1;
1205da2e3ebdSchin goto breakloop;
1206da2e3ebdSchin }
1207da2e3ebdSchin }
1208da2e3ebdSchin break;
1209da2e3ebdSchin case S_BRACT:
1210da2e3ebdSchin /* check for possible subscript */
12117c2fbfb3SApril Chin if((n=endchar(lp))==RBRACT || n==RPAREN ||
1212da2e3ebdSchin (mode==ST_BRACE) ||
12137c2fbfb3SApril Chin (oldmode(lp)==ST_NONE) ||
12147c2fbfb3SApril Chin (mode==ST_NAME && (lp->assignok||lp->lexd.level)))
1215da2e3ebdSchin {
1216b30d1939SAndy Fiddaman fcgetc(n);
1217b30d1939SAndy Fiddaman if(n>0 && n==']')
121834f9b3eeSRoland Mainz {
1219b30d1939SAndy Fiddaman if(mode==ST_NAME)
1220b30d1939SAndy Fiddaman errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax1, shp->inlineno, "[]", "empty subscript");
1221b30d1939SAndy Fiddaman if(!epatchar || epatchar=='%')
1222b30d1939SAndy Fiddaman continue;
122334f9b3eeSRoland Mainz }
1224b30d1939SAndy Fiddaman else
1225b30d1939SAndy Fiddaman fcseek(-LEN);
12267c2fbfb3SApril Chin pushlevel(lp,RBRACT,mode);
1227da2e3ebdSchin wordflags |= ARG_QUOTED;
1228da2e3ebdSchin mode = ST_NESTED;
1229da2e3ebdSchin continue;
1230da2e3ebdSchin }
1231da2e3ebdSchin wordflags |= ARG_EXP;
1232da2e3ebdSchin break;
1233da2e3ebdSchin case S_BRACE:
1234da2e3ebdSchin {
1235da2e3ebdSchin int isfirst;
12367c2fbfb3SApril Chin if(lp->lexd.dolparen)
12377c2fbfb3SApril Chin {
12387c2fbfb3SApril Chin if(mode==ST_BEGIN && (lp->lex.reservok||lp->comsub))
12397c2fbfb3SApril Chin {
1240b30d1939SAndy Fiddaman if(lp->comsub)
1241b30d1939SAndy Fiddaman return(lp->token=c);
12427c2fbfb3SApril Chin fcgetc(n);
12437c2fbfb3SApril Chin if(n>0)
1244b30d1939SAndy Fiddaman fcseek(-LEN);
12457c2fbfb3SApril Chin else
12467c2fbfb3SApril Chin n = '\n';
12477c2fbfb3SApril Chin if(n==RBRACT || sh_lexstates[ST_NORM][n])
12487c2fbfb3SApril Chin return(lp->token=c);
12497c2fbfb3SApril Chin }
1250da2e3ebdSchin break;
12517c2fbfb3SApril Chin }
1252b30d1939SAndy Fiddaman else if(mode==ST_NESTED && endchar(lp)==RBRACE)
1253b30d1939SAndy Fiddaman {
1254b30d1939SAndy Fiddaman lp->lex.nestedbrace++;
1255b30d1939SAndy Fiddaman continue;
1256b30d1939SAndy Fiddaman }
12577c2fbfb3SApril Chin else if(mode==ST_BEGIN)
12587c2fbfb3SApril Chin {
12597c2fbfb3SApril Chin if(lp->comsub && c==RBRACE)
12607c2fbfb3SApril Chin return(lp->token=c);
12617c2fbfb3SApril Chin goto do_reg;
12627c2fbfb3SApril Chin }
12637c2fbfb3SApril Chin isfirst = (lp->lexd.first&&fcseek(0)==lp->lexd.first+1);
1264da2e3ebdSchin fcgetc(n);
1265da2e3ebdSchin /* check for {} */
1266da2e3ebdSchin if(c==LBRACE && n==RBRACE)
1267da2e3ebdSchin break;
1268da2e3ebdSchin if(n>0)
1269b30d1939SAndy Fiddaman fcseek(-LEN);
12707c2fbfb3SApril Chin else if(lp->lex.reservok)
1271da2e3ebdSchin break;
1272da2e3ebdSchin /* check for reserved word { or } */
12737c2fbfb3SApril Chin if(lp->lex.reservok && state[n]==S_BREAK && isfirst)
1274da2e3ebdSchin break;
1275da2e3ebdSchin if(sh_isoption(SH_BRACEEXPAND) && c==LBRACE && !assignment && state[n]!=S_BREAK
12767c2fbfb3SApril Chin && !lp->lex.incase && !lp->lex.intest
12777c2fbfb3SApril Chin && !lp->lex.skipword)
1278da2e3ebdSchin {
1279da2e3ebdSchin wordflags |= ARG_EXP;
1280da2e3ebdSchin }
1281da2e3ebdSchin if(c==RBRACE && n==LPAREN)
1282da2e3ebdSchin goto epat;
1283da2e3ebdSchin break;
1284da2e3ebdSchin }
1285da2e3ebdSchin case S_PAT:
1286da2e3ebdSchin wordflags |= ARG_EXP;
1287da2e3ebdSchin /* FALL THRU */
1288da2e3ebdSchin case S_EPAT:
1289da2e3ebdSchin epat:
1290b30d1939SAndy Fiddaman if(fcgetc(n)==LPAREN && c!='[')
1291da2e3ebdSchin {
1292b30d1939SAndy Fiddaman epatchar = c;
12937c2fbfb3SApril Chin if(lp->lex.incase==TEST_RE)
1294da2e3ebdSchin {
12957c2fbfb3SApril Chin lp->lex.incase++;
12967c2fbfb3SApril Chin pushlevel(lp,RPAREN,ST_NORM);
1297da2e3ebdSchin mode = ST_NESTED;
1298da2e3ebdSchin }
1299da2e3ebdSchin wordflags |= ARG_EXP;
13007c2fbfb3SApril Chin pushlevel(lp,RPAREN,mode);
1301da2e3ebdSchin mode = ST_NESTED;
1302da2e3ebdSchin continue;
1303da2e3ebdSchin }
1304b30d1939SAndy Fiddaman if(lp->lexd.warn && c=='[' && n=='^')
1305b30d1939SAndy Fiddaman errormsg(SH_DICT,ERROR_warn(0),e_lexcharclass,shp->inlineno);
1306da2e3ebdSchin if(n>0)
1307b30d1939SAndy Fiddaman fcseek(-LEN);
1308da2e3ebdSchin if(n=='=' && c=='+' && mode==ST_NAME)
1309da2e3ebdSchin continue;
1310da2e3ebdSchin break;
1311da2e3ebdSchin }
13127c2fbfb3SApril Chin lp->comp_assign = 0;
1313da2e3ebdSchin if(mode==ST_NAME)
1314da2e3ebdSchin mode = ST_NORM;
1315da2e3ebdSchin else if(mode==ST_NONE)
1316da2e3ebdSchin return(0);
1317da2e3ebdSchin }
1318da2e3ebdSchin breakloop:
13197c2fbfb3SApril Chin if(lp->lexd.nocopy)
13207c2fbfb3SApril Chin {
13217c2fbfb3SApril Chin lp->lexd.balance = 0;
13227c2fbfb3SApril Chin return(0);
13237c2fbfb3SApril Chin }
13247c2fbfb3SApril Chin if(lp->lexd.dolparen)
1325da2e3ebdSchin {
13267c2fbfb3SApril Chin lp->lexd.balance = 0;
13277c2fbfb3SApril Chin if(lp->lexd.docword)
1328da2e3ebdSchin nested_here(lp);
13297c2fbfb3SApril Chin lp->lexd.message = (wordflags&ARG_MESSAGE);
13307c2fbfb3SApril Chin return(lp->token=0);
1331da2e3ebdSchin }
13327c2fbfb3SApril Chin if(!(state=lp->lexd.first))
1333da2e3ebdSchin state = fcfirst();
1334da2e3ebdSchin n = fcseek(0)-(char*)state;
13357c2fbfb3SApril Chin if(!lp->arg)
13367c2fbfb3SApril Chin lp->arg = (struct argnod*)stkseek(stkp,ARGVAL);
1337da2e3ebdSchin if(n>0)
13387c2fbfb3SApril Chin sfwrite(stkp,state,n);
1339da2e3ebdSchin /* add balancing character if necessary */
13407c2fbfb3SApril Chin if(lp->lexd.balance)
1341da2e3ebdSchin {
13427c2fbfb3SApril Chin sfputc(stkp,lp->lexd.balance);
13437c2fbfb3SApril Chin lp->lexd.balance = 0;
1344da2e3ebdSchin }
13457c2fbfb3SApril Chin sfputc(stkp,0);
13467c2fbfb3SApril Chin stkseek(stkp,stktell(stkp)-1);
13477c2fbfb3SApril Chin state = stkptr(stkp,ARGVAL);
13487c2fbfb3SApril Chin n = stktell(stkp)-ARGVAL;
13497c2fbfb3SApril Chin lp->lexd.first=0;
1350da2e3ebdSchin if(n==1)
1351da2e3ebdSchin {
1352da2e3ebdSchin /* check for numbered redirection */
1353da2e3ebdSchin n = state[0];
1354da2e3ebdSchin if((c=='<' || c=='>') && isadigit(n))
1355da2e3ebdSchin {
13567c2fbfb3SApril Chin c = sh_lex(lp);
13577c2fbfb3SApril Chin lp->digits = (n-'0');
1358da2e3ebdSchin return(c);
1359da2e3ebdSchin }
1360da2e3ebdSchin if(n==LBRACT)
1361da2e3ebdSchin c = 0;
13627c2fbfb3SApril Chin else if(n==RBRACE && lp->comsub)
13637c2fbfb3SApril Chin return(lp->token=n);
1364da2e3ebdSchin else if(n=='~')
1365da2e3ebdSchin c = ARG_MAC;
1366da2e3ebdSchin else
1367da2e3ebdSchin c = (wordflags&ARG_EXP);
1368da2e3ebdSchin n = 1;
1369da2e3ebdSchin }
13707c2fbfb3SApril Chin else if(n>2 && state[0]=='{' && state[n-1]=='}' && !lp->lex.intest && !lp->lex.incase && (c=='<' || c== '>') && sh_isoption(SH_BRACEEXPAND))
1371da2e3ebdSchin {
1372da2e3ebdSchin if(!strchr(state,','))
1373da2e3ebdSchin {
13747c2fbfb3SApril Chin stkseek(stkp,stktell(stkp)-1);
13757c2fbfb3SApril Chin lp->arg = (struct argnod*)stkfreeze(stkp,1);
13767c2fbfb3SApril Chin return(lp->token=IOVNAME);
1377da2e3ebdSchin }
1378da2e3ebdSchin c = wordflags;
1379da2e3ebdSchin }
1380da2e3ebdSchin else
1381da2e3ebdSchin c = wordflags;
1382da2e3ebdSchin if(assignment<0)
1383da2e3ebdSchin {
13847c2fbfb3SApril Chin stkseek(stkp,stktell(stkp)-1);
13857c2fbfb3SApril Chin lp->arg = (struct argnod*)stkfreeze(stkp,1);
13867c2fbfb3SApril Chin lp->lex.reservok = 1;
13877c2fbfb3SApril Chin return(lp->token=LABLSYM);
1388da2e3ebdSchin }
13897c2fbfb3SApril Chin if(assignment || (lp->lex.intest&&!lp->lex.incase) || mode==ST_NONE)
1390da2e3ebdSchin c &= ~ARG_EXP;
1391da2e3ebdSchin if((c&ARG_EXP) && (c&ARG_QUOTED))
1392da2e3ebdSchin c |= ARG_MAC;
1393da2e3ebdSchin if(mode==ST_NONE)
1394da2e3ebdSchin {
1395da2e3ebdSchin /* eliminate trailing )) */
13967c2fbfb3SApril Chin stkseek(stkp,stktell(stkp)-2);
1397da2e3ebdSchin }
1398da2e3ebdSchin if(c&ARG_MESSAGE)
1399da2e3ebdSchin {
1400da2e3ebdSchin if(sh_isoption(SH_DICTIONARY))
14017c2fbfb3SApril Chin lp->arg = sh_endword(shp,2);
1402b30d1939SAndy Fiddaman c |= ARG_MAC;
1403da2e3ebdSchin }
1404b30d1939SAndy Fiddaman if(c==0 || (c&(ARG_MAC|ARG_EXP|ARG_MESSAGE)))
1405da2e3ebdSchin {
14067c2fbfb3SApril Chin lp->arg = (struct argnod*)stkfreeze(stkp,1);
14077c2fbfb3SApril Chin lp->arg->argflag = (c?c:ARG_RAW);
1408da2e3ebdSchin }
1409da2e3ebdSchin else if(mode==ST_NONE)
14107c2fbfb3SApril Chin lp->arg = sh_endword(shp,-1);
1411da2e3ebdSchin else
14127c2fbfb3SApril Chin lp->arg = sh_endword(shp,0);
14137c2fbfb3SApril Chin state = lp->arg->argval;
14147c2fbfb3SApril Chin lp->comp_assign = assignment;
1415da2e3ebdSchin if(assignment)
14167c2fbfb3SApril Chin lp->arg->argflag |= ARG_ASSIGN;
14177c2fbfb3SApril Chin else if(!lp->lex.skipword)
14187c2fbfb3SApril Chin lp->assignok = 0;
14197c2fbfb3SApril Chin lp->arg->argchn.cp = 0;
14207c2fbfb3SApril Chin lp->arg->argnxt.ap = 0;
1421da2e3ebdSchin if(mode==ST_NONE)
14227c2fbfb3SApril Chin return(lp->token=EXPRSYM);
14237c2fbfb3SApril Chin if(lp->lex.intest)
1424da2e3ebdSchin {
14257c2fbfb3SApril Chin if(lp->lex.testop1)
1426da2e3ebdSchin {
14277c2fbfb3SApril Chin lp->lex.testop1 = 0;
1428da2e3ebdSchin if(n==2 && state[0]=='-' && state[2]==0 &&
1429da2e3ebdSchin strchr(test_opchars,state[1]))
1430da2e3ebdSchin {
14317c2fbfb3SApril Chin if(lp->lexd.warn && state[1]=='a')
1432da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete2,shp->inlineno);
14337c2fbfb3SApril Chin lp->digits = state[1];
14347c2fbfb3SApril Chin lp->token = TESTUNOP;
1435da2e3ebdSchin }
1436da2e3ebdSchin else if(n==1 && state[0]=='!' && state[1]==0)
1437da2e3ebdSchin {
14387c2fbfb3SApril Chin lp->lex.testop1 = 1;
14397c2fbfb3SApril Chin lp->token = '!';
1440da2e3ebdSchin }
1441da2e3ebdSchin else
1442da2e3ebdSchin {
14437c2fbfb3SApril Chin lp->lex.testop2 = 1;
14447c2fbfb3SApril Chin lp->token = 0;
1445da2e3ebdSchin }
14467c2fbfb3SApril Chin return(lp->token);
1447da2e3ebdSchin }
14487c2fbfb3SApril Chin lp->lex.incase = 0;
1449da2e3ebdSchin c = sh_lookup(state,shtab_testops);
1450da2e3ebdSchin switch(c)
1451da2e3ebdSchin {
1452da2e3ebdSchin case TEST_END:
14537c2fbfb3SApril Chin lp->lex.testop2 = lp->lex.intest = 0;
14547c2fbfb3SApril Chin lp->lex.reservok = 1;
14557c2fbfb3SApril Chin lp->token = ETESTSYM;
14567c2fbfb3SApril Chin return(lp->token);
1457da2e3ebdSchin
1458da2e3ebdSchin case TEST_SEQ:
14597c2fbfb3SApril Chin if(lp->lexd.warn && state[1]==0)
1460da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete3,shp->inlineno);
14615ae8bd53SToomas Soome /* FALLTHROUGH */
1462da2e3ebdSchin default:
14637c2fbfb3SApril Chin if(lp->lex.testop2)
1464da2e3ebdSchin {
1465c7b656fcSAndy Fiddaman if(lp->lexd.warn && (c&TEST_ARITH)) {
1466*be548e87SAndy Fiddaman char *alt;
1467c7b656fcSAndy Fiddaman
1468*be548e87SAndy Fiddaman switch (c) {
1469*be548e87SAndy Fiddaman case TEST_EQ:
1470c7b656fcSAndy Fiddaman alt = "==";
1471*be548e87SAndy Fiddaman break;
1472*be548e87SAndy Fiddaman case TEST_NE:
1473c7b656fcSAndy Fiddaman alt = "!=";
1474*be548e87SAndy Fiddaman break;
1475*be548e87SAndy Fiddaman case TEST_LT:
1476c7b656fcSAndy Fiddaman alt = "<";
1477*be548e87SAndy Fiddaman break;
1478*be548e87SAndy Fiddaman case TEST_GT:
1479c7b656fcSAndy Fiddaman alt = ">";
1480*be548e87SAndy Fiddaman break;
1481*be548e87SAndy Fiddaman case TEST_LE:
1482c7b656fcSAndy Fiddaman alt = "<=";
1483*be548e87SAndy Fiddaman break;
1484*be548e87SAndy Fiddaman case TEST_GE:
1485c7b656fcSAndy Fiddaman alt = ">=";
1486*be548e87SAndy Fiddaman break;
1487*be548e87SAndy Fiddaman default:
1488*be548e87SAndy Fiddaman alt = "??";
1489c7b656fcSAndy Fiddaman }
1490*be548e87SAndy Fiddaman errormsg(SH_DICT, ERROR_warn(0),
1491*be548e87SAndy Fiddaman e_lexobsolete4,
1492*be548e87SAndy Fiddaman shp->inlineno, state, alt);
1493c7b656fcSAndy Fiddaman }
1494da2e3ebdSchin if(c&TEST_PATTERN)
14957c2fbfb3SApril Chin lp->lex.incase = 1;
1496da2e3ebdSchin else if(c==TEST_REP)
14977c2fbfb3SApril Chin lp->lex.incase = TEST_RE;
14987c2fbfb3SApril Chin lp->lex.testop2 = 0;
14997c2fbfb3SApril Chin lp->digits = c;
15007c2fbfb3SApril Chin lp->token = TESTBINOP;
15017c2fbfb3SApril Chin return(lp->token);
1502da2e3ebdSchin }
1503da2e3ebdSchin
15045ae8bd53SToomas Soome /* FALLTHROUGH */
1505da2e3ebdSchin case TEST_OR: case TEST_AND:
1506da2e3ebdSchin case 0:
15077c2fbfb3SApril Chin return(lp->token=0);
1508da2e3ebdSchin }
1509da2e3ebdSchin }
15107c2fbfb3SApril Chin if(lp->lex.reservok /* && !lp->lex.incase*/ && n<=2)
1511da2e3ebdSchin {
1512da2e3ebdSchin /* check for {, }, ! */
1513da2e3ebdSchin c = state[0];
1514da2e3ebdSchin if(n==1 && (c=='{' || c=='}' || c=='!'))
1515da2e3ebdSchin {
15167c2fbfb3SApril Chin if(lp->lexd.warn && c=='{' && lp->lex.incase==2)
1517da2e3ebdSchin errormsg(SH_DICT,ERROR_warn(0),e_lexobsolete6,shp->inlineno);
15187c2fbfb3SApril Chin if(lp->lex.incase==1 && c==RBRACE)
15197c2fbfb3SApril Chin lp->lex.incase = 0;
15207c2fbfb3SApril Chin return(lp->token=c);
1521da2e3ebdSchin }
15227c2fbfb3SApril Chin else if(!lp->lex.incase && c==LBRACT && state[1]==LBRACT)
1523da2e3ebdSchin {
15247c2fbfb3SApril Chin lp->lex.intest = lp->lex.testop1 = 1;
15257c2fbfb3SApril Chin lp->lex.testop2 = lp->lex.reservok = 0;
15267c2fbfb3SApril Chin return(lp->token=BTESTSYM);
1527da2e3ebdSchin }
1528da2e3ebdSchin }
1529da2e3ebdSchin c = 0;
15307c2fbfb3SApril Chin if(!lp->lex.skipword)
1531da2e3ebdSchin {
15327c2fbfb3SApril Chin if(n>1 && lp->lex.reservok==1 && mode==ST_NAME &&
1533da2e3ebdSchin (c=sh_lookup(state,shtab_reserved)))
1534da2e3ebdSchin {
15357c2fbfb3SApril Chin if(lp->lex.incase)
1536da2e3ebdSchin {
15377c2fbfb3SApril Chin if(lp->lex.incase >1)
15387c2fbfb3SApril Chin lp->lex.incase = 1;
1539da2e3ebdSchin else if(c==ESACSYM)
15407c2fbfb3SApril Chin lp->lex.incase = 0;
1541da2e3ebdSchin else
1542da2e3ebdSchin c = 0;
1543da2e3ebdSchin }
1544da2e3ebdSchin else if(c==FORSYM || c==CASESYM || c==SELECTSYM || c==FUNCTSYM || c==NSPACESYM)
1545da2e3ebdSchin {
15467c2fbfb3SApril Chin lp->lex.skipword = 1;
15477c2fbfb3SApril Chin lp->lex.incase = 2*(c==CASESYM);
1548da2e3ebdSchin }
1549da2e3ebdSchin else
15507c2fbfb3SApril Chin lp->lex.skipword = 0;
1551da2e3ebdSchin if(c==INSYM)
15527c2fbfb3SApril Chin lp->lex.reservok = 0;
1553da2e3ebdSchin else if(c==TIMESYM)
1554da2e3ebdSchin {
1555da2e3ebdSchin /* yech - POSIX requires time -p */
1556da2e3ebdSchin while(fcgetc(n)==' ' || n=='\t');
1557da2e3ebdSchin if(n>0)
1558b30d1939SAndy Fiddaman fcseek(-LEN);
1559da2e3ebdSchin if(n=='-')
1560da2e3ebdSchin c=0;
1561da2e3ebdSchin }
15627c2fbfb3SApril Chin return(lp->token=c);
1563da2e3ebdSchin }
15647c2fbfb3SApril Chin if(!(wordflags&ARG_QUOTED) && (lp->lex.reservok||lp->aliasok))
1565da2e3ebdSchin {
1566da2e3ebdSchin /* check for aliases */
1567da2e3ebdSchin Namval_t* np;
15687c2fbfb3SApril Chin if(!lp->lex.incase && !assignment && fcpeek(0)!=LPAREN &&
1569da2e3ebdSchin (np=nv_search(state,shp->alias_tree,HASH_SCOPE))
1570da2e3ebdSchin && !nv_isattr(np,NV_NOEXPAND)
1571da2e3ebdSchin #if KSHELL
1572b30d1939SAndy Fiddaman && (lp->aliasok!=2 || nv_isattr(np,BLT_DCL))
1573da2e3ebdSchin && (!sh_isstate(SH_NOALIAS) || nv_isattr(np,NV_NOFREE))
1574da2e3ebdSchin #endif /* KSHELL */
1575da2e3ebdSchin && (state=nv_getval(np)))
1576da2e3ebdSchin {
1577da2e3ebdSchin setupalias(lp,state,np);
1578da2e3ebdSchin nv_onattr(np,NV_NOEXPAND);
15797c2fbfb3SApril Chin lp->lex.reservok = 1;
15807c2fbfb3SApril Chin lp->assignok |= lp->lex.reservok;
15817c2fbfb3SApril Chin return(sh_lex(lp));
1582da2e3ebdSchin }
1583da2e3ebdSchin }
15847c2fbfb3SApril Chin lp->lex.reservok = 0;
1585da2e3ebdSchin }
15867c2fbfb3SApril Chin lp->lex.skipword = lp->lexd.docword = 0;
15877c2fbfb3SApril Chin return(lp->token=c);
1588da2e3ebdSchin }
1589da2e3ebdSchin
1590da2e3ebdSchin /*
1591da2e3ebdSchin * read to end of command substitution
1592da2e3ebdSchin */
comsub(register Lex_t * lp,int endtok)15937c2fbfb3SApril Chin static int comsub(register Lex_t *lp, int endtok)
1594da2e3ebdSchin {
1595da2e3ebdSchin register int n,c,count=1;
15967c2fbfb3SApril Chin register int line=lp->sh->inlineno;
1597b30d1939SAndy Fiddaman char *first,*cp=fcseek(0),word[5];
15983e14f97fSRoger A. Faulkner int off, messages=0, assignok=lp->assignok, csub;
1599da2e3ebdSchin struct lexstate save;
16007c2fbfb3SApril Chin save = lp->lex;
16017c2fbfb3SApril Chin csub = lp->comsub;
16027c2fbfb3SApril Chin sh_lexopen(lp,lp->sh,1);
16037c2fbfb3SApril Chin lp->lexd.dolparen++;
16047c2fbfb3SApril Chin lp->lex.incase=0;
16057c2fbfb3SApril Chin pushlevel(lp,0,0);
16067c2fbfb3SApril Chin lp->comsub = (endtok==LBRACE);
1607b30d1939SAndy Fiddaman if(first=lp->lexd.first)
1608b30d1939SAndy Fiddaman off = cp-first;
1609b30d1939SAndy Fiddaman else
1610b30d1939SAndy Fiddaman off = cp-fcfirst();
1611b30d1939SAndy Fiddaman if(off<0)
1612b30d1939SAndy Fiddaman c=*cp, *cp=0;
1613b30d1939SAndy Fiddaman n = sh_lex(lp);
1614b30d1939SAndy Fiddaman if(off<0)
1615b30d1939SAndy Fiddaman *cp = c;
1616b30d1939SAndy Fiddaman if(n==endtok || off<0)
1617da2e3ebdSchin {
1618b30d1939SAndy Fiddaman if(endtok==LPAREN && lp->lexd.paren)
16193e14f97fSRoger A. Faulkner {
1620b30d1939SAndy Fiddaman
1621b30d1939SAndy Fiddaman if(first==lp->lexd.first)
1622b30d1939SAndy Fiddaman {
1623b30d1939SAndy Fiddaman n = cp+1-(char*)fcseek(0);
1624b30d1939SAndy Fiddaman fcseek(n);
1625b30d1939SAndy Fiddaman }
16263e14f97fSRoger A. Faulkner count++;
16273e14f97fSRoger A. Faulkner lp->lexd.paren = 0;
1628b30d1939SAndy Fiddaman fcgetc(c);
16293e14f97fSRoger A. Faulkner }
1630da2e3ebdSchin while(1)
1631da2e3ebdSchin {
1632da2e3ebdSchin /* look for case and esac */
1633da2e3ebdSchin n=0;
1634da2e3ebdSchin while(1)
1635da2e3ebdSchin {
1636da2e3ebdSchin fcgetc(c);
1637da2e3ebdSchin /* skip leading white space */
1638da2e3ebdSchin if(n==0 && !sh_lexstates[ST_BEGIN][c])
1639da2e3ebdSchin continue;
1640da2e3ebdSchin if(n==4)
1641da2e3ebdSchin break;
1642da2e3ebdSchin if(sh_lexstates[ST_NAME][c])
1643da2e3ebdSchin goto skip;
1644da2e3ebdSchin word[n++] = c;
1645da2e3ebdSchin }
1646da2e3ebdSchin if(sh_lexstates[ST_NAME][c]==S_BREAK)
1647da2e3ebdSchin {
1648da2e3ebdSchin if(memcmp(word,"case",4)==0)
16497c2fbfb3SApril Chin lp->lex.incase=1;
1650da2e3ebdSchin else if(memcmp(word,"esac",4)==0)
16517c2fbfb3SApril Chin lp->lex.incase=0;
1652da2e3ebdSchin }
1653da2e3ebdSchin skip:
1654da2e3ebdSchin if(c && (c!='#' || n==0))
1655b30d1939SAndy Fiddaman fcseek(-LEN);
16567c2fbfb3SApril Chin if(c==RBRACE && lp->lex.incase)
16577c2fbfb3SApril Chin lp->lex.incase=0;
1658b30d1939SAndy Fiddaman c=sh_lex(lp);
1659b30d1939SAndy Fiddaman switch(c)
1660da2e3ebdSchin {
16617c2fbfb3SApril Chin case LBRACE:
16627c2fbfb3SApril Chin if(endtok==LBRACE && !lp->lex.incase)
16637c2fbfb3SApril Chin {
16647c2fbfb3SApril Chin lp->comsub = 0;
16657c2fbfb3SApril Chin count++;
16667c2fbfb3SApril Chin }
16677c2fbfb3SApril Chin break;
16687c2fbfb3SApril Chin case RBRACE:
16697c2fbfb3SApril Chin rbrace:
16707c2fbfb3SApril Chin if(endtok==LBRACE && --count<=0)
16717c2fbfb3SApril Chin goto done;
1672b30d1939SAndy Fiddaman if(count==1)
1673b30d1939SAndy Fiddaman lp->comsub = endtok==LBRACE;
16747c2fbfb3SApril Chin break;
16757c2fbfb3SApril Chin case IPROCSYM: case OPROCSYM:
16767c2fbfb3SApril Chin case LPAREN:
16777c2fbfb3SApril Chin if(endtok==LPAREN && !lp->lex.incase)
1678da2e3ebdSchin count++;
1679da2e3ebdSchin break;
1680da2e3ebdSchin case RPAREN:
16817c2fbfb3SApril Chin if(lp->lex.incase)
16827c2fbfb3SApril Chin lp->lex.incase=0;
16837c2fbfb3SApril Chin else if(endtok==LPAREN && --count<=0)
1684da2e3ebdSchin goto done;
1685da2e3ebdSchin break;
1686da2e3ebdSchin case EOFSYM:
16877c2fbfb3SApril Chin lp->lastline = line;
16887c2fbfb3SApril Chin lp->lasttok = endtok;
16897c2fbfb3SApril Chin sh_syntax(lp);
16905ae8bd53SToomas Soome /* FALLTHROUGH */
1691da2e3ebdSchin case IOSEEKSYM:
1692da2e3ebdSchin if(fcgetc(c)!='#' && c>0)
1693b30d1939SAndy Fiddaman fcseek(-LEN);
1694da2e3ebdSchin break;
1695da2e3ebdSchin case IODOCSYM:
169634f9b3eeSRoland Mainz lp->lexd.docextra = 0;
16977c2fbfb3SApril Chin sh_lex(lp);
1698da2e3ebdSchin break;
1699da2e3ebdSchin case 0:
17007c2fbfb3SApril Chin lp->lex.reservok = 0;
17017c2fbfb3SApril Chin messages |= lp->lexd.message;
17027c2fbfb3SApril Chin break;
17037c2fbfb3SApril Chin case ';':
1704b30d1939SAndy Fiddaman do
1705b30d1939SAndy Fiddaman fcgetc(c);
1706b30d1939SAndy Fiddaman while(!sh_lexstates[ST_BEGIN][c]);
17077c2fbfb3SApril Chin if(c==RBRACE && endtok==LBRACE)
17087c2fbfb3SApril Chin goto rbrace;
17097c2fbfb3SApril Chin if(c>0)
1710b30d1939SAndy Fiddaman fcseek(-LEN);
17117c2fbfb3SApril Chin /* fall through*/
17127c2fbfb3SApril Chin default:
17137c2fbfb3SApril Chin lp->lex.reservok = 1;
1714da2e3ebdSchin }
1715da2e3ebdSchin }
1716da2e3ebdSchin }
1717da2e3ebdSchin done:
17187c2fbfb3SApril Chin poplevel(lp);
17197c2fbfb3SApril Chin lp->comsub = csub;
17207c2fbfb3SApril Chin lp->lastline = line;
17217c2fbfb3SApril Chin lp->lexd.dolparen--;
17227c2fbfb3SApril Chin lp->lex = save;
17237c2fbfb3SApril Chin lp->assignok = (endchar(lp)==RBRACT?assignok:0);
1724b30d1939SAndy Fiddaman if(lp->heredoc)
1725b30d1939SAndy Fiddaman errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax5,lp->sh->inlineno,lp->heredoc->ioname);
1726da2e3ebdSchin return(messages);
1727da2e3ebdSchin }
1728da2e3ebdSchin
1729da2e3ebdSchin /*
1730da2e3ebdSchin * here-doc nested in $(...)
1731da2e3ebdSchin * allocate ionode with delimiter filled in without disturbing stak
1732da2e3ebdSchin */
nested_here(register Lex_t * lp)1733da2e3ebdSchin static void nested_here(register Lex_t *lp)
1734da2e3ebdSchin {
17357c2fbfb3SApril Chin register struct ionod *iop;
1736b30d1939SAndy Fiddaman register int n=0,offset;
17377c2fbfb3SApril Chin struct argnod *arg = lp->arg;
17387c2fbfb3SApril Chin Stk_t *stkp = lp->sh->stk;
17397c2fbfb3SApril Chin char *base;
17407c2fbfb3SApril Chin if(offset=stktell(stkp))
17417c2fbfb3SApril Chin base = stkfreeze(stkp,0);
1742b30d1939SAndy Fiddaman if(lp->lexd.docend)
1743b30d1939SAndy Fiddaman n = fcseek(0)-lp->lexd.docend;
174434f9b3eeSRoland Mainz iop = newof(0,struct ionod,1,lp->lexd.docextra+n+ARGVAL);
17457c2fbfb3SApril Chin iop->iolst = lp->heredoc;
17467c2fbfb3SApril Chin stkseek(stkp,ARGVAL);
174734f9b3eeSRoland Mainz if(lp->lexd.docextra)
174834f9b3eeSRoland Mainz {
174934f9b3eeSRoland Mainz sfseek(lp->sh->strbuf,(Sfoff_t)0, SEEK_SET);
175034f9b3eeSRoland Mainz sfmove(lp->sh->strbuf,stkp,lp->lexd.docextra,-1);
1751b30d1939SAndy Fiddaman sfseek(lp->sh->strbuf,(Sfoff_t)0, SEEK_SET);
175234f9b3eeSRoland Mainz }
17537c2fbfb3SApril Chin sfwrite(stkp,lp->lexd.docend,n);
17547c2fbfb3SApril Chin lp->arg = sh_endword(lp->sh,0);
1755da2e3ebdSchin iop->ioname = (char*)(iop+1);
17567c2fbfb3SApril Chin strcpy(iop->ioname,lp->arg->argval);
1757da2e3ebdSchin iop->iofile = (IODOC|IORAW);
17587c2fbfb3SApril Chin if(lp->lexd.docword>1)
1759da2e3ebdSchin iop->iofile |= IOSTRIP;
17607c2fbfb3SApril Chin lp->heredoc = iop;
17617c2fbfb3SApril Chin lp->arg = arg;
17627c2fbfb3SApril Chin lp->lexd.docword = 0;
1763da2e3ebdSchin if(offset)
17647c2fbfb3SApril Chin stkset(stkp,base,offset);
1765da2e3ebdSchin else
17667c2fbfb3SApril Chin stkseek(stkp,0);
1767da2e3ebdSchin }
1768da2e3ebdSchin
1769da2e3ebdSchin /*
1770da2e3ebdSchin * skip to <close> character
1771da2e3ebdSchin * if <copy> is non,zero, then the characters are copied to the stack
1772da2e3ebdSchin * <state> is the initial lexical state
1773da2e3ebdSchin */
sh_lexskip(Lex_t * lp,int close,register int copy,int state)17747c2fbfb3SApril Chin void sh_lexskip(Lex_t *lp,int close, register int copy, int state)
1775da2e3ebdSchin {
1776da2e3ebdSchin register char *cp;
17777c2fbfb3SApril Chin lp->lexd.nest = close;
17787c2fbfb3SApril Chin lp->lexd.lex_state = state;
17797c2fbfb3SApril Chin lp->lexd.noarg = 1;
1780da2e3ebdSchin if(copy)
17817c2fbfb3SApril Chin fcnotify(lex_advance,lp);
1782da2e3ebdSchin else
17837c2fbfb3SApril Chin lp->lexd.nocopy++;
17847c2fbfb3SApril Chin sh_lex(lp);
17857c2fbfb3SApril Chin lp->lexd.noarg = 0;
1786da2e3ebdSchin if(copy)
1787da2e3ebdSchin {
17887c2fbfb3SApril Chin fcnotify(0,lp);
17897c2fbfb3SApril Chin if(!(cp=lp->lexd.first))
1790da2e3ebdSchin cp = fcfirst();
1791da2e3ebdSchin if((copy = fcseek(0)-cp) > 0)
17927c2fbfb3SApril Chin sfwrite(lp->sh->stk,cp,copy);
1793da2e3ebdSchin }
1794da2e3ebdSchin else
17957c2fbfb3SApril Chin lp->lexd.nocopy--;
1796da2e3ebdSchin }
1797da2e3ebdSchin
1798da2e3ebdSchin #if SHOPT_CRNL
_sfwrite(Sfio_t * sp,const Void_t * buff,size_t n)1799da2e3ebdSchin ssize_t _sfwrite(Sfio_t *sp, const Void_t *buff, size_t n)
1800da2e3ebdSchin {
1801da2e3ebdSchin const char *cp = (const char*)buff, *next=cp, *ep = cp + n;
1802da2e3ebdSchin int m=0,k;
1803da2e3ebdSchin while(next = (const char*)memchr(next,'\r',ep-next))
1804da2e3ebdSchin if(*++next=='\n')
1805da2e3ebdSchin {
1806da2e3ebdSchin if(k=next-cp-1)
1807da2e3ebdSchin {
1808da2e3ebdSchin if((k=sfwrite(sp,cp,k)) < 0)
1809da2e3ebdSchin return(m>0?m:-1);
1810da2e3ebdSchin m += k;
1811da2e3ebdSchin }
1812da2e3ebdSchin cp = next;
1813da2e3ebdSchin }
1814da2e3ebdSchin if((k=sfwrite(sp,cp,ep-cp)) < 0)
1815da2e3ebdSchin return(m>0?m:-1);
1816da2e3ebdSchin return(m+k);
1817da2e3ebdSchin }
1818da2e3ebdSchin # define sfwrite _sfwrite
1819da2e3ebdSchin #endif /* SHOPT_CRNL */
1820da2e3ebdSchin
1821da2e3ebdSchin /*
1822da2e3ebdSchin * read in here-document from script
1823da2e3ebdSchin * quoted here documents, and here-documents without special chars are
1824da2e3ebdSchin * noted with the IOQUOTE flag
1825da2e3ebdSchin * returns 1 for complete here-doc, 0 for EOF
1826da2e3ebdSchin */
1827da2e3ebdSchin
here_copy(Lex_t * lp,register struct ionod * iop)1828da2e3ebdSchin static int here_copy(Lex_t *lp,register struct ionod *iop)
1829da2e3ebdSchin {
1830da2e3ebdSchin register const char *state;
1831da2e3ebdSchin register int c,n;
1832da2e3ebdSchin register char *bufp,*cp;
18337c2fbfb3SApril Chin register Sfio_t *sp=lp->sh->heredocs, *funlog;
1834da2e3ebdSchin int stripcol=0,stripflg, nsave, special=0;
18357c2fbfb3SApril Chin if(funlog=lp->sh->funlog)
1836da2e3ebdSchin {
1837da2e3ebdSchin if(fcfill()>0)
1838b30d1939SAndy Fiddaman fcseek(-LEN);
18397c2fbfb3SApril Chin lp->sh->funlog = 0;
1840da2e3ebdSchin }
1841da2e3ebdSchin if(iop->iolst)
1842da2e3ebdSchin here_copy(lp,iop->iolst);
1843da2e3ebdSchin iop->iooffset = sfseek(sp,(off_t)0,SEEK_END);
1844da2e3ebdSchin iop->iosize = 0;
1845da2e3ebdSchin iop->iodelim=iop->ioname;
1846da2e3ebdSchin /* check for and strip quoted characters in delimiter string */
1847da2e3ebdSchin if(stripflg=iop->iofile&IOSTRIP)
1848da2e3ebdSchin {
1849da2e3ebdSchin while(*iop->iodelim=='\t')
1850da2e3ebdSchin iop->iodelim++;
1851da2e3ebdSchin /* skip over leading tabs in document */
1852da2e3ebdSchin if(iop->iofile&IOLSEEK)
1853da2e3ebdSchin {
1854da2e3ebdSchin iop->iofile &= ~IOLSEEK;
1855da2e3ebdSchin while(fcgetc(c)=='\t' || c==' ')
1856da2e3ebdSchin {
1857da2e3ebdSchin if(c==' ')
1858da2e3ebdSchin stripcol++;
1859da2e3ebdSchin else
1860da2e3ebdSchin stripcol += 8 - stripcol%8;
1861da2e3ebdSchin }
1862da2e3ebdSchin }
1863da2e3ebdSchin else
1864da2e3ebdSchin while(fcgetc(c)=='\t');
1865da2e3ebdSchin if(c>0)
1866b30d1939SAndy Fiddaman fcseek(-LEN);
1867da2e3ebdSchin }
1868da2e3ebdSchin if(iop->iofile&IOQUOTE)
1869da2e3ebdSchin state = sh_lexstates[ST_LIT];
1870da2e3ebdSchin else
1871da2e3ebdSchin state = sh_lexstates[ST_QUOTE];
1872da2e3ebdSchin bufp = fcseek(0);
1873da2e3ebdSchin n = S_NL;
1874da2e3ebdSchin while(1)
1875da2e3ebdSchin {
1876da2e3ebdSchin if(n!=S_NL)
1877da2e3ebdSchin {
1878da2e3ebdSchin /* skip over regular characters */
1879b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
1880b30d1939SAndy Fiddaman do
1881b30d1939SAndy Fiddaman {
1882b30d1939SAndy Fiddaman if(fcleft()< MB_LEN_MAX && mbsize(fcseek(0))<0)
1883b30d1939SAndy Fiddaman {
1884b30d1939SAndy Fiddaman n = S_EOF;
1885b30d1939SAndy Fiddaman LEN = -fcleft();
1886b30d1939SAndy Fiddaman break;
1887b30d1939SAndy Fiddaman }
1888b30d1939SAndy Fiddaman }
1889b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
1890b30d1939SAndy Fiddaman
1891da2e3ebdSchin while((n=STATE(state,c))==0);
1892da2e3ebdSchin }
1893da2e3ebdSchin if(n==S_EOF || !(c=fcget()))
1894da2e3ebdSchin {
1895b30d1939SAndy Fiddaman if(LEN < 0)
1896b30d1939SAndy Fiddaman c = fclast()-bufp;
1897b30d1939SAndy Fiddaman else
1898b30d1939SAndy Fiddaman c= (fcseek(0)-1)-bufp;
1899b30d1939SAndy Fiddaman if(!lp->lexd.dolparen && c)
1900da2e3ebdSchin {
1901da2e3ebdSchin if(n==S_ESC)
1902da2e3ebdSchin c--;
1903b30d1939SAndy Fiddaman if(!lp->lexd.dolparen && (c=sfwrite(sp,bufp,c))>0)
1904da2e3ebdSchin iop->iosize += c;
1905da2e3ebdSchin }
1906b30d1939SAndy Fiddaman #if SHOPT_MULTIBYTE
1907b30d1939SAndy Fiddaman if(LEN==0)
1908b30d1939SAndy Fiddaman LEN=1;
1909b30d1939SAndy Fiddaman if(LEN < 0)
1910b30d1939SAndy Fiddaman {
1911b30d1939SAndy Fiddaman n = LEN;
1912b30d1939SAndy Fiddaman c = fcmbget(&LEN);
1913b30d1939SAndy Fiddaman LEN += n;
1914b30d1939SAndy Fiddaman }
1915b30d1939SAndy Fiddaman else
1916b30d1939SAndy Fiddaman #endif /* SHOPT_MULTIBYTE */
1917b30d1939SAndy Fiddaman c = lexfill(lp);
1918b30d1939SAndy Fiddaman if(c<0)
1919da2e3ebdSchin break;
1920da2e3ebdSchin if(n==S_ESC)
1921da2e3ebdSchin {
1922da2e3ebdSchin #if SHOPT_CRNL
1923da2e3ebdSchin if(c=='\r' && (c=fcget())!=NL)
1924b30d1939SAndy Fiddaman fcseek(-LEN);
1925da2e3ebdSchin #endif /* SHOPT_CRNL */
1926da2e3ebdSchin if(c==NL)
1927da2e3ebdSchin fcseek(1);
1928b30d1939SAndy Fiddaman else if(!lp->lexd.dolparen)
1929b30d1939SAndy Fiddaman {
1930b30d1939SAndy Fiddaman iop->iosize++;
1931da2e3ebdSchin sfputc(sp,'\\');
1932b30d1939SAndy Fiddaman }
1933da2e3ebdSchin }
1934b30d1939SAndy Fiddaman bufp = fcseek(-LEN);
1935da2e3ebdSchin }
1936da2e3ebdSchin else
1937b30d1939SAndy Fiddaman fcseek(-LEN);
1938da2e3ebdSchin switch(n)
1939da2e3ebdSchin {
1940da2e3ebdSchin case S_NL:
19417c2fbfb3SApril Chin lp->sh->inlineno++;
1942da2e3ebdSchin if((stripcol && c==' ') || (stripflg && c=='\t'))
1943da2e3ebdSchin {
19447c2fbfb3SApril Chin if(!lp->lexd.dolparen)
1945da2e3ebdSchin {
1946da2e3ebdSchin /* write out line */
1947da2e3ebdSchin n = fcseek(0)-bufp;
1948da2e3ebdSchin if((n=sfwrite(sp,bufp,n))>0)
1949da2e3ebdSchin iop->iosize += n;
1950da2e3ebdSchin }
1951da2e3ebdSchin /* skip over tabs */
1952da2e3ebdSchin if(stripcol)
1953da2e3ebdSchin {
1954da2e3ebdSchin int col=0;
1955da2e3ebdSchin do
1956da2e3ebdSchin {
1957da2e3ebdSchin fcgetc(c);
1958da2e3ebdSchin if(c==' ')
1959da2e3ebdSchin col++;
1960da2e3ebdSchin else
1961da2e3ebdSchin col += 8 - col%8;
1962da2e3ebdSchin if(col>stripcol)
1963da2e3ebdSchin break;
1964da2e3ebdSchin }
1965da2e3ebdSchin while (c==' ' || c=='\t');
1966da2e3ebdSchin }
1967da2e3ebdSchin else while(c=='\t')
1968da2e3ebdSchin fcgetc(c);
1969da2e3ebdSchin if(c<=0)
1970da2e3ebdSchin goto done;
1971b30d1939SAndy Fiddaman bufp = fcseek(-LEN);
1972da2e3ebdSchin }
1973da2e3ebdSchin if(c!=iop->iodelim[0])
1974da2e3ebdSchin break;
1975da2e3ebdSchin cp = fcseek(0);
1976da2e3ebdSchin nsave = n = 0;
1977da2e3ebdSchin while(1)
1978da2e3ebdSchin {
1979da2e3ebdSchin if(!(c=fcget()))
1980da2e3ebdSchin {
19817c2fbfb3SApril Chin if(!lp->lexd.dolparen && (c=cp-bufp))
1982da2e3ebdSchin {
1983da2e3ebdSchin if((c=sfwrite(sp,cp=bufp,c))>0)
1984da2e3ebdSchin iop->iosize+=c;
1985da2e3ebdSchin }
1986da2e3ebdSchin nsave = n;
19877c2fbfb3SApril Chin if((c=lexfill(lp))<=0)
1988da2e3ebdSchin {
1989da2e3ebdSchin c = iop->iodelim[n]==0;
1990da2e3ebdSchin goto done;
1991da2e3ebdSchin }
1992da2e3ebdSchin }
1993da2e3ebdSchin #if SHOPT_CRNL
1994da2e3ebdSchin if(c=='\r' && (c=fcget())!=NL)
1995da2e3ebdSchin {
1996da2e3ebdSchin if(c)
1997b30d1939SAndy Fiddaman fcseek(-LEN);
1998da2e3ebdSchin c='\r';
1999da2e3ebdSchin }
2000da2e3ebdSchin #endif /* SHOPT_CRNL */
2001da2e3ebdSchin if(c==NL)
20027c2fbfb3SApril Chin lp->sh->inlineno++;
2003da2e3ebdSchin if(iop->iodelim[n]==0 && (c==NL||c==RPAREN))
2004da2e3ebdSchin {
20057c2fbfb3SApril Chin if(!lp->lexd.dolparen && (n=cp-bufp))
2006da2e3ebdSchin {
2007da2e3ebdSchin if((n=sfwrite(sp,bufp,n))>0)
2008da2e3ebdSchin iop->iosize += n;
2009da2e3ebdSchin }
20107c2fbfb3SApril Chin lp->sh->inlineno--;
2011da2e3ebdSchin if(c==RPAREN)
2012b30d1939SAndy Fiddaman fcseek(-LEN);
2013da2e3ebdSchin goto done;
2014da2e3ebdSchin }
2015da2e3ebdSchin if(iop->iodelim[n++]!=c)
2016da2e3ebdSchin {
2017da2e3ebdSchin /*
2018da2e3ebdSchin * The match for delimiter failed.
2019da2e3ebdSchin * nsave>0 only when a buffer boundary
2020da2e3ebdSchin * was crossed while checking the
2021da2e3ebdSchin * delimiter
2022da2e3ebdSchin */
20237c2fbfb3SApril Chin if(!lp->lexd.dolparen && nsave>0)
2024da2e3ebdSchin {
2025b30d1939SAndy Fiddaman if((n=sfwrite(sp,iop->iodelim,nsave))>0)
2026da2e3ebdSchin iop->iosize += n;
2027da2e3ebdSchin bufp = fcfirst();
2028da2e3ebdSchin }
2029da2e3ebdSchin if(c==NL)
2030b30d1939SAndy Fiddaman fcseek(-LEN);
2031da2e3ebdSchin break;
2032da2e3ebdSchin }
2033da2e3ebdSchin }
2034da2e3ebdSchin break;
2035da2e3ebdSchin case S_ESC:
2036da2e3ebdSchin n=1;
2037da2e3ebdSchin #if SHOPT_CRNL
2038da2e3ebdSchin if(c=='\r')
2039da2e3ebdSchin {
2040da2e3ebdSchin fcseek(1);
2041da2e3ebdSchin if(c=fcget())
2042b30d1939SAndy Fiddaman fcseek(-LEN);
2043da2e3ebdSchin if(c==NL)
2044da2e3ebdSchin n=2;
2045da2e3ebdSchin else
2046da2e3ebdSchin {
2047da2e3ebdSchin special++;
2048da2e3ebdSchin break;
2049da2e3ebdSchin }
2050da2e3ebdSchin }
2051da2e3ebdSchin #endif /* SHOPT_CRNL */
2052da2e3ebdSchin if(c==NL)
2053da2e3ebdSchin {
2054da2e3ebdSchin /* new-line joining */
20557c2fbfb3SApril Chin lp->sh->inlineno++;
205634f9b3eeSRoland Mainz if(!lp->lexd.dolparen && (n=(fcseek(0)-bufp)-n)>=0)
2057da2e3ebdSchin {
205834f9b3eeSRoland Mainz if(n && (n=sfwrite(sp,bufp,n))>0)
2059da2e3ebdSchin iop->iosize += n;
2060da2e3ebdSchin bufp = fcseek(0)+1;
2061da2e3ebdSchin }
2062da2e3ebdSchin }
2063da2e3ebdSchin else
2064da2e3ebdSchin special++;
2065da2e3ebdSchin fcget();
2066da2e3ebdSchin break;
2067da2e3ebdSchin
2068da2e3ebdSchin case S_GRAVE:
2069da2e3ebdSchin case S_DOL:
2070da2e3ebdSchin special++;
2071da2e3ebdSchin break;
2072da2e3ebdSchin }
2073da2e3ebdSchin n=0;
2074da2e3ebdSchin }
2075da2e3ebdSchin done:
20767c2fbfb3SApril Chin lp->sh->funlog = funlog;
20777c2fbfb3SApril Chin if(lp->lexd.dolparen)
2078da2e3ebdSchin free((void*)iop);
2079da2e3ebdSchin else if(!special)
2080da2e3ebdSchin iop->iofile |= IOQUOTE;
2081da2e3ebdSchin return(c);
2082da2e3ebdSchin }
2083da2e3ebdSchin
2084da2e3ebdSchin /*
2085da2e3ebdSchin * generates string for given token
2086da2e3ebdSchin */
fmttoken(Lex_t * lp,register int sym,char * tok)2087da2e3ebdSchin static char *fmttoken(Lex_t *lp, register int sym, char *tok)
2088da2e3ebdSchin {
208934f9b3eeSRoland Mainz int n=1;
2090da2e3ebdSchin if(sym < 0)
2091da2e3ebdSchin return((char*)sh_translate(e_lexzerobyte));
2092da2e3ebdSchin if(sym==0)
20937c2fbfb3SApril Chin return(lp->arg?lp->arg->argval:"?");
20947c2fbfb3SApril Chin if(lp->lex.intest && lp->arg && *lp->arg->argval)
20957c2fbfb3SApril Chin return(lp->arg->argval);
2096da2e3ebdSchin if(sym&SYMRES)
2097da2e3ebdSchin {
2098da2e3ebdSchin register const Shtable_t *tp=shtab_reserved;
2099da2e3ebdSchin while(tp->sh_number && tp->sh_number!=sym)
2100da2e3ebdSchin tp++;
2101da2e3ebdSchin return((char*)tp->sh_name);
2102da2e3ebdSchin }
2103da2e3ebdSchin if(sym==EOFSYM)
2104da2e3ebdSchin return((char*)sh_translate(e_endoffile));
2105da2e3ebdSchin if(sym==NL)
2106da2e3ebdSchin return((char*)sh_translate(e_newline));
2107da2e3ebdSchin tok[0] = sym;
2108da2e3ebdSchin if(sym&SYMREP)
210934f9b3eeSRoland Mainz tok[n++] = sym;
2110da2e3ebdSchin else
2111da2e3ebdSchin {
2112da2e3ebdSchin switch(sym&SYMMASK)
2113da2e3ebdSchin {
2114da2e3ebdSchin case SYMAMP:
2115da2e3ebdSchin sym = '&';
2116da2e3ebdSchin break;
2117da2e3ebdSchin case SYMPIPE:
2118da2e3ebdSchin sym = '|';
2119da2e3ebdSchin break;
2120da2e3ebdSchin case SYMGT:
2121da2e3ebdSchin sym = '>';
2122da2e3ebdSchin break;
2123da2e3ebdSchin case SYMLPAR:
2124da2e3ebdSchin sym = LPAREN;
2125da2e3ebdSchin break;
2126da2e3ebdSchin case SYMSHARP:
2127da2e3ebdSchin sym = '#';
2128da2e3ebdSchin break;
21297c2fbfb3SApril Chin case SYMSEMI:
213034f9b3eeSRoland Mainz if(tok[0]=='<')
213134f9b3eeSRoland Mainz tok[n++] = '>';
21327c2fbfb3SApril Chin sym = ';';
21337c2fbfb3SApril Chin break;
2134da2e3ebdSchin default:
2135da2e3ebdSchin sym = 0;
2136da2e3ebdSchin }
213734f9b3eeSRoland Mainz tok[n++] = sym;
2138da2e3ebdSchin }
213934f9b3eeSRoland Mainz tok[n] = 0;
2140da2e3ebdSchin return(tok);
2141da2e3ebdSchin }
2142da2e3ebdSchin
2143da2e3ebdSchin /*
2144da2e3ebdSchin * print a bad syntax message
2145da2e3ebdSchin */
2146da2e3ebdSchin
sh_syntax(Lex_t * lp)21477c2fbfb3SApril Chin void sh_syntax(Lex_t *lp)
2148da2e3ebdSchin {
21497c2fbfb3SApril Chin register Shell_t *shp = lp->sh;
2150da2e3ebdSchin register const char *cp = sh_translate(e_unexpected);
2151da2e3ebdSchin register char *tokstr;
21527c2fbfb3SApril Chin register int tok = lp->token;
2153da2e3ebdSchin char tokbuf[3];
2154da2e3ebdSchin Sfio_t *sp;
21557c2fbfb3SApril Chin if((tok==EOFSYM) && lp->lasttok)
2156da2e3ebdSchin {
21577c2fbfb3SApril Chin tok = lp->lasttok;
2158da2e3ebdSchin cp = sh_translate(e_unmatched);
2159da2e3ebdSchin }
2160da2e3ebdSchin else
21617c2fbfb3SApril Chin lp->lastline = shp->inlineno;
2162da2e3ebdSchin tokstr = fmttoken(lp,tok,tokbuf);
2163b30d1939SAndy Fiddaman VALIDATE_FD(shp, shp->infd);
2164da2e3ebdSchin if((sp=fcfile()) || (shp->infd>=0 && (sp=shp->sftable[shp->infd])))
2165da2e3ebdSchin {
2166da2e3ebdSchin /* clear out any pending input */
2167da2e3ebdSchin register Sfio_t *top;
2168da2e3ebdSchin while(fcget()>0);
2169da2e3ebdSchin fcclose();
2170da2e3ebdSchin while(top=sfstack(sp,SF_POPSTACK))
2171da2e3ebdSchin sfclose(top);
2172da2e3ebdSchin }
2173da2e3ebdSchin else
2174da2e3ebdSchin fcclose();
21757c2fbfb3SApril Chin shp->inlineno = lp->inlineno;
21767c2fbfb3SApril Chin shp->st.firstline = lp->firstline;
2177da2e3ebdSchin #if KSHELL
2178da2e3ebdSchin if(!sh_isstate(SH_INTERACTIVE) && !sh_isstate(SH_PROFILE))
2179da2e3ebdSchin #else
2180da2e3ebdSchin if(shp->inlineno!=1)
2181da2e3ebdSchin #endif
21827c2fbfb3SApril Chin errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax1,lp->lastline,tokstr,cp);
2183da2e3ebdSchin else
2184da2e3ebdSchin errormsg(SH_DICT,ERROR_exit(SYNBAD),e_lexsyntax2,tokstr,cp);
2185da2e3ebdSchin }
2186da2e3ebdSchin
stack_shift(Stk_t * stkp,register char * sp,char * dp)21877c2fbfb3SApril Chin static char *stack_shift(Stk_t *stkp, register char *sp,char *dp)
2188da2e3ebdSchin {
2189da2e3ebdSchin register char *ep;
21907c2fbfb3SApril Chin register int offset = stktell(stkp);
21917c2fbfb3SApril Chin register int left = offset-(sp-stkptr(stkp,0));
2192da2e3ebdSchin register int shift = (dp+1-sp);
2193da2e3ebdSchin offset += shift;
21947c2fbfb3SApril Chin stkseek(stkp,offset);
21957c2fbfb3SApril Chin sp = stkptr(stkp,offset);
2196da2e3ebdSchin ep = sp - shift;
2197da2e3ebdSchin while(left--)
2198da2e3ebdSchin *--sp = *--ep;
2199da2e3ebdSchin return(sp);
2200da2e3ebdSchin }
2201da2e3ebdSchin
2202da2e3ebdSchin /*
2203da2e3ebdSchin * Assumes that current word is unfrozen on top of the stak
2204da2e3ebdSchin * If <mode> is zero, gets rid of quoting and consider argument as string
2205da2e3ebdSchin * and returns pointer to frozen arg
2206da2e3ebdSchin * If mode==1, just replace $"..." strings with international strings
2207da2e3ebdSchin * The result is left on the stak
2208da2e3ebdSchin * If mode==2, the each $"" string is printed on standard output
2209da2e3ebdSchin */
sh_endword(Shell_t * shp,int mode)22107c2fbfb3SApril Chin struct argnod *sh_endword(Shell_t *shp,int mode)
2211da2e3ebdSchin {
2212da2e3ebdSchin register const char *state = sh_lexstates[ST_NESTED];
2213da2e3ebdSchin register int n;
2214da2e3ebdSchin register char *sp,*dp;
2215da2e3ebdSchin register int inquote=0, inlit=0; /* set within quoted strings */
2216da2e3ebdSchin struct argnod* argp=0;
2217da2e3ebdSchin char *ep=0, *xp=0;
2218da2e3ebdSchin int bracket=0;
22197c2fbfb3SApril Chin Stk_t *stkp=shp->stk;
22207c2fbfb3SApril Chin sfputc(stkp,0);
22217c2fbfb3SApril Chin sp = stkptr(stkp,ARGVAL);
2222da2e3ebdSchin #if SHOPT_MULTIBYTE
2223da2e3ebdSchin if(mbwide())
2224da2e3ebdSchin {
2225da2e3ebdSchin do
2226da2e3ebdSchin {
2227da2e3ebdSchin int len;
2228da2e3ebdSchin switch(len = mbsize(sp))
2229da2e3ebdSchin {
2230da2e3ebdSchin case -1: /* illegal multi-byte char */
2231da2e3ebdSchin case 0:
2232da2e3ebdSchin case 1:
2233da2e3ebdSchin n=state[*sp++];
2234da2e3ebdSchin break;
2235da2e3ebdSchin default:
2236da2e3ebdSchin /*
2237da2e3ebdSchin * None of the state tables contain
2238da2e3ebdSchin * entries for multibyte characters,
2239da2e3ebdSchin * however, they should be treated
2240da2e3ebdSchin * the same as any other alph
2241da2e3ebdSchin * character. Therefore, we'll use
2242da2e3ebdSchin * the state of the 'a' character.
2243da2e3ebdSchin */
2244da2e3ebdSchin n=state['a'];
2245da2e3ebdSchin sp += len;
2246da2e3ebdSchin }
2247da2e3ebdSchin }
2248da2e3ebdSchin while(n == 0);
2249da2e3ebdSchin }
2250da2e3ebdSchin else
2251da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
2252da2e3ebdSchin while((n=state[*sp++])==0);
2253da2e3ebdSchin dp = sp;
2254da2e3ebdSchin if(mode<0)
2255da2e3ebdSchin inquote = 1;
2256da2e3ebdSchin while(1)
2257da2e3ebdSchin {
2258da2e3ebdSchin switch(n)
2259da2e3ebdSchin {
2260da2e3ebdSchin case S_EOF:
22617c2fbfb3SApril Chin stkseek(stkp,dp-stkptr(stkp,0));
2262da2e3ebdSchin if(mode<=0)
2263da2e3ebdSchin {
22647c2fbfb3SApril Chin argp = (struct argnod*)stkfreeze(stkp,0);
2265da2e3ebdSchin argp->argflag = ARG_RAW|ARG_QUOTED;
2266da2e3ebdSchin }
2267da2e3ebdSchin return(argp);
2268da2e3ebdSchin case S_LIT:
2269da2e3ebdSchin if(!(inquote&1))
2270da2e3ebdSchin {
2271da2e3ebdSchin inlit = !inlit;
2272da2e3ebdSchin if(mode==0 || (mode<0 && bracket))
2273da2e3ebdSchin {
2274da2e3ebdSchin dp--;
2275da2e3ebdSchin if(ep)
2276da2e3ebdSchin {
2277da2e3ebdSchin *dp = 0;
2278b30d1939SAndy Fiddaman stresc(ep);
2279b30d1939SAndy Fiddaman dp = ep+ strlen(ep);
2280da2e3ebdSchin }
2281da2e3ebdSchin ep = 0;
2282da2e3ebdSchin }
2283da2e3ebdSchin }
2284da2e3ebdSchin break;
2285da2e3ebdSchin case S_QUOTE:
2286da2e3ebdSchin if(mode<0 && !bracket)
2287da2e3ebdSchin break;
2288da2e3ebdSchin if(!inlit)
2289da2e3ebdSchin {
2290da2e3ebdSchin if(mode<=0)
2291da2e3ebdSchin dp--;
2292da2e3ebdSchin inquote = inquote^1;
2293da2e3ebdSchin if(ep)
2294da2e3ebdSchin {
2295da2e3ebdSchin char *msg;
2296da2e3ebdSchin if(mode==2)
2297da2e3ebdSchin {
2298da2e3ebdSchin sfprintf(sfstdout,"%.*s\n",dp-ep,ep);
2299da2e3ebdSchin ep = 0;
2300da2e3ebdSchin break;
2301da2e3ebdSchin }
2302da2e3ebdSchin *--dp = 0;
2303da2e3ebdSchin #if ERROR_VERSION >= 20000317L
2304da2e3ebdSchin msg = ERROR_translate(0,error_info.id,0,ep);
2305da2e3ebdSchin #else
2306da2e3ebdSchin # if ERROR_VERSION >= 20000101L
2307da2e3ebdSchin msg = ERROR_translate(error_info.id,ep);
2308da2e3ebdSchin # else
2309da2e3ebdSchin msg = ERROR_translate(ep,2);
2310da2e3ebdSchin # endif
2311da2e3ebdSchin #endif
2312da2e3ebdSchin n = strlen(msg);
2313da2e3ebdSchin dp = ep+n;
2314da2e3ebdSchin if(sp-dp <= 1)
2315da2e3ebdSchin {
23167c2fbfb3SApril Chin sp = stack_shift(stkp,sp,dp);
2317da2e3ebdSchin dp = sp-1;
2318da2e3ebdSchin ep = dp-n;
2319da2e3ebdSchin }
2320da2e3ebdSchin memmove(ep,msg,n);
2321da2e3ebdSchin *dp++ = '"';
2322da2e3ebdSchin }
2323da2e3ebdSchin ep = 0;
2324da2e3ebdSchin }
2325da2e3ebdSchin break;
2326da2e3ebdSchin case S_DOL: /* check for $'...' and $"..." */
2327da2e3ebdSchin if(inlit)
2328da2e3ebdSchin break;
2329da2e3ebdSchin if(*sp==LPAREN || *sp==LBRACE)
2330da2e3ebdSchin {
2331da2e3ebdSchin inquote <<= 1;
2332da2e3ebdSchin break;
2333da2e3ebdSchin }
2334da2e3ebdSchin if(inquote&1)
2335da2e3ebdSchin break;
2336da2e3ebdSchin if(*sp=='\'' || *sp=='"')
2337da2e3ebdSchin {
2338da2e3ebdSchin if(*sp=='"')
2339da2e3ebdSchin inquote |= 1;
2340da2e3ebdSchin else
2341da2e3ebdSchin inlit = 1;
2342da2e3ebdSchin sp++;
2343da2e3ebdSchin if((mode==0||(mode<0&&bracket)) || (inquote&1))
2344da2e3ebdSchin {
2345da2e3ebdSchin if(mode==2)
2346da2e3ebdSchin ep = dp++;
2347da2e3ebdSchin else if(mode==1)
2348da2e3ebdSchin (ep=dp)[-1] = '"';
2349da2e3ebdSchin else
2350da2e3ebdSchin ep = --dp;
2351da2e3ebdSchin }
2352da2e3ebdSchin }
2353da2e3ebdSchin break;
2354da2e3ebdSchin case S_ESC:
2355da2e3ebdSchin #if SHOPT_CRNL
2356da2e3ebdSchin if(*sp=='\r' && sp[1]=='\n')
2357da2e3ebdSchin sp++;
2358da2e3ebdSchin #endif /* SHOPT_CRNL */
2359da2e3ebdSchin if(inlit || mode>0)
2360da2e3ebdSchin {
2361da2e3ebdSchin if(mode<0)
2362da2e3ebdSchin {
2363da2e3ebdSchin if(dp>=sp)
2364da2e3ebdSchin {
23657c2fbfb3SApril Chin sp = stack_shift(stkp,sp,dp+1);
2366da2e3ebdSchin dp = sp-2;
2367da2e3ebdSchin }
2368da2e3ebdSchin *dp++ = '\\';
2369da2e3ebdSchin }
2370da2e3ebdSchin if(ep)
2371da2e3ebdSchin *dp++ = *sp++;
2372da2e3ebdSchin break;
2373da2e3ebdSchin }
2374da2e3ebdSchin n = *sp;
2375da2e3ebdSchin #if SHOPT_DOS
2376da2e3ebdSchin if(!(inquote&1) && sh_lexstates[ST_NORM][n]==0)
2377da2e3ebdSchin break;
2378da2e3ebdSchin #endif /* SHOPT_DOS */
2379da2e3ebdSchin if(!(inquote&1) || (sh_lexstates[ST_QUOTE][n] && n!=RBRACE))
2380da2e3ebdSchin {
2381da2e3ebdSchin if(n=='\n')
2382da2e3ebdSchin dp--;
2383da2e3ebdSchin else
2384da2e3ebdSchin dp[-1] = n;
2385da2e3ebdSchin sp++;
2386da2e3ebdSchin }
2387da2e3ebdSchin break;
2388da2e3ebdSchin case S_POP:
2389da2e3ebdSchin if(sp[-1]!=RBRACT)
2390da2e3ebdSchin break;
2391da2e3ebdSchin if(!inlit && !(inquote&1))
2392da2e3ebdSchin {
2393da2e3ebdSchin inquote >>= 1;
2394da2e3ebdSchin if(xp)
2395da2e3ebdSchin dp = sh_checkid(xp,dp);
2396da2e3ebdSchin xp = 0;
2397da2e3ebdSchin if(--bracket<=0 && mode<0)
2398da2e3ebdSchin inquote = 1;
2399da2e3ebdSchin }
2400da2e3ebdSchin else if((inlit||inquote) && mode<0)
2401da2e3ebdSchin {
2402da2e3ebdSchin dp[-1] = '\\';
2403da2e3ebdSchin if(dp>=sp)
2404da2e3ebdSchin {
24057c2fbfb3SApril Chin sp = stack_shift(stkp,sp,dp);
2406da2e3ebdSchin dp = sp-1;
2407da2e3ebdSchin }
2408da2e3ebdSchin *dp++ = ']';
2409da2e3ebdSchin }
2410da2e3ebdSchin break;
2411da2e3ebdSchin case S_BRACT:
2412da2e3ebdSchin if(dp[-2]=='.')
2413da2e3ebdSchin xp = dp;
2414da2e3ebdSchin if(mode<0)
2415da2e3ebdSchin {
2416da2e3ebdSchin if(inlit || (bracket&&inquote))
2417da2e3ebdSchin {
2418da2e3ebdSchin dp[-1] = '\\';
2419da2e3ebdSchin if(dp>=sp)
2420da2e3ebdSchin {
24217c2fbfb3SApril Chin sp = stack_shift(stkp,sp,dp);
2422da2e3ebdSchin dp = sp-1;
2423da2e3ebdSchin }
2424da2e3ebdSchin *dp++ = '[';
2425da2e3ebdSchin }
2426da2e3ebdSchin else if(bracket++==0)
2427da2e3ebdSchin inquote = 0;
2428da2e3ebdSchin }
2429da2e3ebdSchin break;
2430da2e3ebdSchin }
2431da2e3ebdSchin #if SHOPT_MULTIBYTE
2432da2e3ebdSchin if(mbwide())
2433da2e3ebdSchin {
2434da2e3ebdSchin do
2435da2e3ebdSchin {
2436da2e3ebdSchin int len;
2437da2e3ebdSchin switch(len = mbsize(sp))
2438da2e3ebdSchin {
2439da2e3ebdSchin case -1: /* illegal multi-byte char */
2440da2e3ebdSchin case 0:
2441da2e3ebdSchin case 1:
2442da2e3ebdSchin n=state[*dp++ = *sp++];
2443da2e3ebdSchin break;
2444da2e3ebdSchin default:
2445da2e3ebdSchin /*
2446da2e3ebdSchin * None of the state tables contain
2447da2e3ebdSchin * entries for multibyte characters,
2448da2e3ebdSchin * however, they should be treated
2449da2e3ebdSchin * the same as any other alph
2450da2e3ebdSchin * character. Therefore, we'll use
2451da2e3ebdSchin * the state of the 'a' character.
2452da2e3ebdSchin */
2453da2e3ebdSchin while(len--)
2454da2e3ebdSchin *dp++ = *sp++;
2455da2e3ebdSchin n=state['a'];
2456da2e3ebdSchin }
2457da2e3ebdSchin }
2458da2e3ebdSchin while(n == 0);
2459da2e3ebdSchin }
2460da2e3ebdSchin else
2461da2e3ebdSchin #endif /* SHOPT_MULTIBYTE */
2462da2e3ebdSchin while((n=state[*dp++ = *sp++])==0);
2463da2e3ebdSchin }
2464da2e3ebdSchin }
2465da2e3ebdSchin
2466da2e3ebdSchin struct alias
2467da2e3ebdSchin {
2468da2e3ebdSchin Sfdisc_t disc;
2469da2e3ebdSchin Namval_t *np;
2470da2e3ebdSchin int nextc;
2471da2e3ebdSchin int line;
2472da2e3ebdSchin char buf[2];
2473da2e3ebdSchin Lex_t *lp;
2474da2e3ebdSchin };
2475da2e3ebdSchin
2476da2e3ebdSchin /*
2477da2e3ebdSchin * This code gets called whenever an end of string is found with alias
2478da2e3ebdSchin */
2479da2e3ebdSchin
2480da2e3ebdSchin #ifndef SF_ATEXIT
2481da2e3ebdSchin # define SF_ATEXIT 0
2482da2e3ebdSchin #endif
2483da2e3ebdSchin /*
2484da2e3ebdSchin * This code gets called whenever an end of string is found with alias
2485da2e3ebdSchin */
2486da2e3ebdSchin #ifdef SF_BUFCONST
alias_exceptf(Sfio_t * iop,int type,void * data,Sfdisc_t * handle)2487da2e3ebdSchin static int alias_exceptf(Sfio_t *iop,int type,void *data, Sfdisc_t *handle)
2488da2e3ebdSchin #else
2489da2e3ebdSchin static int alias_exceptf(Sfio_t *iop,int type,Sfdisc_t *handle)
2490da2e3ebdSchin #endif
2491da2e3ebdSchin {
2492da2e3ebdSchin register struct alias *ap = (struct alias*)handle;
2493da2e3ebdSchin register Namval_t *np;
2494da2e3ebdSchin register Lex_t *lp;
2495da2e3ebdSchin if(type==0 || type==SF_ATEXIT || !ap)
2496da2e3ebdSchin return(0);
2497da2e3ebdSchin lp = ap->lp;
2498da2e3ebdSchin np = ap->np;
2499da2e3ebdSchin if(type!=SF_READ)
2500da2e3ebdSchin {
2501da2e3ebdSchin if(type==SF_CLOSING)
2502da2e3ebdSchin {
2503da2e3ebdSchin register Sfdisc_t *dp = sfdisc(iop,SF_POPDISC);
2504da2e3ebdSchin if(dp!=handle)
2505da2e3ebdSchin sfdisc(iop,dp);
2506da2e3ebdSchin }
2507da2e3ebdSchin else if(type==SF_FINAL)
2508da2e3ebdSchin free((void*)ap);
2509da2e3ebdSchin goto done;
2510da2e3ebdSchin }
2511da2e3ebdSchin if(ap->nextc)
2512da2e3ebdSchin {
2513da2e3ebdSchin /* if last character is a blank, then next work can be alias */
2514da2e3ebdSchin register int c = fcpeek(-1);
2515da2e3ebdSchin if(isblank(c))
25167c2fbfb3SApril Chin lp->aliasok = 1;
2517da2e3ebdSchin *ap->buf = ap->nextc;
2518da2e3ebdSchin ap->nextc = 0;
2519da2e3ebdSchin sfsetbuf(iop,ap->buf,1);
2520da2e3ebdSchin return(1);
2521da2e3ebdSchin }
2522da2e3ebdSchin done:
2523da2e3ebdSchin if(np)
2524da2e3ebdSchin nv_offattr(np,NV_NOEXPAND);
2525da2e3ebdSchin return(0);
2526da2e3ebdSchin }
2527da2e3ebdSchin
2528da2e3ebdSchin
setupalias(Lex_t * lp,const char * string,Namval_t * np)2529da2e3ebdSchin static void setupalias(Lex_t *lp, const char *string,Namval_t *np)
2530da2e3ebdSchin {
2531da2e3ebdSchin register Sfio_t *iop, *base;
2532da2e3ebdSchin struct alias *ap = (struct alias*)malloc(sizeof(struct alias));
2533da2e3ebdSchin ap->disc = alias_disc;
2534da2e3ebdSchin ap->lp = lp;
2535da2e3ebdSchin ap->buf[1] = 0;
2536da2e3ebdSchin if(ap->np = np)
2537da2e3ebdSchin {
2538da2e3ebdSchin #if SHOPT_KIA
25397c2fbfb3SApril Chin if(lp->kiafile)
2540da2e3ebdSchin {
2541da2e3ebdSchin unsigned long r;
25427c2fbfb3SApril Chin r=kiaentity(lp,nv_name(np),-1,'p',0,0,lp->current,'a',0,"");
25437c2fbfb3SApril Chin sfprintf(lp->kiatmp,"p;%..64d;p;%..64d;%d;%d;e;\n",lp->current,r,lp->sh->inlineno,lp->sh->inlineno);
2544da2e3ebdSchin }
2545da2e3ebdSchin #endif /* SHOPT_KIA */
2546da2e3ebdSchin if((ap->nextc=fcget())==0)
2547da2e3ebdSchin ap->nextc = ' ';
2548da2e3ebdSchin }
2549da2e3ebdSchin else
2550da2e3ebdSchin ap->nextc = 0;
2551da2e3ebdSchin iop = sfopen(NIL(Sfio_t*),(char*)string,"s");
2552da2e3ebdSchin sfdisc(iop, &ap->disc);
25537c2fbfb3SApril Chin lp->lexd.nocopy++;
2554da2e3ebdSchin if(!(base=fcfile()))
2555da2e3ebdSchin base = sfopen(NIL(Sfio_t*),fcseek(0),"s");
2556da2e3ebdSchin fcclose();
2557da2e3ebdSchin sfstack(base,iop);
2558da2e3ebdSchin fcfopen(base);
25597c2fbfb3SApril Chin lp->lexd.nocopy--;
2560da2e3ebdSchin }
2561da2e3ebdSchin
2562da2e3ebdSchin /*
2563da2e3ebdSchin * grow storage stack for nested constructs by STACK_ARRAY
2564da2e3ebdSchin */
stack_grow(Lex_t * lp)2565da2e3ebdSchin static int stack_grow(Lex_t *lp)
2566da2e3ebdSchin {
25677c2fbfb3SApril Chin lp->lexd.lex_max += STACK_ARRAY;
25687c2fbfb3SApril Chin if(lp->lexd.lex_match)
25697c2fbfb3SApril Chin lp->lexd.lex_match = (int*)realloc((char*)lp->lexd.lex_match,sizeof(int)*lp->lexd.lex_max);
2570da2e3ebdSchin else
25717c2fbfb3SApril Chin lp->lexd.lex_match = (int*)malloc(sizeof(int)*STACK_ARRAY);
25727c2fbfb3SApril Chin return(lp->lexd.lex_match!=0);
2573da2e3ebdSchin }
2574da2e3ebdSchin
2575