1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman *                                                                      *
3*b30d1939SAndy Fiddaman *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2012 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 *                 Glenn Fowler <gsf@research.att.com>                  *
18*b30d1939SAndy Fiddaman *                  David Korn <dgk@research.att.com>                   *
19*b30d1939SAndy Fiddaman *                   Phong Vo <kpv@research.att.com>                    *
20*b30d1939SAndy Fiddaman *                                                                      *
21*b30d1939SAndy Fiddaman ***********************************************************************/
22*b30d1939SAndy Fiddaman #pragma prototyped
23*b30d1939SAndy Fiddaman 
24*b30d1939SAndy Fiddaman /*
25*b30d1939SAndy Fiddaman  * D. G. Korn
26*b30d1939SAndy Fiddaman  * G. S. Fowler
27*b30d1939SAndy Fiddaman  * AT&T Research
28*b30d1939SAndy Fiddaman  *
29*b30d1939SAndy Fiddaman  * match shell file patterns -- derived from Bourne and Korn shell gmatch()
30*b30d1939SAndy Fiddaman  *
31*b30d1939SAndy Fiddaman  *	sh pattern	egrep RE	description
32*b30d1939SAndy Fiddaman  *	----------	--------	-----------
33*b30d1939SAndy Fiddaman  *	*		.*		0 or more chars
34*b30d1939SAndy Fiddaman  *	?		.		any single char
35*b30d1939SAndy Fiddaman  *	[.]		[.]		char class
36*b30d1939SAndy Fiddaman  *	[!.]		[^.]		negated char class
37*b30d1939SAndy Fiddaman  *	[[:.:]]		[[:.:]]		ctype class
38*b30d1939SAndy Fiddaman  *	[[=.=]]		[[=.=]]		equivalence class
39*b30d1939SAndy Fiddaman  *	[[...]]		[[...]]		collation element
40*b30d1939SAndy Fiddaman  *	*(.)		(.)*		0 or more of
41*b30d1939SAndy Fiddaman  *	+(.)		(.)+		1 or more of
42*b30d1939SAndy Fiddaman  *	?(.)		(.)?		0 or 1 of
43*b30d1939SAndy Fiddaman  *	(.)		(.)		1 of
44*b30d1939SAndy Fiddaman  *	@(.)		(.)		1 of
45*b30d1939SAndy Fiddaman  *	a|b		a|b		a or b
46*b30d1939SAndy Fiddaman  *	\#				() subgroup back reference [1-9]
47*b30d1939SAndy Fiddaman  *	a&b				a and b
48*b30d1939SAndy Fiddaman  *	!(.)				none of
49*b30d1939SAndy Fiddaman  *
50*b30d1939SAndy Fiddaman  * \ used to escape metacharacters
51*b30d1939SAndy Fiddaman  *
52*b30d1939SAndy Fiddaman  *	*, ?, (, |, &, ), [, \ must be \'d outside of [...]
53*b30d1939SAndy Fiddaman  *	only ] must be \'d inside [...]
54*b30d1939SAndy Fiddaman  *
55*b30d1939SAndy Fiddaman  * BUG: unbalanced ) terminates top level pattern
56*b30d1939SAndy Fiddaman  */
57*b30d1939SAndy Fiddaman 
58*b30d1939SAndy Fiddaman #include <ast.h>
59*b30d1939SAndy Fiddaman #include <ctype.h>
60*b30d1939SAndy Fiddaman #include <hashkey.h>
61*b30d1939SAndy Fiddaman 
62*b30d1939SAndy Fiddaman #ifndef	isblank
63*b30d1939SAndy Fiddaman #define	isblank(x)	((x)==' '||(x)=='\t')
64*b30d1939SAndy Fiddaman #endif
65*b30d1939SAndy Fiddaman 
66*b30d1939SAndy Fiddaman #ifndef isgraph
67*b30d1939SAndy Fiddaman #define	isgraph(x)	(isprint(x)&&!isblank(x))
68*b30d1939SAndy Fiddaman #endif
69*b30d1939SAndy Fiddaman 
70*b30d1939SAndy Fiddaman #define MAXGROUP	10
71*b30d1939SAndy Fiddaman 
72*b30d1939SAndy Fiddaman typedef struct
73*b30d1939SAndy Fiddaman {
74*b30d1939SAndy Fiddaman 	char*		beg[MAXGROUP];
75*b30d1939SAndy Fiddaman 	char*		end[MAXGROUP];
76*b30d1939SAndy Fiddaman 	char*		next_s;
77*b30d1939SAndy Fiddaman 	short		groups;
78*b30d1939SAndy Fiddaman } Group_t;
79*b30d1939SAndy Fiddaman 
80*b30d1939SAndy Fiddaman typedef struct
81*b30d1939SAndy Fiddaman {
82*b30d1939SAndy Fiddaman 	Group_t		current;
83*b30d1939SAndy Fiddaman 	Group_t		best;
84*b30d1939SAndy Fiddaman 	char*		last_s;
85*b30d1939SAndy Fiddaman 	char*		next_p;
86*b30d1939SAndy Fiddaman } Match_t;
87*b30d1939SAndy Fiddaman 
88*b30d1939SAndy Fiddaman #define mbgetchar(p)	(*p++)
89*b30d1939SAndy Fiddaman 
90*b30d1939SAndy Fiddaman #ifndef isxdigit
91*b30d1939SAndy Fiddaman #define isxdigit(c)	((c)>='0'&&(c)<='9'||(c)>='a'&&(c)<='f'||(c)>='A'&&(c)<='F')
92*b30d1939SAndy Fiddaman #endif
93*b30d1939SAndy Fiddaman 
94*b30d1939SAndy Fiddaman #define getsource(s,e)	(((s)>=(e))?0:mbgetchar(s))
95*b30d1939SAndy Fiddaman 
96*b30d1939SAndy Fiddaman #define COLL_MAX	3
97*b30d1939SAndy Fiddaman 
98*b30d1939SAndy Fiddaman /*
99*b30d1939SAndy Fiddaman  * gobble chars up to <sub> or ) keeping track of (...) and [...]
100*b30d1939SAndy Fiddaman  * sub must be one of { '|', '&', 0 }
101*b30d1939SAndy Fiddaman  * 0 returned if s runs out
102*b30d1939SAndy Fiddaman  */
103*b30d1939SAndy Fiddaman 
104*b30d1939SAndy Fiddaman static char*
gobble(Match_t * mp,register char * s,register int sub,int * g,int clear)105*b30d1939SAndy Fiddaman gobble(Match_t* mp, register char* s, register int sub, int* g, int clear)
106*b30d1939SAndy Fiddaman {
107*b30d1939SAndy Fiddaman 	register int	p = 0;
108*b30d1939SAndy Fiddaman 	register char*	b = 0;
109*b30d1939SAndy Fiddaman 	int		c = 0;
110*b30d1939SAndy Fiddaman 	int		n;
111*b30d1939SAndy Fiddaman 
112*b30d1939SAndy Fiddaman 	for (;;)
113*b30d1939SAndy Fiddaman 		switch (mbgetchar(s))
114*b30d1939SAndy Fiddaman 		{
115*b30d1939SAndy Fiddaman 		case '\\':
116*b30d1939SAndy Fiddaman 			if (mbgetchar(s))
117*b30d1939SAndy Fiddaman 				break;
118*b30d1939SAndy Fiddaman 			/*FALLTHROUGH*/
119*b30d1939SAndy Fiddaman 		case 0:
120*b30d1939SAndy Fiddaman 			return 0;
121*b30d1939SAndy Fiddaman 		case '[':
122*b30d1939SAndy Fiddaman 			if (!b)
123*b30d1939SAndy Fiddaman 			{
124*b30d1939SAndy Fiddaman 				if (*s == '!' || *s == '^')
125*b30d1939SAndy Fiddaman 					mbgetchar(s);
126*b30d1939SAndy Fiddaman 				b = s;
127*b30d1939SAndy Fiddaman 			}
128*b30d1939SAndy Fiddaman 			else if (*s == '.' || *s == '=' || *s == ':')
129*b30d1939SAndy Fiddaman 				c = *s;
130*b30d1939SAndy Fiddaman 			break;
131*b30d1939SAndy Fiddaman 		case ']':
132*b30d1939SAndy Fiddaman 			if (b)
133*b30d1939SAndy Fiddaman 			{
134*b30d1939SAndy Fiddaman 				if (*(s - 2) == c)
135*b30d1939SAndy Fiddaman 					c = 0;
136*b30d1939SAndy Fiddaman 				else if (b != (s - 1))
137*b30d1939SAndy Fiddaman 					b = 0;
138*b30d1939SAndy Fiddaman 			}
139*b30d1939SAndy Fiddaman 			break;
140*b30d1939SAndy Fiddaman 		case '(':
141*b30d1939SAndy Fiddaman 			if (!b)
142*b30d1939SAndy Fiddaman 			{
143*b30d1939SAndy Fiddaman 				p++;
144*b30d1939SAndy Fiddaman 				n = (*g)++;
145*b30d1939SAndy Fiddaman 				if (clear)
146*b30d1939SAndy Fiddaman 				{
147*b30d1939SAndy Fiddaman 					if (!sub)
148*b30d1939SAndy Fiddaman 						n++;
149*b30d1939SAndy Fiddaman 					if (n < MAXGROUP)
150*b30d1939SAndy Fiddaman 						mp->current.beg[n] = mp->current.end[n] = 0;
151*b30d1939SAndy Fiddaman 				}
152*b30d1939SAndy Fiddaman 			}
153*b30d1939SAndy Fiddaman 			break;
154*b30d1939SAndy Fiddaman 		case ')':
155*b30d1939SAndy Fiddaman 			if (!b && p-- <= 0)
156*b30d1939SAndy Fiddaman 				return sub ? 0 : s;
157*b30d1939SAndy Fiddaman 			break;
158*b30d1939SAndy Fiddaman 		case '|':
159*b30d1939SAndy Fiddaman 			if (!b && !p && sub == '|')
160*b30d1939SAndy Fiddaman 				return s;
161*b30d1939SAndy Fiddaman 			break;
162*b30d1939SAndy Fiddaman 		}
163*b30d1939SAndy Fiddaman }
164*b30d1939SAndy Fiddaman 
165*b30d1939SAndy Fiddaman static int	grpmatch(Match_t*, int, char*, register char*, char*, int);
166*b30d1939SAndy Fiddaman 
167*b30d1939SAndy Fiddaman /*
168*b30d1939SAndy Fiddaman  * match a single pattern
169*b30d1939SAndy Fiddaman  * e is the end (0) of the substring in s
170*b30d1939SAndy Fiddaman  * r marks the start of a repeated subgroup pattern
171*b30d1939SAndy Fiddaman  */
172*b30d1939SAndy Fiddaman 
173*b30d1939SAndy Fiddaman static int
onematch(Match_t * mp,int g,char * s,char * p,char * e,char * r,int flags)174*b30d1939SAndy Fiddaman onematch(Match_t* mp, int g, char* s, char* p, char* e, char* r, int flags)
175*b30d1939SAndy Fiddaman {
176*b30d1939SAndy Fiddaman 	register int 	pc;
177*b30d1939SAndy Fiddaman 	register int 	sc;
178*b30d1939SAndy Fiddaman 	register int	n;
179*b30d1939SAndy Fiddaman 	register int	icase;
180*b30d1939SAndy Fiddaman 	char*		olds;
181*b30d1939SAndy Fiddaman 	char*		oldp;
182*b30d1939SAndy Fiddaman 
183*b30d1939SAndy Fiddaman 	icase = flags & STR_ICASE;
184*b30d1939SAndy Fiddaman 	do
185*b30d1939SAndy Fiddaman 	{
186*b30d1939SAndy Fiddaman 		olds = s;
187*b30d1939SAndy Fiddaman 		sc = getsource(s, e);
188*b30d1939SAndy Fiddaman 		if (icase && isupper(sc))
189*b30d1939SAndy Fiddaman 			sc = tolower(sc);
190*b30d1939SAndy Fiddaman 		oldp = p;
191*b30d1939SAndy Fiddaman 		switch (pc = mbgetchar(p))
192*b30d1939SAndy Fiddaman 		{
193*b30d1939SAndy Fiddaman 		case '(':
194*b30d1939SAndy Fiddaman 		case '*':
195*b30d1939SAndy Fiddaman 		case '?':
196*b30d1939SAndy Fiddaman 		case '+':
197*b30d1939SAndy Fiddaman 		case '@':
198*b30d1939SAndy Fiddaman 		case '!':
199*b30d1939SAndy Fiddaman 			if (pc == '(' || *p == '(')
200*b30d1939SAndy Fiddaman 			{
201*b30d1939SAndy Fiddaman 				char*	subp;
202*b30d1939SAndy Fiddaman 				int	oldg;
203*b30d1939SAndy Fiddaman 
204*b30d1939SAndy Fiddaman 				s = olds;
205*b30d1939SAndy Fiddaman 				subp = p + (pc != '(');
206*b30d1939SAndy Fiddaman 				oldg = g;
207*b30d1939SAndy Fiddaman 				n = ++g;
208*b30d1939SAndy Fiddaman 				if (g < MAXGROUP && (!r || g > mp->current.groups))
209*b30d1939SAndy Fiddaman 					mp->current.beg[g] = mp->current.end[g] = 0;
210*b30d1939SAndy Fiddaman 				if (!(p = gobble(mp, subp, 0, &g, !r)))
211*b30d1939SAndy Fiddaman 					return 0;
212*b30d1939SAndy Fiddaman 				if (pc == '*' || pc == '?' || pc == '+' && oldp == r)
213*b30d1939SAndy Fiddaman 				{
214*b30d1939SAndy Fiddaman 					if (onematch(mp, g, s, p, e, NiL, flags))
215*b30d1939SAndy Fiddaman 						return 1;
216*b30d1939SAndy Fiddaman 					if (!sc || !getsource(s, e))
217*b30d1939SAndy Fiddaman 					{
218*b30d1939SAndy Fiddaman 						mp->current.groups = oldg;
219*b30d1939SAndy Fiddaman 						return 0;
220*b30d1939SAndy Fiddaman 					}
221*b30d1939SAndy Fiddaman 				}
222*b30d1939SAndy Fiddaman 				if (pc == '*' || pc == '+')
223*b30d1939SAndy Fiddaman 				{
224*b30d1939SAndy Fiddaman 					p = oldp;
225*b30d1939SAndy Fiddaman 					sc = n - 1;
226*b30d1939SAndy Fiddaman 				}
227*b30d1939SAndy Fiddaman 				else
228*b30d1939SAndy Fiddaman 					sc = g;
229*b30d1939SAndy Fiddaman 				pc = (pc != '!');
230*b30d1939SAndy Fiddaman 				do
231*b30d1939SAndy Fiddaman 				{
232*b30d1939SAndy Fiddaman 					if (grpmatch(mp, n, olds, subp, s, flags) == pc)
233*b30d1939SAndy Fiddaman 					{
234*b30d1939SAndy Fiddaman 						if (n < MAXGROUP)
235*b30d1939SAndy Fiddaman 						{
236*b30d1939SAndy Fiddaman 							if (!mp->current.beg[n] || mp->current.beg[n] > olds)
237*b30d1939SAndy Fiddaman 								mp->current.beg[n] = olds;
238*b30d1939SAndy Fiddaman 							if (s > mp->current.end[n])
239*b30d1939SAndy Fiddaman 								mp->current.end[n] = s;
240*b30d1939SAndy Fiddaman 						}
241*b30d1939SAndy Fiddaman 						if (onematch(mp, sc, s, p, e, oldp, flags))
242*b30d1939SAndy Fiddaman 						{
243*b30d1939SAndy Fiddaman 							if (p == oldp && n < MAXGROUP)
244*b30d1939SAndy Fiddaman 							{
245*b30d1939SAndy Fiddaman 								if (!mp->current.beg[n] || mp->current.beg[n] > olds)
246*b30d1939SAndy Fiddaman 									mp->current.beg[n] = olds;
247*b30d1939SAndy Fiddaman 								if (s > mp->current.end[n])
248*b30d1939SAndy Fiddaman 									mp->current.end[n] = s;
249*b30d1939SAndy Fiddaman 							}
250*b30d1939SAndy Fiddaman 							return 1;
251*b30d1939SAndy Fiddaman 						}
252*b30d1939SAndy Fiddaman 					}
253*b30d1939SAndy Fiddaman 				} while (s < e && mbgetchar(s));
254*b30d1939SAndy Fiddaman 				mp->current.groups = oldg;
255*b30d1939SAndy Fiddaman 				return 0;
256*b30d1939SAndy Fiddaman 			}
257*b30d1939SAndy Fiddaman 			else if (pc == '*')
258*b30d1939SAndy Fiddaman 			{
259*b30d1939SAndy Fiddaman 				/*
260*b30d1939SAndy Fiddaman 				 * several stars are the same as one
261*b30d1939SAndy Fiddaman 				 */
262*b30d1939SAndy Fiddaman 
263*b30d1939SAndy Fiddaman 				while (*p == '*' && *(p + 1) != '(')
264*b30d1939SAndy Fiddaman 					p++;
265*b30d1939SAndy Fiddaman 				oldp = p;
266*b30d1939SAndy Fiddaman 				switch (pc = mbgetchar(p))
267*b30d1939SAndy Fiddaman 				{
268*b30d1939SAndy Fiddaman 				case '@':
269*b30d1939SAndy Fiddaman 				case '!':
270*b30d1939SAndy Fiddaman 				case '+':
271*b30d1939SAndy Fiddaman 					n = *p == '(';
272*b30d1939SAndy Fiddaman 					break;
273*b30d1939SAndy Fiddaman 				case '(':
274*b30d1939SAndy Fiddaman 				case '[':
275*b30d1939SAndy Fiddaman 				case '?':
276*b30d1939SAndy Fiddaman 				case '*':
277*b30d1939SAndy Fiddaman 					n = 1;
278*b30d1939SAndy Fiddaman 					break;
279*b30d1939SAndy Fiddaman 				case 0:
280*b30d1939SAndy Fiddaman 				case '|':
281*b30d1939SAndy Fiddaman 				case '&':
282*b30d1939SAndy Fiddaman 				case ')':
283*b30d1939SAndy Fiddaman 					mp->current.next_s = (flags & STR_MAXIMAL) ? e : olds;
284*b30d1939SAndy Fiddaman 					mp->next_p = oldp;
285*b30d1939SAndy Fiddaman 					mp->current.groups = g;
286*b30d1939SAndy Fiddaman 					if (!pc && (!mp->best.next_s || (flags & STR_MAXIMAL) && mp->current.next_s > mp->best.next_s || !(flags & STR_MAXIMAL) && mp->current.next_s < mp->best.next_s))
287*b30d1939SAndy Fiddaman 						mp->best = mp->current;
288*b30d1939SAndy Fiddaman 					return 1;
289*b30d1939SAndy Fiddaman 				case '\\':
290*b30d1939SAndy Fiddaman 					if (!(pc = mbgetchar(p)))
291*b30d1939SAndy Fiddaman 						return 0;
292*b30d1939SAndy Fiddaman 					if (pc >= '0' && pc <= '9')
293*b30d1939SAndy Fiddaman 					{
294*b30d1939SAndy Fiddaman 						n = pc - '0';
295*b30d1939SAndy Fiddaman 						if (n <= g && mp->current.beg[n])
296*b30d1939SAndy Fiddaman 							pc = *mp->current.beg[n];
297*b30d1939SAndy Fiddaman 					}
298*b30d1939SAndy Fiddaman 					/*FALLTHROUGH*/
299*b30d1939SAndy Fiddaman 				default:
300*b30d1939SAndy Fiddaman 					if (icase && isupper(pc))
301*b30d1939SAndy Fiddaman 						pc = tolower(pc);
302*b30d1939SAndy Fiddaman 					n = 0;
303*b30d1939SAndy Fiddaman 					break;
304*b30d1939SAndy Fiddaman 				}
305*b30d1939SAndy Fiddaman 				p = oldp;
306*b30d1939SAndy Fiddaman 				for (;;)
307*b30d1939SAndy Fiddaman 				{
308*b30d1939SAndy Fiddaman 					if ((n || pc == sc) && onematch(mp, g, olds, p, e, NiL, flags))
309*b30d1939SAndy Fiddaman 						return 1;
310*b30d1939SAndy Fiddaman 					if (!sc)
311*b30d1939SAndy Fiddaman 						return 0;
312*b30d1939SAndy Fiddaman 					olds = s;
313*b30d1939SAndy Fiddaman 					sc = getsource(s, e);
314*b30d1939SAndy Fiddaman 					if ((flags & STR_ICASE) && isupper(sc))
315*b30d1939SAndy Fiddaman 						sc = tolower(sc);
316*b30d1939SAndy Fiddaman 				}
317*b30d1939SAndy Fiddaman 			}
318*b30d1939SAndy Fiddaman 			else if (pc != '?' && pc != sc)
319*b30d1939SAndy Fiddaman 				return 0;
320*b30d1939SAndy Fiddaman 			break;
321*b30d1939SAndy Fiddaman 		case 0:
322*b30d1939SAndy Fiddaman 			if (!(flags & STR_MAXIMAL))
323*b30d1939SAndy Fiddaman 				sc = 0;
324*b30d1939SAndy Fiddaman 			/*FALLTHROUGH*/
325*b30d1939SAndy Fiddaman 		case '|':
326*b30d1939SAndy Fiddaman 		case '&':
327*b30d1939SAndy Fiddaman 		case ')':
328*b30d1939SAndy Fiddaman 			if (!sc)
329*b30d1939SAndy Fiddaman 			{
330*b30d1939SAndy Fiddaman 				mp->current.next_s = olds;
331*b30d1939SAndy Fiddaman 				mp->next_p = oldp;
332*b30d1939SAndy Fiddaman 				mp->current.groups = g;
333*b30d1939SAndy Fiddaman 			}
334*b30d1939SAndy Fiddaman 			if (!pc && (!mp->best.next_s || (flags & STR_MAXIMAL) && olds > mp->best.next_s || !(flags & STR_MAXIMAL) && olds < mp->best.next_s))
335*b30d1939SAndy Fiddaman 			{
336*b30d1939SAndy Fiddaman 				mp->best = mp->current;
337*b30d1939SAndy Fiddaman 				mp->best.next_s = olds;
338*b30d1939SAndy Fiddaman 				mp->best.groups = g;
339*b30d1939SAndy Fiddaman 			}
340*b30d1939SAndy Fiddaman 			return !sc;
341*b30d1939SAndy Fiddaman 		case '[':
342*b30d1939SAndy Fiddaman 			{
343*b30d1939SAndy Fiddaman 				/*UNDENT...*/
344*b30d1939SAndy Fiddaman 
345*b30d1939SAndy Fiddaman 	int	invert;
346*b30d1939SAndy Fiddaman 	int	x;
347*b30d1939SAndy Fiddaman 	int	ok = 0;
348*b30d1939SAndy Fiddaman 	char*	range;
349*b30d1939SAndy Fiddaman 
350*b30d1939SAndy Fiddaman 	if (!sc)
351*b30d1939SAndy Fiddaman 		return 0;
352*b30d1939SAndy Fiddaman 	range = 0;
353*b30d1939SAndy Fiddaman 	n = 0;
354*b30d1939SAndy Fiddaman 	if (invert = *p == '!' || *p == '^')
355*b30d1939SAndy Fiddaman 		p++;
356*b30d1939SAndy Fiddaman 	for (;;)
357*b30d1939SAndy Fiddaman 	{
358*b30d1939SAndy Fiddaman 		oldp = p;
359*b30d1939SAndy Fiddaman 		if (!(pc = mbgetchar(p)))
360*b30d1939SAndy Fiddaman 			return 0;
361*b30d1939SAndy Fiddaman 		else if (pc == '[' && (*p == ':' || *p == '=' || *p == '.'))
362*b30d1939SAndy Fiddaman 		{
363*b30d1939SAndy Fiddaman 			x = 0;
364*b30d1939SAndy Fiddaman 			n = mbgetchar(p);
365*b30d1939SAndy Fiddaman 			oldp = p;
366*b30d1939SAndy Fiddaman 			for (;;)
367*b30d1939SAndy Fiddaman 			{
368*b30d1939SAndy Fiddaman 				if (!(pc = mbgetchar(p)))
369*b30d1939SAndy Fiddaman 					return 0;
370*b30d1939SAndy Fiddaman 				if (pc == n && *p == ']')
371*b30d1939SAndy Fiddaman 					break;
372*b30d1939SAndy Fiddaman 				x++;
373*b30d1939SAndy Fiddaman 			}
374*b30d1939SAndy Fiddaman 			mbgetchar(p);
375*b30d1939SAndy Fiddaman 			if (ok)
376*b30d1939SAndy Fiddaman 				/*NOP*/;
377*b30d1939SAndy Fiddaman 			else if (n == ':')
378*b30d1939SAndy Fiddaman 			{
379*b30d1939SAndy Fiddaman 				switch (HASHNKEY5(x, oldp[0], oldp[1], oldp[2], oldp[3], oldp[4]))
380*b30d1939SAndy Fiddaman 				{
381*b30d1939SAndy Fiddaman 				case HASHNKEY5(5,'a','l','n','u','m'):
382*b30d1939SAndy Fiddaman 					if (isalnum(sc))
383*b30d1939SAndy Fiddaman 						ok = 1;
384*b30d1939SAndy Fiddaman 					break;
385*b30d1939SAndy Fiddaman 				case HASHNKEY5(5,'a','l','p','h','a'):
386*b30d1939SAndy Fiddaman 					if (isalpha(sc))
387*b30d1939SAndy Fiddaman 						ok = 1;
388*b30d1939SAndy Fiddaman 					break;
389*b30d1939SAndy Fiddaman 				case HASHNKEY5(5,'b','l','a','n','k'):
390