1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman *                                                                      *
3*b30d1939SAndy Fiddaman *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1982-2011 AT&T Intellectual Property          *
5*b30d1939SAndy Fiddaman *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*b30d1939SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*b30d1939SAndy Fiddaman *                                                                      *
9*b30d1939SAndy Fiddaman *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*b30d1939SAndy Fiddaman *                                                                      *
13*b30d1939SAndy Fiddaman *              Information and Software Systems Research               *
14*b30d1939SAndy Fiddaman *                            AT&T Research                             *
15*b30d1939SAndy Fiddaman *                           Florham Park NJ                            *
16*b30d1939SAndy Fiddaman *                                                                      *
17*b30d1939SAndy Fiddaman *                  David Korn <dgk@research.att.com>                   *
18*b30d1939SAndy Fiddaman *                                                                      *
19*b30d1939SAndy Fiddaman ***********************************************************************/
20*b30d1939SAndy Fiddaman #pragma prototyped
21*b30d1939SAndy Fiddaman /*
22*b30d1939SAndy Fiddaman  *	File name expansion
23*b30d1939SAndy Fiddaman  *
24*b30d1939SAndy Fiddaman  *	David Korn
25*b30d1939SAndy Fiddaman  *	AT&T Labs
26*b30d1939SAndy Fiddaman  *
27*b30d1939SAndy Fiddaman  */
28*b30d1939SAndy Fiddaman 
29*b30d1939SAndy Fiddaman #if KSHELL
30*b30d1939SAndy Fiddaman #   include	"defs.h"
31*b30d1939SAndy Fiddaman #   include	"variables.h"
32*b30d1939SAndy Fiddaman #   include	"test.h"
33*b30d1939SAndy Fiddaman #else
34*b30d1939SAndy Fiddaman #   include	<ast.h>
35*b30d1939SAndy Fiddaman #   include	<ctype.h>
36*b30d1939SAndy Fiddaman #   include	<setjmp.h>
37*b30d1939SAndy Fiddaman #endif /* KSHELL */
38*b30d1939SAndy Fiddaman #include	<glob.h>
39*b30d1939SAndy Fiddaman #include	<ls.h>
40*b30d1939SAndy Fiddaman #include	<stak.h>
41*b30d1939SAndy Fiddaman #include	<ast_dir.h>
42*b30d1939SAndy Fiddaman #include	"io.h"
43*b30d1939SAndy Fiddaman #include	"path.h"
44*b30d1939SAndy Fiddaman 
45*b30d1939SAndy Fiddaman #if !SHOPT_BRACEPAT
46*b30d1939SAndy Fiddaman #   define SHOPT_BRACEPAT	0
47*b30d1939SAndy Fiddaman #endif
48*b30d1939SAndy Fiddaman 
49*b30d1939SAndy Fiddaman #if KSHELL
50*b30d1939SAndy Fiddaman #   define argbegin	argnxt.cp
51*b30d1939SAndy Fiddaman     static	const char	*sufstr;
52*b30d1939SAndy Fiddaman     static	int		suflen;
53*b30d1939SAndy Fiddaman     static int scantree(Dt_t*,const char*, struct argnod**);
54*b30d1939SAndy Fiddaman #else
55*b30d1939SAndy Fiddaman #   define sh_sigcheck(sig)	(0)
56*b30d1939SAndy Fiddaman #   define sh_access		access
57*b30d1939SAndy Fiddaman #   define suflen		0
58*b30d1939SAndy Fiddaman #endif /* KSHELL */
59*b30d1939SAndy Fiddaman 
60*b30d1939SAndy Fiddaman 
61*b30d1939SAndy Fiddaman /*
62*b30d1939SAndy Fiddaman  * This routine builds a list of files that match a given pathname
63*b30d1939SAndy Fiddaman  * Uses external routine strgrpmatch() to match each component
64*b30d1939SAndy Fiddaman  * A leading . must match explicitly
65*b30d1939SAndy Fiddaman  *
66*b30d1939SAndy Fiddaman  */
67*b30d1939SAndy Fiddaman 
68*b30d1939SAndy Fiddaman #ifndef GLOB_AUGMENTED
69*b30d1939SAndy Fiddaman #   define GLOB_AUGMENTED	0
70*b30d1939SAndy Fiddaman #endif
71*b30d1939SAndy Fiddaman 
72*b30d1939SAndy Fiddaman #define GLOB_RESCAN 1
73*b30d1939SAndy Fiddaman #define globptr()	((struct glob*)membase)
74*b30d1939SAndy Fiddaman 
75*b30d1939SAndy Fiddaman static struct glob	 *membase;
76*b30d1939SAndy Fiddaman 
77*b30d1939SAndy Fiddaman #if GLOB_VERSION >= 20010916L
nextdir(glob_t * gp,char * dir)78*b30d1939SAndy Fiddaman static char *nextdir(glob_t *gp, char *dir)
79*b30d1939SAndy Fiddaman {
80*b30d1939SAndy Fiddaman 	Shell_t	*shp = sh_getinterp();
81*b30d1939SAndy Fiddaman 	Pathcomp_t *pp = (Pathcomp_t*)gp->gl_handle;
82*b30d1939SAndy Fiddaman 	if(!dir)
83*b30d1939SAndy Fiddaman 		pp = path_get(shp,"");
84*b30d1939SAndy Fiddaman 	else
85*b30d1939SAndy Fiddaman 		pp = pp->next;
86*b30d1939SAndy Fiddaman 	gp->gl_handle = (void*)pp;
87*b30d1939SAndy Fiddaman 	if(pp)
88*b30d1939SAndy Fiddaman 		return(pp->name);
89*b30d1939SAndy Fiddaman 	return(0);
90*b30d1939SAndy Fiddaman }
91*b30d1939SAndy Fiddaman #endif
92*b30d1939SAndy Fiddaman 
path_expand(Shell_t * shp,const char * pattern,struct argnod ** arghead)93*b30d1939SAndy Fiddaman int path_expand(Shell_t *shp,const char *pattern, struct argnod **arghead)
94*b30d1939SAndy Fiddaman {
95*b30d1939SAndy Fiddaman 	glob_t gdata;
96*b30d1939SAndy Fiddaman 	register struct argnod *ap;
97*b30d1939SAndy Fiddaman 	register glob_t *gp= &gdata;
98*b30d1939SAndy Fiddaman 	register int flags,extra=0;
99*b30d1939SAndy Fiddaman #if SHOPT_BASH
100*b30d1939SAndy Fiddaman 	register int off;
101*b30d1939SAndy Fiddaman 	register char *sp, *cp, *cp2;
102*b30d1939SAndy Fiddaman #endif
103*b30d1939SAndy Fiddaman 	sh_stats(STAT_GLOBS);
104*b30d1939SAndy Fiddaman 	memset(gp,0,sizeof(gdata));
105*b30d1939SAndy Fiddaman 	flags = GLOB_GROUP|GLOB_AUGMENTED|GLOB_NOCHECK|GLOB_NOSORT|GLOB_STACK|GLOB_LIST|GLOB_DISC;
106*b30d1939SAndy Fiddaman 	if(sh_isoption(SH_MARKDIRS))
107*b30d1939SAndy Fiddaman 		flags |= GLOB_MARK;
108*b30d1939SAndy Fiddaman 	if(sh_isoption(SH_GLOBSTARS))
109*b30d1939SAndy Fiddaman 		flags |= GLOB_STARSTAR;
110*b30d1939SAndy Fiddaman #if SHOPT_BASH
111*b30d1939SAndy Fiddaman #if 0
112*b30d1939SAndy Fiddaman 	if(sh_isoption(SH_BASH) && !sh_isoption(SH_EXTGLOB))
113*b30d1939SAndy Fiddaman 		flags &= ~GLOB_AUGMENTED;
114*b30d1939SAndy Fiddaman #endif
115*b30d1939SAndy Fiddaman 	if(sh_isoption(SH_NULLGLOB))
116*b30d1939SAndy Fiddaman 		flags &= ~GLOB_NOCHECK;
117*b30d1939SAndy Fiddaman 	if(sh_isoption(SH_NOCASEGLOB))
118*b30d1939SAndy Fiddaman 		flags |= GLOB_ICASE;
119*b30d1939SAndy Fiddaman #endif
120*b30d1939SAndy Fiddaman 	if(sh_isstate(SH_COMPLETE))
121*b30d1939SAndy Fiddaman 	{
122*b30d1939SAndy Fiddaman #if KSHELL
123*b30d1939SAndy Fiddaman 		extra += scantree(shp->alias_tree,pattern,arghead);
124*b30d1939SAndy Fiddaman 		extra += scantree(shp->fun_tree,pattern,arghead);
125*b30d1939SAndy Fiddaman #   if GLOB_VERSION >= 20010916L
126*b30d1939SAndy Fiddaman 		gp->gl_nextdir = nextdir;
127*b30d1939SAndy Fiddaman #   endif
128*b30d1939SAndy Fiddaman #endif /* KSHELL */
129*b30d1939SAndy Fiddaman 		flags |= GLOB_COMPLETE;
130*b30d1939SAndy Fiddaman 		flags &= ~GLOB_NOCHECK;
131*b30d1939SAndy Fiddaman 	}
132*b30d1939SAndy Fiddaman #if SHOPT_BASH
133*b30d1939SAndy Fiddaman 	if(off = staktell())
134*b30d1939SAndy Fiddaman 		sp = stakfreeze(0);
135*b30d1939SAndy Fiddaman 	if(sh_isoption(SH_BASH))
136*b30d1939SAndy Fiddaman 	{
137*b30d1939SAndy Fiddaman 		/*
138*b30d1939SAndy Fiddaman 		 * For bash, FIGNORE is a colon separated list of suffixes to
139*b30d1939SAndy Fiddaman 		 * ignore when doing filename/command completion.
140*b30d1939SAndy Fiddaman 		 * GLOBIGNORE is similar to ksh FIGNORE, but colon separated
141*b30d1939SAndy Fiddaman 		 * instead of being an augmented shell pattern.
142*b30d1939SAndy Fiddaman 		 * Generate shell patterns out of those here.
143*b30d1939SAndy Fiddaman 		 */
144*b30d1939SAndy Fiddaman 		if(sh_isstate(SH_FCOMPLETE))
145*b30d1939SAndy Fiddaman 			cp=nv_getval(sh_scoped(shp,FIGNORENOD));
146*b30d1939SAndy Fiddaman 		else
147*b30d1939SAndy Fiddaman 		{
148*b30d1939SAndy Fiddaman 			static Namval_t *GLOBIGNORENOD;
149*b30d1939SAndy Fiddaman 			if(!GLOBIGNORENOD)
150*b30d1939SAndy Fiddaman 				GLOBIGNORENOD = nv_open("GLOBIGNORE",shp->var_tree,0);
151*b30d1939SAndy Fiddaman 			cp=nv_getval(sh_scoped(shp,GLOBIGNORENOD));
152*b30d1939SAndy Fiddaman 		}
153*b30d1939SAndy Fiddaman 		if(cp)
154*b30d1939SAndy Fiddaman 		{
155*b30d1939SAndy Fiddaman 			flags |= GLOB_AUGMENTED;
156*b30d1939SAndy Fiddaman 			stakputs("@(");
157*b30d1939SAndy Fiddaman 			if(!sh_isstate(SH_FCOMPLETE))
158*b30d1939SAndy Fiddaman 			{
159*b30d1939SAndy Fiddaman 				stakputs(cp);
160*b30d1939SAndy Fiddaman 				for(cp=stakptr(off); *cp; cp++)
161*b30d1939SAndy Fiddaman 					if(*cp == ':')
162*b30d1939SAndy Fiddaman 						*cp='|';
163*b30d1939SAndy Fiddaman 			}
164*b30d1939SAndy Fiddaman 			else
165*b30d1939SAndy Fiddaman 			{
166*b30d1939SAndy Fiddaman 				cp2 = strtok(cp, ":");
167*b30d1939SAndy Fiddaman 				if(!cp2)
168*b30d1939SAndy Fiddaman 					cp2=cp;
169*b30d1939SAndy Fiddaman 				do
170*b30d1939SAndy Fiddaman 				{
171*b30d1939SAndy Fiddaman 					stakputc('*');
172*b30d1939SAndy Fiddaman 					stakputs(cp2);
173*b30d1939SAndy Fiddaman 					if(cp2 = strtok(NULL, ":"))
174*b30d1939SAndy Fiddaman 					{
175*b30d1939SAndy Fiddaman 						*(cp2-1)=':';
176*b30d1939SAndy Fiddaman 						stakputc('|');
177*b30d1939SAndy Fiddaman 					}
178*b30d1939SAndy Fiddaman 				} while(cp2);
179*b30d1939SAndy Fiddaman 			}
180*b30d1939SAndy Fiddaman 			stakputc(')');
181*b30d1939SAndy Fiddaman 			gp->gl_fignore = stakfreeze(1);
182*b30d1939SAndy Fiddaman 		}
183*b30d1939SAndy Fiddaman 		else if(!sh_isstate(SH_FCOMPLETE) && sh_isoption(SH_DOTGLOB))
184*b30d1939SAndy Fiddaman 			gp->gl_fignore = "";
185*b30d1939SAndy Fiddaman 	}
186*b30d1939SAndy Fiddaman 	else
187*b30d1939SAndy Fiddaman #endif
188*b30d1939SAndy Fiddaman 	gp->gl_fignore = nv_getval(sh_scoped(shp,FIGNORENOD));
189*b30d1939SAndy Fiddaman 	if(suflen)
190*b30d1939SAndy Fiddaman 		gp->gl_suffix = sufstr;
191*b30d1939SAndy Fiddaman 	gp->gl_intr = &shp->trapnote;
192*b30d1939SAndy Fiddaman 	suflen = 0;
193*b30d1939SAndy Fiddaman 	if(memcmp(pattern,"~(N",3)==0)
194*b30d1939SAndy Fiddaman 		flags &= ~GLOB_NOCHECK;
195*b30d1939SAndy Fiddaman 	glob(pattern, flags, 0, gp);
196*b30d1939SAndy Fiddaman #if SHOPT_BASH
197*b30d1939SAndy Fiddaman 	if(off)
198*b30d1939SAndy Fiddaman 		stakset(sp,off);
199*b30d1939SAndy Fiddaman 	else
200*b30d1939SAndy Fiddaman 		stakseek(0);
201*b30d1939SAndy Fiddaman #endif
202*b30d1939SAndy Fiddaman 	sh_sigcheck(shp);
203*b30d1939SAndy Fiddaman 	for(ap= (struct argnod*)gp->gl_list; ap; ap = ap->argnxt.ap)
204*b30d1939SAndy Fiddaman 	{
205*b30d1939SAndy Fiddaman 		ap->argchn.ap = ap->argnxt.ap;
206*b30d1939SAndy Fiddaman 		if(!ap->argnxt.ap)
207*b30d1939SAndy Fiddaman 			ap->argchn.ap = *arghead;
208*b30d1939SAndy Fiddaman 	}
209*b30d1939SAndy Fiddaman 	if(gp->gl_list)
210*b30d1939SAndy Fiddaman 		*arghead = (struct argnod*)gp->gl_list;
211*b30d1939SAndy Fiddaman 	return(gp->gl_pathc+extra);
212*b30d1939SAndy Fiddaman }
213*b30d1939SAndy Fiddaman 
214*b30d1939SAndy Fiddaman #if KSHELL
215*b30d1939SAndy Fiddaman 
216*b30d1939SAndy Fiddaman /*
217*b30d1939SAndy Fiddaman  * scan tree and add each name that matches the given pattern
218*b30d1939SAndy Fiddaman  */
scantree(Dt_t * tree,const char * pattern,struct argnod ** arghead)219*b30d1939SAndy Fiddaman static int scantree(Dt_t *tree, const char *pattern, struct argnod **arghead)
220*b30d1939SAndy Fiddaman {
221*b30d1939SAndy Fiddaman 	register Namval_t *np;
222*b30d1939SAndy Fiddaman 	register struct argnod *ap;
223*b30d1939SAndy Fiddaman 	register int nmatch=0;
224*b30d1939SAndy Fiddaman 	register char *cp;
225*b30d1939SAndy Fiddaman 	np = (Namval_t*)dtfirst(tree);
226*b30d1939SAndy Fiddaman 	for(;np && !nv_isnull(np);(np = (Namval_t*)dtnext(tree,np)))
227*b30d1939SAndy Fiddaman 	{
228*b30d1939SAndy Fiddaman 		if(strmatch(cp=nv_name(np),pattern))
229*b30d1939SAndy Fiddaman 		{
230*b30d1939SAndy Fiddaman 			ap = (struct argnod*)stakseek(ARGVAL);
231*b30d1939SAndy Fiddaman 			stakputs(cp);
232*b30d1939SAndy Fiddaman 			ap = (struct argnod*)stakfreeze(1);
233*b30d1939SAndy Fiddaman 			ap->argbegin = NIL(char*);
234*b30d1939SAndy Fiddaman 			ap->argchn.ap = *arghead;
235*b30d1939SAndy Fiddaman 			ap->argflag = ARG_RAW|ARG_MAKE;
236*b30d1939SAndy Fiddaman 			*arghead = ap;
237*b30d1939SAndy Fiddaman 			nmatch++;
238*b30d1939SAndy Fiddaman 		}
239*b30d1939SAndy Fiddaman 	}
240*b30d1939SAndy Fiddaman 	return(nmatch);
241*b30d1939SAndy Fiddaman }
242*b30d1939SAndy Fiddaman 
243*b30d1939SAndy Fiddaman /*
244*b30d1939SAndy Fiddaman  * file name completion
245*b30d1939SAndy Fiddaman  * generate the list of files found by adding an suffix to end of name
246*b30d1939SAndy Fiddaman  * The number of matches is returned
247*b30d1939SAndy Fiddaman  */
248*b30d1939SAndy Fiddaman 
path_complete(Shell_t * shp,const char * name,register const char * suffix,struct argnod ** arghead)249*b30d1939SAndy Fiddaman int path_complete(Shell_t *shp,const char *name,register const char *suffix, struct argnod **arghead)
250*b30d1939SAndy Fiddaman {
251*b30d1939SAndy Fiddaman 	sufstr = suffix;
252*b30d1939SAndy Fiddaman 	suflen = strlen(suffix);
253*b30d1939SAndy Fiddaman 	return(path_expand(shp,name,arghead));
254*b30d1939SAndy Fiddaman }
255*b30d1939SAndy Fiddaman 
256*b30d1939SAndy Fiddaman #endif
257*b30d1939SAndy Fiddaman 
258*b30d1939SAndy Fiddaman #if SHOPT_BRACEPAT
259*b30d1939SAndy Fiddaman 
checkfmt(Sfio_t * sp,void * vp,Sffmt_t * fp)260*b30d1939SAndy Fiddaman static int checkfmt(Sfio_t* sp, void* vp, Sffmt_t* fp)
261*b30d1939SAndy Fiddaman {
262*b30d1939SAndy Fiddaman 	return -1;
263*b30d1939SAndy Fiddaman }
264*b30d1939SAndy Fiddaman 
path_generate(Shell_t * shp,struct argnod * todo,struct argnod ** arghead)265*b30d1939SAndy Fiddaman int path_generate(Shell_t *shp,struct argnod *todo, struct argnod **arghead)
266*b30d1939SAndy Fiddaman /*@
267*b30d1939SAndy Fiddaman 	assume todo!=0;
268*b30d1939SAndy Fiddaman 	return count satisfying count>=1;
269*b30d1939SAndy Fiddaman @*/
270*b30d1939SAndy Fiddaman {
271*b30d1939SAndy Fiddaman 	register char *cp;
272*b30d1939SAndy Fiddaman 	register int brace;
273*b30d1939SAndy Fiddaman 	register struct argnod *ap;
274*b30d1939SAndy Fiddaman 	struct argnod *top = 0;
275*b30d1939SAndy Fiddaman 	struct argnod *apin;
276*b30d1939SAndy Fiddaman 	char *pat, *rescan;
277*b30d1939SAndy Fiddaman 	char *format;
278*b30d1939SAndy Fiddaman 	char comma, range=0;
279*b30d1939SAndy Fiddaman 	int first, last, incr, count = 0;
280*b30d1939SAndy Fiddaman 	char tmp[32], end[1];
281*b30d1939SAndy Fiddaman 	todo->argchn.ap = 0;
282*b30d1939SAndy Fiddaman again:
283*b30d1939SAndy Fiddaman 	apin = ap = todo;
284*b30d1939SAndy Fiddaman 	todo = ap->argchn.ap;
285*b30d1939SAndy Fiddaman 	cp = ap->argval;
286*b30d1939SAndy Fiddaman 	range = comma = brace = 0;
287*b30d1939SAndy Fiddaman 	/* first search for {...,...} */
288*b30d1939SAndy Fiddaman 	while(1) switch(*cp++)
289*b30d1939SAndy Fiddaman 	{
290*b30d1939SAndy Fiddaman 		case '{':
291*b30d1939SAndy Fiddaman 			if(brace++==0)
292*b30d1939SAndy Fiddaman 				pat = cp;
293*b30d1939SAndy Fiddaman 			break;
294*b30d1939SAndy Fiddaman 		case '}':
295*b30d1939SAndy Fiddaman 			if(--brace>0)
296*b30d1939SAndy Fiddaman 				break;
297*b30d1939SAndy Fiddaman 			if(brace==0 && comma && *cp!='(')
298*b30d1939SAndy Fiddaman 				goto endloop1;
299*b30d1939SAndy Fiddaman 			comma = brace = 0;
300*b30d1939SAndy Fiddaman 			break;
301*b30d1939SAndy Fiddaman 		case '.':
302*b30d1939SAndy Fiddaman 			if(brace==1 && *cp=='.')
303*b30d1939SAndy Fiddaman 			{
304*b30d1939SAndy Fiddaman 				char *endc;
305*b30d1939SAndy Fiddaman 				incr = 1;
306*b30d1939SAndy Fiddaman 				if(isdigit(*pat) || *pat=='+' || *pat=='-')
307*b30d1939SAndy Fiddaman 				{
308*b30d1939SAndy Fiddaman 					first = strtol(pat,&endc,0);
309*b30d1939SAndy Fiddaman 					if(endc==(cp-1))
310*b30d1939SAndy Fiddaman 					{
311*b30d1939SAndy Fiddaman 						last = strtol(cp+1,&endc,0);
312*b30d1939SAndy Fiddaman 						if(*endc=='.' && endc[1]=='.')
313*b30d1939SAndy Fiddaman 							incr = strtol(endc+2,&endc,0);
314*b30d1939SAndy Fiddaman 						else if(last<first)
315*b30d1939SAndy Fiddaman 							incr = -1;
316*b30d1939SAndy Fiddaman 						if(incr)
317*b30d1939SAndy Fiddaman 						{
318*b30d1939SAndy Fiddaman 							if(*endc=='%')
319*b30d1939SAndy Fiddaman 							{
320*b30d1939SAndy Fiddaman 								Sffmt_t	fmt;
321*b30d1939SAndy Fiddaman 								memset(&fmt, 0, sizeof(fmt));
322*b30d1939SAndy Fiddaman 								fmt.version = SFIO_VERSION;
323*b30d1939SAndy Fiddaman 								fmt.form = endc;
324*b30d1939SAndy Fiddaman 								fmt.extf = checkfmt;
325*b30d1939SAndy Fiddaman 								sfprintf(sfstdout, "%!", &fmt);
326*b30d1939SAndy Fiddaman 								if(!(fmt.flags&(SFFMT_LLONG|SFFMT_LDOUBLE)))
327*b30d1939SAndy Fiddaman 									switch (fmt.fmt)
328*b30d1939SAndy Fiddaman 									{
329*b30d1939SAndy Fiddaman 									case 'c':
330*b30d1939SAndy Fiddaman 									case 'd':
331*b30d1939SAndy Fiddaman 									case 'i':
332*b30d1939SAndy Fiddaman 									case 'o':
333*b30d1939SAndy Fiddaman 									case 'u':
334*b30d1939SAndy Fiddaman 									case 'x':
335*b30d1939SAndy Fiddaman 									case 'X':
336*b30d1939SAndy Fiddaman 										format = endc;
337*b30d1939SAndy Fiddaman 										endc = fmt.form;
338*b30d1939SAndy Fiddaman 										break;
339*b30d1939SAndy Fiddaman 									}
340*b30d1939SAndy Fiddaman 							}
341*b30d1939SAndy Fiddaman 							else
342*b30d1939SAndy Fiddaman 								format = "%d";
343*b30d1939SAndy Fiddaman 							if(*endc=='}')
344*b30d1939SAndy Fiddaman 							{
345*b30d1939SAndy Fiddaman 								cp = endc+1;
346*b30d1939SAndy Fiddaman 								range = 2;
347*b30d1939SAndy Fiddaman 								goto endloop1;
348*b30d1939SAndy Fiddaman 							}
349*b30d1939SAndy Fiddaman 						}
350*b30d1939SAndy Fiddaman 					}
351*b30d1939SAndy Fiddaman 				}
352*b30d1939SAndy Fiddaman 				else if((cp[2]=='}' || cp[2]=='.' && cp[3]=='.') && ((*pat>='a'  && *pat<='z' && cp[1]>='a' && cp[1]<='z') || (*pat>='A'  && *pat<='Z' && cp[1]>='A' && cp[1]<='Z')))
353*b30d1939SAndy Fiddaman 				{
354*b30d1939SAndy Fiddaman 					first = *pat;
355*b30d1939SAndy Fiddaman 					last = cp[1];
356*b30d1939SAndy Fiddaman 					cp += 2;
357*b30d1939SAndy Fiddaman 					if(*cp=='.')
358*b30d1939SAndy Fiddaman 					{
359*b30d1939SAndy Fiddaman 						incr = strtol(cp+2,&endc,0);
360*b30d1939SAndy Fiddaman 						cp = endc;
361*b30d1939SAndy Fiddaman 					}
362*b30d1939SAndy Fiddaman 					else if(first>last)
363*b30d1939SAndy Fiddaman 						incr = -1;
364*b30d1939SAndy Fiddaman 					if(incr && *cp=='}')
365*b30d1939SAndy Fiddaman 					{
366*b30d1939SAndy Fiddaman 						cp++;
367*b30d1939SAndy Fiddaman 						range = 1;
368*b30d1939SAndy Fiddaman 						goto endloop1;
369*b30d1939SAndy Fiddaman 					}
370*b30d1939SAndy Fiddaman 				}
371*b30d1939SAndy Fiddaman 				cp++;
372*b30d1939SAndy Fiddaman 			}
373*b30d1939SAndy Fiddaman 			break;
374*b30d1939SAndy Fiddaman 		case ',':
375*b30d1939SAndy Fiddaman 			if(brace==1)
376*b30d1939SAndy Fiddaman 				comma = 1;
377*b30d1939SAndy Fiddaman 			break;
378*b30d1939SAndy Fiddaman 		case '\\':
379*b30d1939SAndy Fiddaman 			cp++;
380*b30d1939SAndy Fiddaman 			break;
381*b30d1939SAndy Fiddaman 		case 0:
382*b30d1939SAndy Fiddaman 			/* insert on stack */
383*b30d1939SAndy Fiddaman 			ap->argchn.ap = top;
384*b30d1939SAndy Fiddaman 			top = ap;
385*b30d1939SAndy Fiddaman 			if(todo)
386*b30d1939SAndy Fiddaman 				goto again;
387*b30d1939SAndy Fiddaman 			for(; ap; ap=apin)
388*b30d1939SAndy Fiddaman 			{
389*b30d1939SAndy Fiddaman 				apin = ap->argchn.ap;
390*b30d1939SAndy Fiddaman 				if(!sh_isoption(SH_NOGLOB))
391*b30d1939SAndy Fiddaman 					brace=path_expand(shp,ap->argval,arghead);
392*b30d1939SAndy Fiddaman 				else
393*b30d1939SAndy Fiddaman 				{
394*b30d1939SAndy Fiddaman 					ap->argchn.ap = *arghead;
395*b30d1939SAndy Fiddaman 					*arghead = ap;
396*b30d1939SAndy Fiddaman 					brace=1;
397*b30d1939SAndy Fiddaman 				}
398*b30d1939SAndy Fiddaman 				if(brace)
399*b30d1939SAndy Fiddaman 				{
400*b30d1939SAndy Fiddaman 					count += brace;
401*b30d1939SAndy Fiddaman 					(*arghead)->argflag |= ARG_MAKE;
402*b30d1939SAndy Fiddaman 				}
403*b30d1939SAndy Fiddaman 			}
404*b30d1939SAndy Fiddaman 			return(count);
405*b30d1939SAndy Fiddaman 	}
406*b30d1939SAndy Fiddaman endloop1:
407*b30d1939SAndy Fiddaman 	rescan = cp;
408*b30d1939SAndy Fiddaman 	cp = pat-1;
409*b30d1939SAndy Fiddaman 	*cp = 0;
410*b30d1939SAndy Fiddaman 	while(1)
411*b30d1939SAndy Fiddaman 	{
412*b30d1939SAndy Fiddaman 		brace = 0;
413*b30d1939SAndy Fiddaman 		if(range)
414*b30d1939SAndy Fiddaman 		{
415*b30d1939SAndy Fiddaman 			if(range==1)
416*b30d1939SAndy Fiddaman 			{
417*b30d1939SAndy Fiddaman 				pat[0] = first;
418*b30d1939SAndy Fiddaman 				cp = &pat[1];
419*b30d1939SAndy Fiddaman 			}
420*b30d1939SAndy Fiddaman 			else
421*b30d1939SAndy Fiddaman 			{
422*b30d1939SAndy Fiddaman 				*(rescan - 1) = 0;
423*b30d1939SAndy Fiddaman 				sfsprintf(pat=tmp,sizeof(tmp),format,first);
424*b30d1939SAndy Fiddaman 				*(rescan - 1) = '}';
425*b30d1939SAndy Fiddaman 				*(cp = end) = 0;
426*b30d1939SAndy Fiddaman 			}
427*b30d1939SAndy Fiddaman 			if(incr*(first+incr) > last*incr)
428*b30d1939SAndy Fiddaman 				*cp = '}';
429*b30d1939SAndy Fiddaman 			else
430*b30d1939SAndy Fiddaman 				first += incr;
431*b30d1939SAndy Fiddaman 		}
432*b30d1939SAndy Fiddaman 		/* generate each pattern and put on the todo list */
433*b30d1939SAndy Fiddaman 		else while(1) switch(*++cp)
434*b30d1939SAndy Fiddaman 		{
435*b30d1939SAndy Fiddaman 			case '\\':
436*b30d1939SAndy Fiddaman 				cp++;
437*b30d1939SAndy Fiddaman 				break;
438*b30d1939SAndy Fiddaman 			case '{':
439*b30d1939SAndy Fiddaman 				brace++;
440*b30d1939SAndy Fiddaman 				break;
441*b30d1939SAndy Fiddaman 			case ',':
442*b30d1939SAndy Fiddaman 				if(brace==0)
443*b30d1939SAndy Fiddaman 					goto endloop2;
444*b30d1939SAndy Fiddaman 				break;
445*b30d1939SAndy Fiddaman 			case '}':
446*b30d1939SAndy Fiddaman 				if(--brace<0)
447*b30d1939SAndy Fiddaman 					goto endloop2;
448*b30d1939SAndy Fiddaman 		}
449*b30d1939SAndy Fiddaman 	endloop2:
450*b30d1939SAndy Fiddaman 		brace = *cp;
451*b30d1939SAndy Fiddaman 		*cp = 0;
452*b30d1939SAndy Fiddaman 		sh_sigcheck(shp);
453*b30d1939SAndy Fiddaman 		ap = (struct argnod*)stakseek(ARGVAL);
454*b30d1939SAndy Fiddaman 		ap->argflag = ARG_RAW;
455*b30d1939SAndy Fiddaman 		ap->argchn.ap = todo;
456*b30d1939SAndy Fiddaman 		stakputs(apin->argval);
457*b30d1939SAndy Fiddaman 		stakputs(pat);
458*b30d1939SAndy Fiddaman 		stakputs(rescan);
459*b30d1939SAndy Fiddaman 		todo = ap = (struct argnod*)stakfreeze(1);
460*b30d1939SAndy Fiddaman 		if(brace == '}')
461*b30d1939SAndy Fiddaman 			break;
462*b30d1939SAndy Fiddaman 		if(!range)
463*b30d1939SAndy Fiddaman 			pat = cp+1;
464*b30d1939SAndy Fiddaman 	}
465*b30d1939SAndy Fiddaman 	goto again;
466*b30d1939SAndy Fiddaman }
467*b30d1939SAndy Fiddaman 
468*b30d1939SAndy Fiddaman #endif /* SHOPT_BRACEPAT */
469