xref: /minix3/external/bsd/bind/dist/lib/isc/regex.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: regex.c,v 1.3 2014/12/10 04:37:59 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2013, 2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  *
6*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
7*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
8*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
9*00b67f09SDavid van Moolenbroek  *
10*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
17*00b67f09SDavid van Moolenbroek  */
18*00b67f09SDavid van Moolenbroek 
19*00b67f09SDavid van Moolenbroek #include <config.h>
20*00b67f09SDavid van Moolenbroek 
21*00b67f09SDavid van Moolenbroek #include <isc/file.h>
22*00b67f09SDavid van Moolenbroek #include <isc/regex.h>
23*00b67f09SDavid van Moolenbroek #include <isc/string.h>
24*00b67f09SDavid van Moolenbroek 
25*00b67f09SDavid van Moolenbroek #if VALREGEX_REPORT_REASON
26*00b67f09SDavid van Moolenbroek #define FAIL(x) do { reason = (x); goto error; } while(/*CONSTCOND*/0)
27*00b67f09SDavid van Moolenbroek #else
28*00b67f09SDavid van Moolenbroek #define FAIL(x) goto error
29*00b67f09SDavid van Moolenbroek #endif
30*00b67f09SDavid van Moolenbroek 
31*00b67f09SDavid van Moolenbroek /*
32*00b67f09SDavid van Moolenbroek  * Validate the regular expression 'C' locale.
33*00b67f09SDavid van Moolenbroek  */
34*00b67f09SDavid van Moolenbroek int
isc_regex_validate(const char * c)35*00b67f09SDavid van Moolenbroek isc_regex_validate(const char *c) {
36*00b67f09SDavid van Moolenbroek 	enum {
37*00b67f09SDavid van Moolenbroek 		none, parse_bracket, parse_bound,
38*00b67f09SDavid van Moolenbroek 		parse_ce, parse_ec, parse_cc
39*00b67f09SDavid van Moolenbroek 	} state = none;
40*00b67f09SDavid van Moolenbroek 	/* Well known character classes. */
41*00b67f09SDavid van Moolenbroek 	const char *cc[] = {
42*00b67f09SDavid van Moolenbroek 		":alnum:", ":digit:", ":punct:", ":alpha:", ":graph:",
43*00b67f09SDavid van Moolenbroek 		":space:", ":blank:", ":lower:", ":upper:", ":cntrl:",
44*00b67f09SDavid van Moolenbroek 		":print:", ":xdigit:"
45*00b67f09SDavid van Moolenbroek 	};
46*00b67f09SDavid van Moolenbroek 	isc_boolean_t seen_comma = ISC_FALSE;
47*00b67f09SDavid van Moolenbroek 	isc_boolean_t seen_high = ISC_FALSE;
48*00b67f09SDavid van Moolenbroek 	isc_boolean_t seen_char = ISC_FALSE;
49*00b67f09SDavid van Moolenbroek 	isc_boolean_t seen_ec = ISC_FALSE;
50*00b67f09SDavid van Moolenbroek 	isc_boolean_t seen_ce = ISC_FALSE;
51*00b67f09SDavid van Moolenbroek 	isc_boolean_t have_atom = ISC_FALSE;
52*00b67f09SDavid van Moolenbroek 	int group = 0;
53*00b67f09SDavid van Moolenbroek 	int range = 0;
54*00b67f09SDavid van Moolenbroek 	int sub = 0;
55*00b67f09SDavid van Moolenbroek 	isc_boolean_t empty_ok = ISC_FALSE;
56*00b67f09SDavid van Moolenbroek 	isc_boolean_t neg = ISC_FALSE;
57*00b67f09SDavid van Moolenbroek 	isc_boolean_t was_multiple = ISC_FALSE;
58*00b67f09SDavid van Moolenbroek 	unsigned int low = 0;
59*00b67f09SDavid van Moolenbroek 	unsigned int high = 0;
60*00b67f09SDavid van Moolenbroek 	const char *ccname = NULL;
61*00b67f09SDavid van Moolenbroek 	int range_start = 0;
62*00b67f09SDavid van Moolenbroek #if VALREGEX_REPORT_REASON
63*00b67f09SDavid van Moolenbroek 	const char *reason = "";
64*00b67f09SDavid van Moolenbroek #endif
65*00b67f09SDavid van Moolenbroek 
66*00b67f09SDavid van Moolenbroek 	if (c == NULL || *c == 0)
67*00b67f09SDavid van Moolenbroek 		FAIL("empty string");
68*00b67f09SDavid van Moolenbroek 
69*00b67f09SDavid van Moolenbroek 	while (c != NULL && *c != 0) {
70*00b67f09SDavid van Moolenbroek 		switch (state) {
71*00b67f09SDavid van Moolenbroek 		case none:
72*00b67f09SDavid van Moolenbroek 			switch (*c) {
73*00b67f09SDavid van Moolenbroek 			case '\\':	/* make literal */
74*00b67f09SDavid van Moolenbroek 				++c;
75*00b67f09SDavid van Moolenbroek 				switch (*c) {
76*00b67f09SDavid van Moolenbroek 				case '1': case '2': case '3':
77*00b67f09SDavid van Moolenbroek 				case '4': case '5': case '6':
78*00b67f09SDavid van Moolenbroek 				case '7': case '8': case '9':
79*00b67f09SDavid van Moolenbroek 					if ((*c - '0') > sub)
80*00b67f09SDavid van Moolenbroek 						FAIL("bad back reference");
81*00b67f09SDavid van Moolenbroek 					have_atom = ISC_TRUE;
82*00b67f09SDavid van Moolenbroek 					was_multiple = ISC_FALSE;
83*00b67f09SDavid van Moolenbroek 					break;
84*00b67f09SDavid van Moolenbroek 				case 0:
85*00b67f09SDavid van Moolenbroek 					FAIL("escaped end-of-string");
86*00b67f09SDavid van Moolenbroek 				default:
87*00b67f09SDavid van Moolenbroek 					goto literal;
88*00b67f09SDavid van Moolenbroek 				}
89*00b67f09SDavid van Moolenbroek 				++c;
90*00b67f09SDavid van Moolenbroek 				break;
91*00b67f09SDavid van Moolenbroek 			case '[':	/* bracket start */
92*00b67f09SDavid van Moolenbroek 				++c;
93*00b67f09SDavid van Moolenbroek 				neg = ISC_FALSE;
94*00b67f09SDavid van Moolenbroek 				was_multiple = ISC_FALSE;
95*00b67f09SDavid van Moolenbroek 				seen_char = ISC_FALSE;
96*00b67f09SDavid van Moolenbroek 				state = parse_bracket;
97*00b67f09SDavid van Moolenbroek 				break;
98*00b67f09SDavid van Moolenbroek 			case '{': 	/* bound start */
99*00b67f09SDavid van Moolenbroek 				switch (c[1]) {
100*00b67f09SDavid van Moolenbroek 				case '0': case '1': case '2': case '3':
101*00b67f09SDavid van Moolenbroek 				case '4': case '5': case '6': case '7':
102*00b67f09SDavid van Moolenbroek 				case '8': case '9':
103*00b67f09SDavid van Moolenbroek 					if (!have_atom)
104*00b67f09SDavid van Moolenbroek 						FAIL("no atom");
105*00b67f09SDavid van Moolenbroek 					if (was_multiple)
106*00b67f09SDavid van Moolenbroek 						FAIL("was multiple");
107*00b67f09SDavid van Moolenbroek 					seen_comma = ISC_FALSE;
108*00b67f09SDavid van Moolenbroek 					seen_high = ISC_FALSE;
109*00b67f09SDavid van Moolenbroek 					low = high = 0;
110*00b67f09SDavid van Moolenbroek 					state = parse_bound;
111*00b67f09SDavid van Moolenbroek 					break;
112*00b67f09SDavid van Moolenbroek 				default:
113*00b67f09SDavid van Moolenbroek 					goto literal;
114*00b67f09SDavid van Moolenbroek 				}
115*00b67f09SDavid van Moolenbroek 				++c;
116*00b67f09SDavid van Moolenbroek 				have_atom = ISC_TRUE;
117*00b67f09SDavid van Moolenbroek 				was_multiple = ISC_TRUE;
118*00b67f09SDavid van Moolenbroek 				break;
119*00b67f09SDavid van Moolenbroek 			case '}':
120*00b67f09SDavid van Moolenbroek 				goto literal;
121*00b67f09SDavid van Moolenbroek 			case '(':	/* group start */
122*00b67f09SDavid van Moolenbroek 				have_atom = ISC_FALSE;
123*00b67f09SDavid van Moolenbroek 				was_multiple = ISC_FALSE;
124*00b67f09SDavid van Moolenbroek 				empty_ok = ISC_TRUE;
125*00b67f09SDavid van Moolenbroek 				++group;
126*00b67f09SDavid van Moolenbroek 				++sub;
127*00b67f09SDavid van Moolenbroek 				++c;
128*00b67f09SDavid van Moolenbroek 				break;
129*00b67f09SDavid van Moolenbroek 			case ')':	/* group end */
130*00b67f09SDavid van Moolenbroek 				if (group && !have_atom && !empty_ok)
131*00b67f09SDavid van Moolenbroek 					FAIL("empty alternative");
132*00b67f09SDavid van Moolenbroek 				have_atom = ISC_TRUE;
133*00b67f09SDavid van Moolenbroek 				was_multiple = ISC_FALSE;
134*00b67f09SDavid van Moolenbroek 				if (group != 0)
135*00b67f09SDavid van Moolenbroek 					--group;
136*00b67f09SDavid van Moolenbroek 				++c;
137*00b67f09SDavid van Moolenbroek 				break;
138*00b67f09SDavid van Moolenbroek 			case '|':	/* alternative seperator */
139*00b67f09SDavid van Moolenbroek 				if (!have_atom)
140*00b67f09SDavid van Moolenbroek 					FAIL("no atom");
141*00b67f09SDavid van Moolenbroek 				have_atom = ISC_FALSE;
142*00b67f09SDavid van Moolenbroek 				empty_ok = ISC_FALSE;
143*00b67f09SDavid van Moolenbroek 				was_multiple = ISC_FALSE;
144*00b67f09SDavid van Moolenbroek 				++c;
145*00b67f09SDavid van Moolenbroek 				break;
146*00b67f09SDavid van Moolenbroek 			case '^':
147*00b67f09SDavid van Moolenbroek 			case '$':
148*00b67f09SDavid van Moolenbroek 				have_atom = ISC_TRUE;
149*00b67f09SDavid van Moolenbroek 				was_multiple = ISC_TRUE;
150*00b67f09SDavid van Moolenbroek 				++c;
151*00b67f09SDavid van Moolenbroek 				break;
152*00b67f09SDavid van Moolenbroek 			case '+':
153*00b67f09SDavid van Moolenbroek 			case '*':
154*00b67f09SDavid van Moolenbroek 			case '?':
155*00b67f09SDavid van Moolenbroek 				if (was_multiple)
156*00b67f09SDavid van Moolenbroek 					FAIL("was multiple");
157*00b67f09SDavid van Moolenbroek 				if (!have_atom)
158*00b67f09SDavid van Moolenbroek 					FAIL("no atom");
159*00b67f09SDavid van Moolenbroek 				have_atom = ISC_TRUE;
160*00b67f09SDavid van Moolenbroek 				was_multiple = ISC_TRUE;
161*00b67f09SDavid van Moolenbroek 				++c;
162*00b67f09SDavid van Moolenbroek 				break;
163*00b67f09SDavid van Moolenbroek 			case '.':
164*00b67f09SDavid van Moolenbroek 			default:
165*00b67f09SDavid van Moolenbroek 			literal:
166*00b67f09SDavid van Moolenbroek 				have_atom = ISC_TRUE;
167*00b67f09SDavid van Moolenbroek 				was_multiple = ISC_FALSE;
168*00b67f09SDavid van Moolenbroek 				++c;
169*00b67f09SDavid van Moolenbroek 				break;
170*00b67f09SDavid van Moolenbroek 			}
171*00b67f09SDavid van Moolenbroek 			break;
172*00b67f09SDavid van Moolenbroek 		case parse_bound:
173*00b67f09SDavid van Moolenbroek 			switch (*c) {
174*00b67f09SDavid van Moolenbroek 			case '0': case '1': case '2': case '3': case '4':
175*00b67f09SDavid van Moolenbroek 			case '5': case '6': case '7': case '8': case '9':
176*00b67f09SDavid van Moolenbroek 				if (!seen_comma) {
177*00b67f09SDavid van Moolenbroek 					low = low * 10 + *c - '0';
178*00b67f09SDavid van Moolenbroek 					if (low > 255)
179*00b67f09SDavid van Moolenbroek 						FAIL("lower bound too big");
180*00b67f09SDavid van Moolenbroek 				} else {
181*00b67f09SDavid van Moolenbroek 					seen_high = ISC_TRUE;
182*00b67f09SDavid van Moolenbroek 					high = high * 10 + *c - '0';
183*00b67f09SDavid van Moolenbroek 					if (high > 255)
184*00b67f09SDavid van Moolenbroek 						FAIL("upper bound too big");
185*00b67f09SDavid van Moolenbroek 				}
186*00b67f09SDavid van Moolenbroek 				++c;
187*00b67f09SDavid van Moolenbroek 				break;
188*00b67f09SDavid van Moolenbroek 			case ',':
189*00b67f09SDavid van Moolenbroek 				if (seen_comma)
190*00b67f09SDavid van Moolenbroek 					FAIL("multiple commas");
191*00b67f09SDavid van Moolenbroek 				seen_comma = ISC_TRUE;
192*00b67f09SDavid van Moolenbroek 				++c;
193*00b67f09SDavid van Moolenbroek 				break;
194*00b67f09SDavid van Moolenbroek 			default:
195*00b67f09SDavid van Moolenbroek 			case '{':
196*00b67f09SDavid van Moolenbroek 				FAIL("non digit/comma");
197*00b67f09SDavid van Moolenbroek 			case '}':
198*00b67f09SDavid van Moolenbroek 				if (seen_high && low > high)
199*00b67f09SDavid van Moolenbroek 					FAIL("bad parse bound");
200*00b67f09SDavid van Moolenbroek 				seen_comma = ISC_FALSE;
201*00b67f09SDavid van Moolenbroek 				state = none;
202*00b67f09SDavid van Moolenbroek 				++c;
203*00b67f09SDavid van Moolenbroek 				break;
204*00b67f09SDavid van Moolenbroek 			}
205*00b67f09SDavid van Moolenbroek 			break;
206*00b67f09SDavid van Moolenbroek 		case parse_bracket:
207*00b67f09SDavid van Moolenbroek 			switch (*c) {
208*00b67f09SDavid van Moolenbroek 			case '^':
209*00b67f09SDavid van Moolenbroek 				if (seen_char || neg) goto inside;
210*00b67f09SDavid van Moolenbroek 				neg = ISC_TRUE;
211*00b67f09SDavid van Moolenbroek 				++c;
212*00b67f09SDavid van Moolenbroek 				break;
213*00b67f09SDavid van Moolenbroek 			case '-':
214*00b67f09SDavid van Moolenbroek 				if (range == 2) goto inside;
215*00b67f09SDavid van Moolenbroek 				if (!seen_char) goto inside;
216*00b67f09SDavid van Moolenbroek 				if (range == 1)
217*00b67f09SDavid van Moolenbroek 					FAIL("bad range");
218*00b67f09SDavid van Moolenbroek 				range = 2;
219*00b67f09SDavid van Moolenbroek 				++c;
220*00b67f09SDavid van Moolenbroek 				break;
221*00b67f09SDavid van Moolenbroek 			case '[':
222*00b67f09SDavid van Moolenbroek 				++c;
223*00b67f09SDavid van Moolenbroek 				switch (*c) {
224*00b67f09SDavid van Moolenbroek 				case '.':	/* collating element */
225*00b67f09SDavid van Moolenbroek 					if (range != 0) --range;
226*00b67f09SDavid van Moolenbroek 					++c;
227*00b67f09SDavid van Moolenbroek 					state = parse_ce;
228*00b67f09SDavid van Moolenbroek 					seen_ce = ISC_FALSE;
229*00b67f09SDavid van Moolenbroek 					break;
230*00b67f09SDavid van Moolenbroek 				case '=':	/* equivalence class */
231*00b67f09SDavid van Moolenbroek 					if (range == 2)
232*00b67f09SDavid van Moolenbroek 					    FAIL("equivalence class in range");
233*00b67f09SDavid van Moolenbroek 					++c;
234*00b67f09SDavid van Moolenbroek 					state = parse_ec;
235*00b67f09SDavid van Moolenbroek 					seen_ec = ISC_FALSE;
236*00b67f09SDavid van Moolenbroek 					break;
237*00b67f09SDavid van Moolenbroek 				case ':':	/* character class */
238*00b67f09SDavid van Moolenbroek 					if (range == 2)
239*00b67f09SDavid van Moolenbroek 					      FAIL("character class in range");
240*00b67f09SDavid van Moolenbroek 					ccname = c;
241*00b67f09SDavid van Moolenbroek 					++c;
242*00b67f09SDavid van Moolenbroek 					state = parse_cc;
243*00b67f09SDavid van Moolenbroek 					break;
244*00b67f09SDavid van Moolenbroek 				}
245*00b67f09SDavid van Moolenbroek 				seen_char = ISC_TRUE;
246*00b67f09SDavid van Moolenbroek 				break;
247*00b67f09SDavid van Moolenbroek 			case ']':
248*00b67f09SDavid van Moolenbroek 				if (!c[1] && !seen_char)
249*00b67f09SDavid van Moolenbroek 					FAIL("unfinished brace");
250*00b67f09SDavid van Moolenbroek 				if (!seen_char)
251*00b67f09SDavid van Moolenbroek 					goto inside;
252*00b67f09SDavid van Moolenbroek 				++c;
253*00b67f09SDavid van Moolenbroek 				range = 0;
254*00b67f09SDavid van Moolenbroek 				have_atom = ISC_TRUE;
255*00b67f09SDavid van Moolenbroek 				state = none;
256*00b67f09SDavid van Moolenbroek 				break;
257*00b67f09SDavid van Moolenbroek 			default:
258*00b67f09SDavid van Moolenbroek 			inside:
259*00b67f09SDavid van Moolenbroek 				seen_char = ISC_TRUE;
260*00b67f09SDavid van Moolenbroek 				if (range == 2 && (*c & 0xff) < range_start)
261*00b67f09SDavid van Moolenbroek 					FAIL("out of order range");
262*00b67f09SDavid van Moolenbroek 				if (range != 0)
263*00b67f09SDavid van Moolenbroek 					--range;
264*00b67f09SDavid van Moolenbroek 				range_start = *c & 0xff;
265*00b67f09SDavid van Moolenbroek 				++c;
266*00b67f09SDavid van Moolenbroek 				break;
267*00b67f09SDavid van Moolenbroek 			};
268*00b67f09SDavid van Moolenbroek 			break;
269*00b67f09SDavid van Moolenbroek 		case parse_ce:
270*00b67f09SDavid van Moolenbroek 			switch (*c) {
271*00b67f09SDavid van Moolenbroek 			case '.':
272*00b67f09SDavid van Moolenbroek 				++c;
273*00b67f09SDavid van Moolenbroek 				switch (*c) {
274*00b67f09SDavid van Moolenbroek 				case ']':
275*00b67f09SDavid van Moolenbroek 					if (!seen_ce)
276*00b67f09SDavid van Moolenbroek 						 FAIL("empty ce");
277*00b67f09SDavid van Moolenbroek 					++c;
278*00b67f09SDavid van Moolenbroek 					state = parse_bracket;
279*00b67f09SDavid van Moolenbroek 					break;
280*00b67f09SDavid van Moolenbroek 				default:
281*00b67f09SDavid van Moolenbroek 					if (seen_ce)
282*00b67f09SDavid van Moolenbroek 						range_start = 256;
283*00b67f09SDavid van Moolenbroek 					else
284*00b67f09SDavid van Moolenbroek 						range_start = '.';
285*00b67f09SDavid van Moolenbroek 					seen_ce = ISC_TRUE;
286*00b67f09SDavid van Moolenbroek 					break;
287*00b67f09SDavid van Moolenbroek 				}
288*00b67f09SDavid van Moolenbroek 				break;
289*00b67f09SDavid van Moolenbroek 			default:
290*00b67f09SDavid van Moolenbroek 				if (seen_ce)
291*00b67f09SDavid van Moolenbroek 					range_start = 256;
292*00b67f09SDavid van Moolenbroek 				else
293*00b67f09SDavid van Moolenbroek 					range_start = *c;
294*00b67f09SDavid van Moolenbroek 				seen_ce = ISC_TRUE;
295*00b67f09SDavid van Moolenbroek 				++c;
296*00b67f09SDavid van Moolenbroek 				break;
297*00b67f09SDavid van Moolenbroek 			}
298*00b67f09SDavid van Moolenbroek 			break;
299*00b67f09SDavid van Moolenbroek 		case parse_ec:
300*00b67f09SDavid van Moolenbroek 			switch (*c) {
301*00b67f09SDavid van Moolenbroek 			case '=':
302*00b67f09SDavid van Moolenbroek 				++c;
303*00b67f09SDavid van Moolenbroek 				switch (*c) {
304*00b67f09SDavid van Moolenbroek 				case ']':
305*00b67f09SDavid van Moolenbroek 					if (!seen_ec)
306*00b67f09SDavid van Moolenbroek 						FAIL("no ec");
307*00b67f09SDavid van Moolenbroek 					++c;
308*00b67f09SDavid van Moolenbroek 					state = parse_bracket;
309*00b67f09SDavid van Moolenbroek 					break;
310*00b67f09SDavid van Moolenbroek 				default:
311*00b67f09SDavid van Moolenbroek 					seen_ec = ISC_TRUE;
312*00b67f09SDavid van Moolenbroek 					break;
313*00b67f09SDavid van Moolenbroek 				}
314*00b67f09SDavid van Moolenbroek 				break;
315*00b67f09SDavid van Moolenbroek 			default:
316*00b67f09SDavid van Moolenbroek 				seen_ec = ISC_TRUE;
317*00b67f09SDavid van Moolenbroek 				++c;
318*00b67f09SDavid van Moolenbroek 				break;
319*00b67f09SDavid van Moolenbroek 			}
320*00b67f09SDavid van Moolenbroek 			break;
321*00b67f09SDavid van Moolenbroek 		case parse_cc:
322*00b67f09SDavid van Moolenbroek 			switch (*c) {
323*00b67f09SDavid van Moolenbroek 			case ':':
324*00b67f09SDavid van Moolenbroek 				++c;
325*00b67f09SDavid van Moolenbroek 				switch (*c) {
326*00b67f09SDavid van Moolenbroek 				case ']': {
327*00b67f09SDavid van Moolenbroek 					unsigned int i;
328*00b67f09SDavid van Moolenbroek 					isc_boolean_t found = ISC_FALSE;
329*00b67f09SDavid van Moolenbroek 					for (i = 0;
330*00b67f09SDavid van Moolenbroek 					     i < sizeof(cc)/sizeof(*cc);
331*00b67f09SDavid van Moolenbroek 					     i++)
332*00b67f09SDavid van Moolenbroek 					{
333*00b67f09SDavid van Moolenbroek 						unsigned int len;
334*00b67f09SDavid van Moolenbroek 						len = strlen(cc[i]);
335*00b67f09SDavid van Moolenbroek 						if (len !=
336*00b67f09SDavid van Moolenbroek 						    (unsigned int)(c - ccname))
337*00b67f09SDavid van Moolenbroek 							continue;
338*00b67f09SDavid van Moolenbroek 						if (strncmp(cc[i], ccname, len))
339*00b67f09SDavid van Moolenbroek 							continue;
340*00b67f09SDavid van Moolenbroek 						found = ISC_TRUE;
341*00b67f09SDavid van Moolenbroek 					}
342*00b67f09SDavid van Moolenbroek 					if (!found)
343*00b67f09SDavid van Moolenbroek 						FAIL("unknown cc");
344*00b67f09SDavid van Moolenbroek 					++c;
345*00b67f09SDavid van Moolenbroek 					state = parse_bracket;
346*00b67f09SDavid van Moolenbroek 					break;
347*00b67f09SDavid van Moolenbroek 					}
348*00b67f09SDavid van Moolenbroek 				default:
349*00b67f09SDavid van Moolenbroek 					break;
350*00b67f09SDavid van Moolenbroek 				}
351*00b67f09SDavid van Moolenbroek 				break;
352*00b67f09SDavid van Moolenbroek 			default:
353*00b67f09SDavid van Moolenbroek 				++c;
354*00b67f09SDavid van Moolenbroek 				break;
355*00b67f09SDavid van Moolenbroek 			}
356*00b67f09SDavid van Moolenbroek 			break;
357*00b67f09SDavid van Moolenbroek 		}
358*00b67f09SDavid van Moolenbroek 	}
359*00b67f09SDavid van Moolenbroek 	if (group != 0)
360*00b67f09SDavid van Moolenbroek 		FAIL("group open");
361*00b67f09SDavid van Moolenbroek 	if (state != none)
362*00b67f09SDavid van Moolenbroek 		FAIL("incomplete");
363*00b67f09SDavid van Moolenbroek 	if (!have_atom)
364*00b67f09SDavid van Moolenbroek 		FAIL("no atom");
365*00b67f09SDavid van Moolenbroek 	return (sub);
366*00b67f09SDavid van Moolenbroek 
367*00b67f09SDavid van Moolenbroek  error:
368*00b67f09SDavid van Moolenbroek #if VALREGEX_REPORT_REASON
369*00b67f09SDavid van Moolenbroek 	fprintf(stderr, "%s\n", reason);
370*00b67f09SDavid van Moolenbroek #endif
371*00b67f09SDavid van Moolenbroek 	return (-1);
372*00b67f09SDavid van Moolenbroek }
373