xref: /freebsd/lib/libc/regex/regcomp.c (revision 22cf89c938886d14f5796fc49f9f020c23ea8eaf)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1992, 1993, 1994 Henry Spencer.
5  * Copyright (c) 1992, 1993, 1994
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Copyright (c) 2011 The FreeBSD Foundation
9  *
10  * Portions of this software were developed by David Chisnall
11  * under sponsorship from the FreeBSD Foundation.
12  *
13  * This code is derived from software contributed to Berkeley by
14  * Henry Spencer.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions
18  * are met:
19  * 1. Redistributions of source code must retain the above copyright
20  *    notice, this list of conditions and the following disclaimer.
21  * 2. Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the
23  *    documentation and/or other materials provided with the distribution.
24  * 3. Neither the name of the University nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  *
40  *	@(#)regcomp.c	8.5 (Berkeley) 3/20/94
41  */
42 
43 #if defined(LIBC_SCCS) && !defined(lint)
44 static char sccsid[] = "@(#)regcomp.c	8.5 (Berkeley) 3/20/94";
45 #endif /* LIBC_SCCS and not lint */
46 #include <sys/cdefs.h>
47 #include <sys/types.h>
48 #include <stdio.h>
49 #include <string.h>
50 #include <ctype.h>
51 #include <limits.h>
52 #include <stdlib.h>
53 #include <regex.h>
54 #include <stdbool.h>
55 #include <wchar.h>
56 #include <wctype.h>
57 
58 #ifndef LIBREGEX
59 #include "collate.h"
60 #endif
61 
62 #include "utils.h"
63 #include "regex2.h"
64 
65 #include "cname.h"
66 
67 /*
68  * Branching context, used to keep track of branch state for all of the branch-
69  * aware functions. In addition to keeping track of branch positions for the
70  * p_branch_* functions, we use this to simplify some clumsiness in BREs for
71  * detection of whether ^ is acting as an anchor or being used erroneously and
72  * also for whether we're in a sub-expression or not.
73  */
74 struct branchc {
75 	sopno start;
76 	sopno back;
77 	sopno fwd;
78 
79 	int nbranch;
80 	int nchain;
81 	bool outer;
82 	bool terminate;
83 };
84 
85 /*
86  * parse structure, passed up and down to avoid global variables and
87  * other clumsinesses
88  */
89 struct parse {
90 	const char *next;	/* next character in RE */
91 	const char *end;	/* end of string (-> NUL normally) */
92 	int error;		/* has an error been seen? */
93 	int gnuext;
94 	sop *strip;		/* malloced strip */
95 	sopno ssize;		/* malloced strip size (allocated) */
96 	sopno slen;		/* malloced strip length (used) */
97 	int ncsalloc;		/* number of csets allocated */
98 	struct re_guts *g;
99 #	define	NPAREN	10	/* we need to remember () 1-9 for back refs */
100 	sopno pbegin[NPAREN];	/* -> ( ([0] unused) */
101 	sopno pend[NPAREN];	/* -> ) ([0] unused) */
102 	bool allowbranch;	/* can this expression branch? */
103 	bool bre;		/* convenience; is this a BRE? */
104 	int pflags;		/* other parsing flags -- legacy escapes? */
105 	bool (*parse_expr)(struct parse *, struct branchc *);
106 	void (*pre_parse)(struct parse *, struct branchc *);
107 	void (*post_parse)(struct parse *, struct branchc *);
108 };
109 
110 #define PFLAG_LEGACY_ESC	0x00000001
111 
112 /* ========= begin header generated by ./mkh ========= */
113 #ifdef __cplusplus
114 extern "C" {
115 #endif
116 
117 /* === regcomp.c === */
118 static bool p_ere_exp(struct parse *p, struct branchc *bc);
119 static void p_str(struct parse *p);
120 static int p_branch_eat_delim(struct parse *p, struct branchc *bc);
121 static void p_branch_ins_offset(struct parse *p, struct branchc *bc);
122 static void p_branch_fix_tail(struct parse *p, struct branchc *bc);
123 static bool p_branch_empty(struct parse *p, struct branchc *bc);
124 static bool p_branch_do(struct parse *p, struct branchc *bc);
125 static void p_bre_pre_parse(struct parse *p, struct branchc *bc);
126 static void p_bre_post_parse(struct parse *p, struct branchc *bc);
127 static void p_re(struct parse *p, int end1, int end2);
128 static bool p_simp_re(struct parse *p, struct branchc *bc);
129 static int p_count(struct parse *p);
130 static void p_bracket(struct parse *p);
131 static int p_range_cmp(wchar_t c1, wchar_t c2);
132 static void p_b_term(struct parse *p, cset *cs);
133 static int p_b_pseudoclass(struct parse *p, char c);
134 static void p_b_cclass(struct parse *p, cset *cs);
135 static void p_b_cclass_named(struct parse *p, cset *cs, const char[]);
136 static void p_b_eclass(struct parse *p, cset *cs);
137 static wint_t p_b_symbol(struct parse *p);
138 static wint_t p_b_coll_elem(struct parse *p, wint_t endc);
139 static bool may_escape(struct parse *p, const wint_t ch);
140 static wint_t othercase(wint_t ch);
141 static void bothcases(struct parse *p, wint_t ch);
142 static void ordinary(struct parse *p, wint_t ch);
143 static void nonnewline(struct parse *p);
144 static void repeat(struct parse *p, sopno start, int from, int to);
145 static int seterr(struct parse *p, int e);
146 static cset *allocset(struct parse *p);
147 static void freeset(struct parse *p, cset *cs);
148 static void CHadd(struct parse *p, cset *cs, wint_t ch);
149 static void CHaddrange(struct parse *p, cset *cs, wint_t min, wint_t max);
150 static void CHaddtype(struct parse *p, cset *cs, wctype_t wct);
151 static wint_t singleton(cset *cs);
152 static sopno dupl(struct parse *p, sopno start, sopno finish);
153 static void doemit(struct parse *p, sop op, size_t opnd);
154 static void doinsert(struct parse *p, sop op, size_t opnd, sopno pos);
155 static void dofwd(struct parse *p, sopno pos, sop value);
156 static int enlarge(struct parse *p, sopno size);
157 static void stripsnug(struct parse *p, struct re_guts *g);
158 static void findmust(struct parse *p, struct re_guts *g);
159 static int altoffset(sop *scan, int offset);
160 static void computejumps(struct parse *p, struct re_guts *g);
161 static void computematchjumps(struct parse *p, struct re_guts *g);
162 static sopno pluscount(struct parse *p, struct re_guts *g);
163 static wint_t wgetnext(struct parse *p);
164 
165 #ifdef __cplusplus
166 }
167 #endif
168 /* ========= end header generated by ./mkh ========= */
169 
170 static char nuls[10];		/* place to point scanner in event of error */
171 
172 /*
173  * macros for use with parse structure
174  * BEWARE:  these know that the parse structure is named `p' !!!
175  */
176 #define	PEEK()	(*p->next)
177 #define	PEEK2()	(*(p->next+1))
178 #define	MORE()	(p->end - p->next > 0)
179 #define	MORE2()	(p->end - p->next > 1)
180 #define	SEE(c)	(MORE() && PEEK() == (c))
181 #define	SEETWO(a, b)	(MORE2() && PEEK() == (a) && PEEK2() == (b))
182 #define	SEESPEC(a)	(p->bre ? SEETWO('\\', a) : SEE(a))
183 #define	EAT(c)	((SEE(c)) ? (NEXT(), 1) : 0)
184 #define	EATTWO(a, b)	((SEETWO(a, b)) ? (NEXT2(), 1) : 0)
185 #define	EATSPEC(a)	(p->bre ? EATTWO('\\', a) : EAT(a))
186 #define	NEXT()	(p->next++)
187 #define	NEXT2()	(p->next += 2)
188 #define	NEXTn(n)	(p->next += (n))
189 #define	GETNEXT()	(*p->next++)
190 #define	WGETNEXT()	wgetnext(p)
191 #define	SETERROR(e)	seterr(p, (e))
192 #define	REQUIRE(co, e)	((co) || SETERROR(e))
193 #define	MUSTSEE(c, e)	(REQUIRE(MORE() && PEEK() == (c), e))
194 #define	MUSTEAT(c, e)	(REQUIRE(MORE() && GETNEXT() == (c), e))
195 #define	MUSTNOTSEE(c, e)	(REQUIRE(!MORE() || PEEK() != (c), e))
196 #define	EMIT(op, sopnd)	doemit(p, (sop)(op), (size_t)(sopnd))
197 #define	INSERT(op, pos)	doinsert(p, (sop)(op), HERE()-(pos)+1, pos)
198 #define	AHEAD(pos)		dofwd(p, pos, HERE()-(pos))
199 #define	ASTERN(sop, pos)	EMIT(sop, HERE()-pos)
200 #define	HERE()		(p->slen)
201 #define	THERE()		(p->slen - 1)
202 #define	THERETHERE()	(p->slen - 2)
203 #define	DROP(n)	(p->slen -= (n))
204 
205 /* Macro used by computejump()/computematchjump() */
206 #define MIN(a,b)	((a)<(b)?(a):(b))
207 
208 static int				/* 0 success, otherwise REG_something */
209 regcomp_internal(regex_t * __restrict preg,
210 	const char * __restrict pattern,
211 	int cflags, int pflags)
212 {
213 	struct parse pa;
214 	struct re_guts *g;
215 	struct parse *p = &pa;
216 	int i;
217 	size_t len;
218 	size_t maxlen;
219 #ifdef REDEBUG
220 #	define	GOODFLAGS(f)	(f)
221 #else
222 #	define	GOODFLAGS(f)	((f)&~REG_DUMP)
223 #endif
224 
225 	cflags = GOODFLAGS(cflags);
226 	if ((cflags&REG_EXTENDED) && (cflags&REG_NOSPEC))
227 		return(REG_INVARG);
228 
229 	if (cflags&REG_PEND) {
230 		if (preg->re_endp < pattern)
231 			return(REG_INVARG);
232 		len = preg->re_endp - pattern;
233 	} else
234 		len = strlen(pattern);
235 
236 	/* do the mallocs early so failure handling is easy */
237 	g = (struct re_guts *)malloc(sizeof(struct re_guts));
238 	if (g == NULL)
239 		return(REG_ESPACE);
240 	/*
241 	 * Limit the pattern space to avoid a 32-bit overflow on buffer
242 	 * extension.  Also avoid any signed overflow in case of conversion
243 	 * so make the real limit based on a 31-bit overflow.
244 	 *
245 	 * Likely not applicable on 64-bit systems but handle the case
246 	 * generically (who are we to stop people from using ~715MB+
247 	 * patterns?).
248 	 */
249 	maxlen = ((size_t)-1 >> 1) / sizeof(sop) * 2 / 3;
250 	if (len >= maxlen) {
251 		free((char *)g);
252 		return(REG_ESPACE);
253 	}
254 	p->ssize = len/(size_t)2*(size_t)3 + (size_t)1;	/* ugh */
255 	assert(p->ssize >= len);
256 
257 	p->strip = (sop *)malloc(p->ssize * sizeof(sop));
258 	p->slen = 0;
259 	if (p->strip == NULL) {
260 		free((char *)g);
261 		return(REG_ESPACE);
262 	}
263 
264 	/* set things up */
265 	p->g = g;
266 	p->next = pattern;	/* convenience; we do not modify it */
267 	p->end = p->next + len;
268 	p->error = 0;
269 	p->ncsalloc = 0;
270 	p->pflags = pflags;
271 	for (i = 0; i < NPAREN; i++) {
272 		p->pbegin[i] = 0;
273 		p->pend[i] = 0;
274 	}
275 #ifdef LIBREGEX
276 	if (cflags&REG_POSIX) {
277 		p->gnuext = false;
278 		p->allowbranch = (cflags & REG_EXTENDED) != 0;
279 	} else
280 		p->gnuext = p->allowbranch = true;
281 #else
282 	p->gnuext = false;
283 	p->allowbranch = (cflags & REG_EXTENDED) != 0;
284 #endif
285 	if (cflags & REG_EXTENDED) {
286 		p->bre = false;
287 		p->parse_expr = p_ere_exp;
288 		p->pre_parse = NULL;
289 		p->post_parse = NULL;
290 	} else {
291 		p->bre = true;
292 		p->parse_expr = p_simp_re;
293 		p->pre_parse = p_bre_pre_parse;
294 		p->post_parse = p_bre_post_parse;
295 	}
296 	g->sets = NULL;
297 	g->ncsets = 0;
298 	g->cflags = cflags;
299 	g->iflags = 0;
300 	g->nbol = 0;
301 	g->neol = 0;
302 	g->must = NULL;
303 	g->moffset = -1;
304 	g->charjump = NULL;
305 	g->matchjump = NULL;
306 	g->mlen = 0;
307 	g->nsub = 0;
308 	g->backrefs = 0;
309 
310 	/* do it */
311 	EMIT(OEND, 0);
312 	g->firststate = THERE();
313 	if (cflags & REG_NOSPEC)
314 		p_str(p);
315 	else
316 		p_re(p, OUT, OUT);
317 	EMIT(OEND, 0);
318 	g->laststate = THERE();
319 
320 	/* tidy up loose ends and fill things in */
321 	stripsnug(p, g);
322 	findmust(p, g);
323 	/* only use Boyer-Moore algorithm if the pattern is bigger
324 	 * than three characters
325 	 */
326 	if(g->mlen > 3) {
327 		computejumps(p, g);
328 		computematchjumps(p, g);
329 		if(g->matchjump == NULL && g->charjump != NULL) {
330 			free(g->charjump);
331 			g->charjump = NULL;
332 		}
333 	}
334 	g->nplus = pluscount(p, g);
335 	g->magic = MAGIC2;
336 	preg->re_nsub = g->nsub;
337 	preg->re_g = g;
338 	preg->re_magic = MAGIC1;
339 #ifndef REDEBUG
340 	/* not debugging, so can't rely on the assert() in regexec() */
341 	if (g->iflags&BAD)
342 		SETERROR(REG_ASSERT);
343 #endif
344 
345 	/* win or lose, we're done */
346 	if (p->error != 0)	/* lose */
347 		regfree(preg);
348 	return(p->error);
349 }
350 
351 /*
352  - regcomp - interface for parser and compilation
353  = extern int regcomp(regex_t *, const char *, int);
354  = #define	REG_BASIC	0000
355  = #define	REG_EXTENDED	0001
356  = #define	REG_ICASE	0002
357  = #define	REG_NOSUB	0004
358  = #define	REG_NEWLINE	0010
359  = #define	REG_NOSPEC	0020
360  = #define	REG_PEND	0040
361  = #define	REG_DUMP	0200
362  */
363 int				/* 0 success, otherwise REG_something */
364 regcomp(regex_t * __restrict preg,
365 	const char * __restrict pattern,
366 	int cflags)
367 {
368 
369 	return (regcomp_internal(preg, pattern, cflags, 0));
370 }
371 
372 #ifndef LIBREGEX
373 /*
374  * Legacy interface that requires more lax escaping behavior.
375  */
376 int
377 freebsd12_regcomp(regex_t * __restrict preg,
378 	const char * __restrict pattern,
379 	int cflags, int pflags)
380 {
381 
382 	return (regcomp_internal(preg, pattern, cflags, PFLAG_LEGACY_ESC));
383 }
384 
385 __sym_compat(regcomp, freebsd12_regcomp, FBSD_1.0);
386 #endif	/* !LIBREGEX */
387 
388 /*
389  - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op,
390  - return whether we should terminate or not
391  == static bool p_ere_exp(struct parse *p);
392  */
393 static bool
394 p_ere_exp(struct parse *p, struct branchc *bc)
395 {
396 	char c;
397 	wint_t wc;
398 	sopno pos;
399 	int count;
400 	int count2;
401 #ifdef LIBREGEX
402 	int i;
403 	int handled;
404 #endif
405 	sopno subno;
406 	int wascaret = 0;
407 
408 	(void)bc;
409 	assert(MORE());		/* caller should have ensured this */
410 	c = GETNEXT();
411 
412 #ifdef LIBREGEX
413 	handled = 0;
414 #endif
415 	pos = HERE();
416 	switch (c) {
417 	case '(':
418 		(void)REQUIRE(MORE(), REG_EPAREN);
419 		p->g->nsub++;
420 		subno = p->g->nsub;
421 		if (subno < NPAREN)
422 			p->pbegin[subno] = HERE();
423 		EMIT(OLPAREN, subno);
424 		if (!SEE(')'))
425 			p_re(p, ')', IGN);
426 		if (subno < NPAREN) {
427 			p->pend[subno] = HERE();
428 			assert(p->pend[subno] != 0);
429 		}
430 		EMIT(ORPAREN, subno);
431 		(void)MUSTEAT(')', REG_EPAREN);
432 		break;
433 #ifndef POSIX_MISTAKE
434 	case ')':		/* happens only if no current unmatched ( */
435 		/*
436 		 * You may ask, why the ifndef?  Because I didn't notice
437 		 * this until slightly too late for 1003.2, and none of the
438 		 * other 1003.2 regular-expression reviewers noticed it at
439 		 * all.  So an unmatched ) is legal POSIX, at least until
440 		 * we can get it fixed.
441 		 */
442 		SETERROR(REG_EPAREN);
443 		break;
444 #endif
445 	case '^':
446 		EMIT(OBOL, 0);
447 		p->g->iflags |= USEBOL;
448 		p->g->nbol++;
449 		wascaret = 1;
450 		break;
451 	case '$':
452 		EMIT(OEOL, 0);
453 		p->g->iflags |= USEEOL;
454 		p->g->neol++;
455 		break;
456 	case '|':
457 		SETERROR(REG_EMPTY);
458 		break;
459 	case '*':
460 	case '+':
461 	case '?':
462 	case '{':
463 		SETERROR(REG_BADRPT);
464 		break;
465 	case '.':
466 		if (p->g->cflags&REG_NEWLINE)
467 			nonnewline(p);
468 		else
469 			EMIT(OANY, 0);
470 		break;
471 	case '[':
472 		p_bracket(p);
473 		break;
474 	case '\\':
475 		(void)REQUIRE(MORE(), REG_EESCAPE);
476 		wc = WGETNEXT();
477 #ifdef LIBREGEX
478 		if (p->gnuext) {
479 			handled = 1;
480 			switch (wc) {
481 			case '`':
482 				EMIT(OBOS, 0);
483 				break;
484 			case '\'':
485 				EMIT(OEOS, 0);
486 				break;
487 			case 'B':
488 				EMIT(ONWBND, 0);
489 				break;
490 			case 'b':
491 				EMIT(OWBND, 0);
492 				break;
493 			case 'W':
494 			case 'w':
495 			case 'S':
496 			case 's':
497 				p_b_pseudoclass(p, wc);
498 				break;
499 			case '1':
500 			case '2':
501 			case '3':
502 			case '4':
503 			case '5':
504 			case '6':
505 			case '7':
506 			case '8':
507 			case '9':
508 				i = wc - '0';
509 				assert(i < NPAREN);
510 				if (p->pend[i] != 0) {
511 					assert(i <= p->g->nsub);
512 					EMIT(OBACK_, i);
513 					assert(p->pbegin[i] != 0);
514 					assert(OP(p->strip[p->pbegin[i]]) == OLPAREN);
515 					assert(OP(p->strip[p->pend[i]]) == ORPAREN);
516 					(void) dupl(p, p->pbegin[i]+1, p->pend[i]);
517 					EMIT(O_BACK, i);
518 				} else
519 					SETERROR(REG_ESUBREG);
520 				p->g->backrefs = 1;
521 				break;
522 			default:
523 				handled = 0;
524 			}
525 			/* Don't proceed to the POSIX bits if we've already handled it */
526 			if (handled)
527 				break;
528 		}
529 #endif
530 		switch (wc) {
531 		case '<':
532 			EMIT(OBOW, 0);
533 			break;
534 		case '>':
535 			EMIT(OEOW, 0);
536 			break;
537 		default:
538 			if (may_escape(p, wc))
539 				ordinary(p, wc);
540 			else
541 				SETERROR(REG_EESCAPE);
542 			break;
543 		}
544 		break;
545 	default:
546 		if (p->error != 0)
547 			return (false);
548 		p->next--;
549 		wc = WGETNEXT();
550 		ordinary(p, wc);
551 		break;
552 	}
553 
554 	if (!MORE())
555 		return (false);
556 	c = PEEK();
557 	/* we call { a repetition if followed by a digit */
558 	if (!( c == '*' || c == '+' || c == '?' || c == '{'))
559 		return (false);		/* no repetition, we're done */
560 	else if (c == '{')
561 		(void)REQUIRE(MORE2() && \
562 		    (isdigit((uch)PEEK2()) || PEEK2() == ','), REG_BADRPT);
563 	NEXT();
564 
565 	(void)REQUIRE(!wascaret, REG_BADRPT);
566 	switch (c) {
567 	case '*':	/* implemented as +? */
568 		/* this case does not require the (y|) trick, noKLUDGE */
569 		INSERT(OPLUS_, pos);
570 		ASTERN(O_PLUS, pos);
571 		INSERT(OQUEST_, pos);
572 		ASTERN(O_QUEST, pos);
573 		break;
574 	case '+':
575 		INSERT(OPLUS_, pos);
576 		ASTERN(O_PLUS, pos);
577 		break;
578 	case '?':
579 		/* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
580 		INSERT(OCH_, pos);		/* offset slightly wrong */
581 		ASTERN(OOR1, pos);		/* this one's right */
582 		AHEAD(pos);			/* fix the OCH_ */
583 		EMIT(OOR2, 0);			/* offset very wrong... */
584 		AHEAD(THERE());			/* ...so fix it */
585 		ASTERN(O_CH, THERETHERE());
586 		break;
587 	case '{':
588 		count = p_count(p);
589 		if (EAT(',')) {
590 			if (isdigit((uch)PEEK())) {
591 				count2 = p_count(p);
592 				(void)REQUIRE(count <= count2, REG_BADBR);
593 			} else		/* single number with comma */
594 				count2 = INFINITY;
595 		} else		/* just a single number */
596 			count2 = count;
597 		repeat(p, pos, count, count2);
598 		if (!EAT('}')) {	/* error heuristics */
599 			while (MORE() && PEEK() != '}')
600 				NEXT();
601 			(void)REQUIRE(MORE(), REG_EBRACE);
602 			SETERROR(REG_BADBR);
603 		}
604 		break;
605 	}
606 
607 	if (!MORE())
608 		return (false);
609 	c = PEEK();
610 	if (!( c == '*' || c == '+' || c == '?' ||
611 				(c == '{' && MORE2() && isdigit((uch)PEEK2())) ) )
612 		return (false);
613 	SETERROR(REG_BADRPT);
614 	return (false);
615 }
616 
617 /*
618  - p_str - string (no metacharacters) "parser"
619  == static void p_str(struct parse *p);
620  */
621 static void
622 p_str(struct parse *p)
623 {
624 	(void)REQUIRE(MORE(), REG_EMPTY);
625 	while (MORE())
626 		ordinary(p, WGETNEXT());
627 }
628 
629 /*
630  * Eat consecutive branch delimiters for the kind of expression that we are
631  * parsing, return the number of delimiters that we ate.
632  */
633 static int
634 p_branch_eat_delim(struct parse *p, struct branchc *bc)
635 {
636 	int nskip;
637 
638 	(void)bc;
639 	nskip = 0;
640 	while (EATSPEC('|'))
641 		++nskip;
642 	return (nskip);
643 }
644 
645 /*
646  * Insert necessary branch book-keeping operations. This emits a
647  * bogus 'next' offset, since we still have more to parse
648  */
649 static void
650 p_branch_ins_offset(struct parse *p, struct branchc *bc)
651 {
652 
653 	if (bc->nbranch == 0) {
654 		INSERT(OCH_, bc->start);	/* offset is wrong */
655 		bc->fwd = bc->start;
656 		bc->back = bc->start;
657 	}
658 
659 	ASTERN(OOR1, bc->back);
660 	bc->back = THERE();
661 	AHEAD(bc->fwd);			/* fix previous offset */
662 	bc->fwd = HERE();
663 	EMIT(OOR2, 0);			/* offset is very wrong */
664 	++bc->nbranch;
665 }
666 
667 /*
668  * Fix the offset of the tail branch, if we actually had any branches.
669  * This is to correct the bogus placeholder offset that we use.
670  */
671 static void
672 p_branch_fix_tail(struct parse *p, struct branchc *bc)
673 {
674 
675 	/* Fix bogus offset at the tail if we actually have branches */
676 	if (bc->nbranch > 0) {
677 		AHEAD(bc->fwd);
678 		ASTERN(O_CH, bc->back);
679 	}
680 }
681 
682 /*
683  * Signal to the parser that an empty branch has been encountered; this will,
684  * in the future, be used to allow for more permissive behavior with empty
685  * branches. The return value should indicate whether parsing may continue
686  * or not.
687  */
688 static bool
689 p_branch_empty(struct parse *p, struct branchc *bc)
690 {
691 
692 	(void)bc;
693 	SETERROR(REG_EMPTY);
694 	return (false);
695 }
696 
697 /*
698  * Take care of any branching requirements. This includes inserting the
699  * appropriate branching instructions as well as eating all of the branch
700  * delimiters until we either run out of pattern or need to parse more pattern.
701  */
702 static bool
703 p_branch_do(struct parse *p, struct branchc *bc)
704 {
705 	int ate = 0;
706 
707 	ate = p_branch_eat_delim(p, bc);
708 	if (ate == 0)
709 		return (false);
710 	else if ((ate > 1 || (bc->outer && !MORE())) && !p_branch_empty(p, bc))
711 		/*
712 		 * Halt parsing only if we have an empty branch and p_branch_empty
713 		 * indicates that we must not continue. In the future, this will not
714 		 * necessarily be an error.
715 		 */
716 		return (false);
717 	p_branch_ins_offset(p, bc);
718 
719 	return (true);
720 }
721 
722 static void
723 p_bre_pre_parse(struct parse *p, struct branchc *bc)
724 {
725 
726 	(void) bc;
727 	/*
728 	 * Does not move cleanly into expression parser because of
729 	 * ordinary interpration of * at the beginning position of
730 	 * an expression.
731 	 */
732 	if (EAT('^')) {
733 		EMIT(OBOL, 0);
734 		p->g->iflags |= USEBOL;
735 		p->g->nbol++;
736 	}
737 }
738 
739 static void
740 p_bre_post_parse(struct parse *p, struct branchc *bc)
741 {
742 
743 	/* Expression is terminating due to EOL token */
744 	if (bc->terminate) {
745 		DROP(1);
746 		EMIT(OEOL, 0);
747 		p->g->iflags |= USEEOL;
748 		p->g->neol++;
749 	}
750 }
751 
752 /*
753  - p_re - Top level parser, concatenation and BRE anchoring
754  == static void p_re(struct parse *p, int end1, int end2);
755  * Giving end1 as OUT essentially eliminates the end1/end2 check.
756  *
757  * This implementation is a bit of a kludge, in that a trailing $ is first
758  * taken as an ordinary character and then revised to be an anchor.
759  * The amount of lookahead needed to avoid this kludge is excessive.
760  */
761 static void
762 p_re(struct parse *p,
763 	int end1,	/* first terminating character */
764 	int end2)	/* second terminating character; ignored for EREs */
765 {
766 	struct branchc bc;
767 
768 	bc.nbranch = 0;
769 	if (end1 == OUT && end2 == OUT)
770 		bc.outer = true;
771 	else
772 		bc.outer = false;
773 #define	SEEEND()	(!p->bre ? SEE(end1) : SEETWO(end1, end2))
774 	for (;;) {
775 		bc.start = HERE();
776 		bc.nchain = 0;
777 		bc.terminate = false;
778 		if (p->pre_parse != NULL)
779 			p->pre_parse(p, &bc);
780 		while (MORE() && (!p->allowbranch || !SEESPEC('|')) && !SEEEND()) {
781 			bc.terminate = p->parse_expr(p, &bc);
782 			++bc.nchain;
783 		}
784 		if (p->post_parse != NULL)
785 			p->post_parse(p, &bc);
786 		(void) REQUIRE(p->gnuext || HERE() != bc.start, REG_EMPTY);
787 #ifdef LIBREGEX
788 		if (HERE() == bc.start && !p_branch_empty(p, &bc))
789 			break;
790 #endif
791 		if (!p->allowbranch)
792 			break;
793 		/*
794 		 * p_branch_do's return value indicates whether we should
795 		 * continue parsing or not. This is both for correctness and
796 		 * a slight optimization, because it will check if we've
797 		 * encountered an empty branch or the end of the string
798 		 * immediately following a branch delimiter.
799 		 */
800 		if (!p_branch_do(p, &bc))
801 			break;
802 	}
803 #undef SEE_END
804 	if (p->allowbranch)
805 		p_branch_fix_tail(p, &bc);
806 	assert(!MORE() || SEE(end1));
807 }
808 
809 /*
810  - p_simp_re - parse a simple RE, an atom possibly followed by a repetition
811  == static bool p_simp_re(struct parse *p, struct branchc *bc);
812  */
813 static bool			/* was the simple RE an unbackslashed $? */
814 p_simp_re(struct parse *p, struct branchc *bc)
815 {
816 	int c;
817 	int cc;			/* convenient/control character */
818 	int count;
819 	int count2;
820 	sopno pos;
821 	bool handled;
822 	int i;
823 	wint_t wc;
824 	sopno subno;
825 #	define	BACKSL	(1<<CHAR_BIT)
826 
827 	pos = HERE();		/* repetition op, if any, covers from here */
828 	handled = false;
829 
830 	assert(MORE());		/* caller should have ensured this */
831 	c = GETNEXT();
832 	if (c == '\\') {
833 		(void)REQUIRE(MORE(), REG_EESCAPE);
834 		cc = GETNEXT();
835 		c = BACKSL | cc;
836 #ifdef LIBREGEX
837 		if (p->gnuext) {
838 			handled = true;
839 			switch (c) {
840 			case BACKSL|'`':
841 				EMIT(OBOS, 0);
842 				break;
843 			case BACKSL|'\'':
844 				EMIT(OEOS, 0);
845 				break;
846 			case BACKSL|'B':
847 				EMIT(ONWBND, 0);
848 				break;
849 			case BACKSL|'b':
850 				EMIT(OWBND, 0);
851 				break;
852 			case BACKSL|'W':
853 			case BACKSL|'w':
854 			case BACKSL|'S':
855 			case BACKSL|'s':
856 				p_b_pseudoclass(p, cc);
857 				break;
858 			default:
859 				handled = false;
860 			}
861 		}
862 #endif
863 	}
864 	if (!handled) {
865 		switch (c) {
866 		case '.':
867 			if (p->g->cflags&REG_NEWLINE)
868 				nonnewline(p);
869 			else
870 				EMIT(OANY, 0);
871 			break;
872 		case '[':
873 			p_bracket(p);
874 			break;
875 		case BACKSL|'<':
876 			EMIT(OBOW, 0);
877 			break;
878 		case BACKSL|'>':
879 			EMIT(OEOW, 0);
880 			break;
881 		case BACKSL|'{':
882 			SETERROR(REG_BADRPT);
883 			break;
884 		case BACKSL|'(':
885 			p->g->nsub++;
886 			subno = p->g->nsub;
887 			if (subno < NPAREN)
888 				p->pbegin[subno] = HERE();
889 			EMIT(OLPAREN, subno);
890 			/* the MORE here is an error heuristic */
891 			if (MORE() && !SEETWO('\\', ')'))
892 				p_re(p, '\\', ')');
893 			if (subno < NPAREN) {
894 				p->pend[subno] = HERE();
895 				assert(p->pend[subno] != 0);
896 			}
897 			EMIT(ORPAREN, subno);
898 			(void)REQUIRE(EATTWO('\\', ')'), REG_EPAREN);
899 			break;
900 		case BACKSL|')':	/* should not get here -- must be user */
901 			SETERROR(REG_EPAREN);
902 			break;
903 		case BACKSL|'1':
904 		case BACKSL|'2':
905 		case BACKSL|'3':
906 		case BACKSL|'4':
907 		case BACKSL|'5':
908 		case BACKSL|'6':
909 		case BACKSL|'7':
910 		case BACKSL|'8':
911 		case BACKSL|'9':
912 			i = (c&~BACKSL) - '0';
913 			assert(i < NPAREN);
914 			if (p->pend[i] != 0) {
915 				assert(i <= p->g->nsub);
916 				EMIT(OBACK_, i);
917 				assert(p->pbegin[i] != 0);
918 				assert(OP(p->strip[p->pbegin[i]]) == OLPAREN);
919 				assert(OP(p->strip[p->pend[i]]) == ORPAREN);
920 				(void) dupl(p, p->pbegin[i]+1, p->pend[i]);
921 				EMIT(O_BACK, i);
922 			} else
923 				SETERROR(REG_ESUBREG);
924 			p->g->backrefs = 1;
925 			break;
926 		case '*':
927 			/*
928 			 * Ordinary if used as the first character beyond BOL anchor of
929 			 * a (sub-)expression, counts as a bad repetition operator if it
930 			 * appears otherwise.
931 			 */
932 			(void)REQUIRE(bc->nchain == 0, REG_BADRPT);
933 			/* FALLTHROUGH */
934 		default:
935 			if (p->error != 0)
936 				return (false);	/* Definitely not $... */
937 			p->next--;
938 			wc = WGETNEXT();
939 			if ((c & BACKSL) == 0 || may_escape(p, wc))
940 				ordinary(p, wc);
941 			else
942 				SETERROR(REG_EESCAPE);
943 			break;
944 		}
945 	}
946 
947 	if (EAT('*')) {		/* implemented as +? */
948 		/* this case does not require the (y|) trick, noKLUDGE */
949 		INSERT(OPLUS_, pos);
950 		ASTERN(O_PLUS, pos);
951 		INSERT(OQUEST_, pos);
952 		ASTERN(O_QUEST, pos);
953 #ifdef LIBREGEX
954 	} else if (p->gnuext && EATTWO('\\', '?')) {
955 		INSERT(OQUEST_, pos);
956 		ASTERN(O_QUEST, pos);
957 	} else if (p->gnuext && EATTWO('\\', '+')) {
958 		INSERT(OPLUS_, pos);
959 		ASTERN(O_PLUS, pos);
960 #endif
961 	} else if (EATTWO('\\', '{')) {
962 		count = p_count(p);
963 		if (EAT(',')) {
964 			if (MORE() && isdigit((uch)PEEK())) {
965 				count2 = p_count(p);
966 				(void)REQUIRE(count <= count2, REG_BADBR);
967 			} else		/* single number with comma */
968 				count2 = INFINITY;
969 		} else		/* just a single number */
970 			count2 = count;
971 		repeat(p, pos, count, count2);
972 		if (!EATTWO('\\', '}')) {	/* error heuristics */
973 			while (MORE() && !SEETWO('\\', '}'))
974 				NEXT();
975 			(void)REQUIRE(MORE(), REG_EBRACE);
976 			SETERROR(REG_BADBR);
977 		}
978 	} else if (c == '$')     /* $ (but not \$) ends it */
979 		return (true);
980 
981 	return (false);
982 }
983 
984 /*
985  - p_count - parse a repetition count
986  == static int p_count(struct parse *p);
987  */
988 static int			/* the value */
989 p_count(struct parse *p)
990 {
991 	int count = 0;
992 	int ndigits = 0;
993 
994 	while (MORE() && isdigit((uch)PEEK()) && count <= DUPMAX) {
995 		count = count*10 + (GETNEXT() - '0');
996 		ndigits++;
997 	}
998 
999 	(void)REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR);
1000 	return(count);
1001 }
1002 
1003 /*
1004  - p_bracket - parse a bracketed character list
1005  == static void p_bracket(struct parse *p);
1006  */
1007 static void
1008 p_bracket(struct parse *p)
1009 {
1010 	cset *cs;
1011 	wint_t ch;
1012 
1013 	/* Dept of Truly Sickening Special-Case Kludges */
1014 	if (p->end - p->next > 5) {
1015 		if (strncmp(p->next, "[:<:]]", 6) == 0) {
1016 			EMIT(OBOW, 0);
1017 			NEXTn(6);
1018 			return;
1019 		}
1020 		if (strncmp(p->next, "[:>:]]", 6) == 0) {
1021 			EMIT(OEOW, 0);
1022 			NEXTn(6);
1023 			return;
1024 		}
1025 	}
1026 
1027 	if ((cs = allocset(p)) == NULL)
1028 		return;
1029 
1030 	if (p->g->cflags&REG_ICASE)
1031 		cs->icase = 1;
1032 	if (EAT('^'))
1033 		cs->invert = 1;
1034 	if (EAT(']'))
1035 		CHadd(p, cs, ']');
1036 	else if (EAT('-'))
1037 		CHadd(p, cs, '-');
1038 	while (MORE() && PEEK() != ']' && !SEETWO('-', ']'))
1039 		p_b_term(p, cs);
1040 	if (EAT('-'))
1041 		CHadd(p, cs, '-');
1042 	(void)MUSTEAT(']', REG_EBRACK);
1043 
1044 	if (p->error != 0)	/* don't mess things up further */
1045 		return;
1046 
1047 	if (cs->invert && p->g->cflags&REG_NEWLINE)
1048 		cs->bmp['\n' >> 3] |= 1 << ('\n' & 7);
1049 
1050 	if ((ch = singleton(cs)) != OUT) {	/* optimize singleton sets */
1051 		ordinary(p, ch);
1052 		freeset(p, cs);
1053 	} else
1054 		EMIT(OANYOF, (int)(cs - p->g->sets));
1055 }
1056 
1057 static int
1058 p_range_cmp(wchar_t c1, wchar_t c2)
1059 {
1060 #ifndef LIBREGEX
1061 	return __wcollate_range_cmp(c1, c2);
1062 #else
1063 	/* Copied from libc/collate __wcollate_range_cmp */
1064 	wchar_t s1[2], s2[2];
1065 
1066 	s1[0] = c1;
1067 	s1[1] = L'\0';
1068 	s2[0] = c2;
1069 	s2[1] = L'\0';
1070 	return (wcscoll(s1, s2));
1071 #endif
1072 }
1073 
1074 /*
1075  - p_b_term - parse one term of a bracketed character list
1076  == static void p_b_term(struct parse *p, cset *cs);
1077  */
1078 static void
1079 p_b_term(struct parse *p, cset *cs)
1080 {
1081 	char c;
1082 	wint_t start, finish;
1083 	wint_t i;
1084 #ifndef LIBREGEX
1085 	struct xlocale_collate *table =
1086 		(struct xlocale_collate*)__get_locale()->components[XLC_COLLATE];
1087 #endif
1088 	/* classify what we've got */
1089 	switch ((MORE()) ? PEEK() : '\0') {
1090 	case '[':
1091 		c = (MORE2()) ? PEEK2() : '\0';
1092 		break;
1093 	case '-':
1094 		SETERROR(REG_ERANGE);
1095 		return;			/* NOTE RETURN */
1096 	default:
1097 		c = '\0';
1098 		break;
1099 	}
1100 
1101 	switch (c) {
1102 	case ':':		/* character class */
1103 		NEXT2();
1104 		(void)REQUIRE(MORE(), REG_EBRACK);
1105 		c = PEEK();
1106 		(void)REQUIRE(c != '-' && c != ']', REG_ECTYPE);
1107 		p_b_cclass(p, cs);
1108 		(void)REQUIRE(MORE(), REG_EBRACK);
1109 		(void)REQUIRE(EATTWO(':', ']'), REG_ECTYPE);
1110 		break;
1111 	case '=':		/* equivalence class */
1112 		NEXT2();
1113 		(void)REQUIRE(MORE(), REG_EBRACK);
1114 		c = PEEK();
1115 		(void)REQUIRE(c != '-' && c != ']', REG_ECOLLATE);
1116 		p_b_eclass(p, cs);
1117 		(void)REQUIRE(MORE(), REG_EBRACK);
1118 		(void)REQUIRE(EATTWO('=', ']'), REG_ECOLLATE);
1119 		break;
1120 	default:		/* symbol, ordinary character, or range */
1121 		start = p_b_symbol(p);
1122 		if (SEE('-') && MORE2() && PEEK2() != ']') {
1123 			/* range */
1124 			NEXT();
1125 			if (EAT('-'))
1126 				finish = '-';
1127 			else
1128 				finish = p_b_symbol(p);
1129 		} else
1130 			finish = start;
1131 		if (start == finish)
1132 			CHadd(p, cs, start);
1133 		else {
1134 #ifndef LIBREGEX
1135 			if (table->__collate_load_error || MB_CUR_MAX > 1) {
1136 #else
1137 			if (MB_CUR_MAX > 1) {
1138 #endif
1139 				(void)REQUIRE(start <= finish, REG_ERANGE);
1140 				CHaddrange(p, cs, start, finish);
1141 			} else {
1142 				(void)REQUIRE(p_range_cmp(start, finish) <= 0, REG_ERANGE);
1143 				for (i = 0; i <= UCHAR_MAX; i++) {
1144 					if (p_range_cmp(start, i) <= 0 &&
1145 					    p_range_cmp(i, finish) <= 0 )
1146 						CHadd(p, cs, i);
1147 				}
1148 			}
1149 		}
1150 		break;
1151 	}
1152 }
1153 
1154 /*
1155  - p_b_pseudoclass - parse a pseudo-class (\w, \W, \s, \S)
1156  == static int p_b_pseudoclass(struct parse *p, char c)
1157  */
1158 static int
1159 p_b_pseudoclass(struct parse *p, char c) {
1160 	cset *cs;
1161 
1162 	if ((cs = allocset(p)) == NULL)
1163 		return(0);
1164 
1165 	if (p->g->cflags&REG_ICASE)
1166 		cs->icase = 1;
1167 
1168 	switch (c) {
1169 	case 'W':
1170 		cs->invert = 1;
1171 		/* PASSTHROUGH */
1172 	case 'w':
1173 		p_b_cclass_named(p, cs, "alnum");
1174 		break;
1175 	case 'S':
1176 		cs->invert = 1;
1177 		/* PASSTHROUGH */
1178 	case 's':
1179 		p_b_cclass_named(p, cs, "space");
1180 		break;
1181 	default:
1182 		return(0);
1183 	}
1184 
1185 	EMIT(OANYOF, (int)(cs - p->g->sets));
1186 	return(1);
1187 }
1188 
1189 /*
1190  - p_b_cclass - parse a character-class name and deal with it
1191  == static void p_b_cclass(struct parse *p, cset *cs);
1192  */
1193 static void
1194 p_b_cclass(struct parse *p, cset *cs)
1195 {
1196 	const char *sp = p->next;
1197 	size_t len;
1198 	char clname[16];
1199 
1200 	while (MORE() && isalpha((uch)PEEK()))
1201 		NEXT();
1202 	len = p->next - sp;
1203 	if (len >= sizeof(clname) - 1) {
1204 		SETERROR(REG_ECTYPE);
1205 		return;
1206 	}
1207 	memcpy(clname, sp, len);
1208 	clname[len] = '\0';
1209 
1210 	p_b_cclass_named(p, cs, clname);
1211 }
1212 /*
1213  - p_b_cclass_named - deal with a named character class
1214  == static void p_b_cclass_named(struct parse *p, cset *cs, const char []);
1215  */
1216 static void
1217 p_b_cclass_named(struct parse *p, cset *cs, const char clname[]) {
1218 	wctype_t wct;
1219 
1220 	if ((wct = wctype(clname)) == 0) {
1221 		SETERROR(REG_ECTYPE);
1222 		return;
1223 	}
1224 	CHaddtype(p, cs, wct);
1225 }
1226 
1227 /*
1228  - p_b_eclass - parse an equivalence-class name and deal with it
1229  == static void p_b_eclass(struct parse *p, cset *cs);
1230  *
1231  * This implementation is incomplete. xxx
1232  */
1233 static void
1234 p_b_eclass(struct parse *p, cset *cs)
1235 {
1236 	wint_t c;
1237 
1238 	c = p_b_coll_elem(p, '=');
1239 	CHadd(p, cs, c);
1240 }
1241 
1242 /*
1243  - p_b_symbol - parse a character or [..]ed multicharacter collating symbol
1244  == static wint_t p_b_symbol(struct parse *p);
1245  */
1246 static wint_t			/* value of symbol */
1247 p_b_symbol(struct parse *p)
1248 {
1249 	wint_t value;
1250 
1251 	(void)REQUIRE(MORE(), REG_EBRACK);
1252 	if (!EATTWO('[', '.'))
1253 		return(WGETNEXT());
1254 
1255 	/* collating symbol */
1256 	value = p_b_coll_elem(p, '.');
1257 	(void)REQUIRE(EATTWO('.', ']'), REG_ECOLLATE);
1258 	return(value);
1259 }
1260 
1261 /*
1262  - p_b_coll_elem - parse a collating-element name and look it up
1263  == static wint_t p_b_coll_elem(struct parse *p, wint_t endc);
1264  */
1265 static wint_t			/* value of collating element */
1266 p_b_coll_elem(struct parse *p,
1267 	wint_t endc)		/* name ended by endc,']' */
1268 {
1269 	const char *sp = p->next;
1270 	struct cname *cp;
1271 	mbstate_t mbs;
1272 	wchar_t wc;
1273 	size_t clen, len;
1274 
1275 	while (MORE() && !SEETWO(endc, ']'))
1276 		NEXT();
1277 	if (!MORE()) {
1278 		SETERROR(REG_EBRACK);
1279 		return(0);
1280 	}
1281 	len = p->next - sp;
1282 	for (cp = cnames; cp->name != NULL; cp++)
1283 		if (strncmp(cp->name, sp, len) == 0 && strlen(cp->name) == len)
1284 			return(cp->code);	/* known name */
1285 	memset(&mbs, 0, sizeof(mbs));
1286 	if ((clen = mbrtowc(&wc, sp, len, &mbs)) == len)
1287 		return (wc);			/* single character */
1288 	else if (clen == (size_t)-1 || clen == (size_t)-2)
1289 		SETERROR(REG_ILLSEQ);
1290 	else
1291 		SETERROR(REG_ECOLLATE);		/* neither */
1292 	return(0);
1293 }
1294 
1295 /*
1296  - may_escape - determine whether 'ch' is escape-able in the current context
1297  == static int may_escape(struct parse *p, const wint_t ch)
1298  */
1299 static bool
1300 may_escape(struct parse *p, const wint_t ch)
1301 {
1302 
1303 	if ((p->pflags & PFLAG_LEGACY_ESC) != 0)
1304 		return (true);
1305 	if (isalpha(ch) || ch == '\'' || ch == '`')
1306 		return (false);
1307 	return (true);
1308 #ifdef NOTYET
1309 	/*
1310 	 * Build a whitelist of characters that may be escaped to produce an
1311 	 * ordinary in the current context. This assumes that these have not
1312 	 * been otherwise interpreted as a special character. Escaping an
1313 	 * ordinary character yields undefined results according to
1314 	 * IEEE 1003.1-2008. Some extensions (notably, some GNU extensions) take
1315 	 * advantage of this and use escaped ordinary characters to provide
1316 	 * special meaning, e.g. \b, \B, \w, \W, \s, \S.
1317 	 */
1318 	switch(ch) {
1319 	case '|':
1320 	case '+':
1321 	case '?':
1322 		/* The above characters may not be escaped in BREs */
1323 		if (!(p->g->cflags&REG_EXTENDED))
1324 			return (false);
1325 		/* Fallthrough */
1326 	case '(':
1327 	case ')':
1328 	case '{':
1329 	case '}':
1330 	case '.':
1331 	case '[':
1332 	case ']':
1333 	case '\\':
1334 	case '*':
1335 	case '^':
1336 	case '$':
1337 		return (true);
1338 	default:
1339 		return (false);
1340 	}
1341 #endif
1342 }
1343 
1344 /*
1345  - othercase - return the case counterpart of an alphabetic
1346  == static wint_t othercase(wint_t ch);
1347  */
1348 static wint_t			/* if no counterpart, return ch */
1349 othercase(wint_t ch)
1350 {
1351 	assert(iswalpha(ch));
1352 	if (iswupper(ch))
1353 		return(towlower(ch));
1354 	else if (iswlower(ch))
1355 		return(towupper(ch));
1356 	else			/* peculiar, but could happen */
1357 		return(ch);
1358 }
1359 
1360 /*
1361  - bothcases - emit a dualcase version of a two-case character
1362  == static void bothcases(struct parse *p, wint_t ch);
1363  *
1364  * Boy, is this implementation ever a kludge...
1365  */
1366 static void
1367 bothcases(struct parse *p, wint_t ch)
1368 {
1369 	const char *oldnext = p->next;
1370 	const char *oldend = p->end;
1371 	char bracket[3 + MB_LEN_MAX];
1372 	size_t n;
1373 	mbstate_t mbs;
1374 
1375 	assert(othercase(ch) != ch);	/* p_bracket() would recurse */
1376 	p->next = bracket;
1377 	memset(&mbs, 0, sizeof(mbs));
1378 	n = wcrtomb(bracket, ch, &mbs);
1379 	assert(n != (size_t)-1);
1380 	bracket[n] = ']';
1381 	bracket[n + 1] = '\0';
1382 	p->end = bracket+n+1;
1383 	p_bracket(p);
1384 	assert(p->next == p->end);
1385 	p->next = oldnext;
1386 	p->end = oldend;
1387 }
1388 
1389 /*
1390  - ordinary - emit an ordinary character
1391  == static void ordinary(struct parse *p, wint_t ch);
1392  */
1393 static void
1394 ordinary(struct parse *p, wint_t ch)
1395 {
1396 	cset *cs;
1397 
1398 	if ((p->g->cflags&REG_ICASE) && iswalpha(ch) && othercase(ch) != ch)
1399 		bothcases(p, ch);
1400 	else if ((ch & OPDMASK) == ch)
1401 		EMIT(OCHAR, ch);
1402 	else {
1403 		/*
1404 		 * Kludge: character is too big to fit into an OCHAR operand.
1405 		 * Emit a singleton set.
1406 		 */
1407 		if ((cs = allocset(p)) == NULL)
1408 			return;
1409 		CHadd(p, cs, ch);
1410 		EMIT(OANYOF, (int)(cs - p->g->sets));
1411 	}
1412 }
1413 
1414 /*
1415  - nonnewline - emit REG_NEWLINE version of OANY
1416  == static void nonnewline(struct parse *p);
1417  *
1418  * Boy, is this implementation ever a kludge...
1419  */
1420 static void
1421 nonnewline(struct parse *p)
1422 {
1423 	const char *oldnext = p->next;
1424 	const char *oldend = p->end;
1425 	char bracket[4];
1426 
1427 	p->next = bracket;
1428 	p->end = bracket+3;
1429 	bracket[0] = '^';
1430 	bracket[1] = '\n';
1431 	bracket[2] = ']';
1432 	bracket[3] = '\0';
1433 	p_bracket(p);
1434 	assert(p->next == bracket+3);
1435 	p->next = oldnext;
1436 	p->end = oldend;
1437 }
1438 
1439 /*
1440  - repeat - generate code for a bounded repetition, recursively if needed
1441  == static void repeat(struct parse *p, sopno start, int from, int to);
1442  */
1443 static void
1444 repeat(struct parse *p,
1445 	sopno start,		/* operand from here to end of strip */
1446 	int from,		/* repeated from this number */
1447 	int to)			/* to this number of times (maybe INFINITY) */
1448 {
1449 	sopno finish = HERE();
1450 #	define	N	2
1451 #	define	INF	3
1452 #	define	REP(f, t)	((f)*8 + (t))
1453 #	define	MAP(n)	(((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N)
1454 	sopno copy;
1455 
1456 	if (p->error != 0)	/* head off possible runaway recursion */
1457 		return;
1458 
1459 	assert(from <= to);
1460 
1461 	switch (REP(MAP(from), MAP(to))) {
1462 	case REP(0, 0):			/* must be user doing this */
1463 		DROP(finish-start);	/* drop the operand */
1464 		break;
1465 	case REP(0, 1):			/* as x{1,1}? */
1466 	case REP(0, N):			/* as x{1,n}? */
1467 	case REP(0, INF):		/* as x{1,}? */
1468 		/* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
1469 		INSERT(OCH_, start);		/* offset is wrong... */
1470 		repeat(p, start+1, 1, to);
1471 		ASTERN(OOR1, start);
1472 		AHEAD(start);			/* ... fix it */
1473 		EMIT(OOR2, 0);
1474 		AHEAD(THERE());
1475 		ASTERN(O_CH, THERETHERE());
1476 		break;
1477 	case REP(1, 1):			/* trivial case */
1478 		/* done */
1479 		break;
1480 	case REP(1, N):			/* as x?x{1,n-1} */
1481 		/* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
1482 		INSERT(OCH_, start);
1483 		ASTERN(OOR1, start);
1484 		AHEAD(start);
1485 		EMIT(OOR2, 0);			/* offset very wrong... */
1486 		AHEAD(THERE());			/* ...so fix it */
1487 		ASTERN(O_CH, THERETHERE());
1488 		copy = dupl(p, start+1, finish+1);
1489 		assert(copy == finish+4);
1490 		repeat(p, copy, 1, to-1);
1491 		break;
1492 	case REP(1, INF):		/* as x+ */
1493 		INSERT(OPLUS_, start);
1494 		ASTERN(O_PLUS, start);
1495 		break;
1496 	case REP(N, N):			/* as xx{m-1,n-1} */
1497 		copy = dupl(p, start, finish);
1498 		repeat(p, copy, from-1, to-1);
1499 		break;
1500 	case REP(N, INF):		/* as xx{n-1,INF} */
1501 		copy = dupl(p, start, finish);
1502 		repeat(p, copy, from-1, to);
1503 		break;
1504 	default:			/* "can't happen" */
1505 		SETERROR(REG_ASSERT);	/* just in case */
1506 		break;
1507 	}
1508 }
1509 
1510 /*
1511  - wgetnext - helper function for WGETNEXT() macro. Gets the next wide
1512  - character from the parse struct, signals a REG_ILLSEQ error if the
1513  - character can't be converted. Returns the number of bytes consumed.
1514  */
1515 static wint_t
1516 wgetnext(struct parse *p)
1517 {
1518 	mbstate_t mbs;
1519 	wchar_t wc;
1520 	size_t n;
1521 
1522 	memset(&mbs, 0, sizeof(mbs));
1523 	n = mbrtowc(&wc, p->next, p->end - p->next, &mbs);
1524 	if (n == (size_t)-1 || n == (size_t)-2) {
1525 		SETERROR(REG_ILLSEQ);
1526 		return (0);
1527 	}
1528 	if (n == 0)
1529 		n = 1;
1530 	p->next += n;
1531 	return (wc);
1532 }
1533 
1534 /*
1535  - seterr - set an error condition
1536  == static int seterr(struct parse *p, int e);
1537  */
1538 static int			/* useless but makes type checking happy */
1539 seterr(struct parse *p, int e)
1540 {
1541 	if (p->error == 0)	/* keep earliest error condition */
1542 		p->error = e;
1543 	p->next = nuls;		/* try to bring things to a halt */
1544 	p->end = nuls;
1545 	return(0);		/* make the return value well-defined */
1546 }
1547 
1548 /*
1549  - allocset - allocate a set of characters for []
1550  == static cset *allocset(struct parse *p);
1551  */
1552 static cset *
1553 allocset(struct parse *p)
1554 {
1555 	cset *cs, *ncs;
1556 
1557 	ncs = reallocarray(p->g->sets, p->g->ncsets + 1, sizeof(*ncs));
1558 	if (ncs == NULL) {
1559 		SETERROR(REG_ESPACE);
1560 		return (NULL);
1561 	}
1562 	p->g->sets = ncs;
1563 	cs = &p->g->sets[p->g->ncsets++];
1564 	memset(cs, 0, sizeof(*cs));
1565 
1566 	return(cs);
1567 }
1568 
1569 /*
1570  - freeset - free a now-unused set
1571  == static void freeset(struct parse *p, cset *cs);
1572  */
1573 static void
1574 freeset(struct parse *p, cset *cs)
1575 {
1576 	cset *top = &p->g->sets[p->g->ncsets];
1577 
1578 	free(cs->wides);
1579 	free(cs->ranges);
1580 	free(cs->types);
1581 	memset(cs, 0, sizeof(*cs));
1582 	if (cs == top-1)	/* recover only the easy case */
1583 		p->g->ncsets--;
1584 }
1585 
1586 /*
1587  - singleton - Determine whether a set contains only one character,
1588  - returning it if so, otherwise returning OUT.
1589  */
1590 static wint_t
1591 singleton(cset *cs)
1592 {
1593 	wint_t i, s, n;
1594 
1595 	for (i = n = 0; i < NC; i++)
1596 		if (CHIN(cs, i)) {
1597 			n++;
1598 			s = i;
1599 		}
1600 	if (n == 1)
1601 		return (s);
1602 	if (cs->nwides == 1 && cs->nranges == 0 && cs->ntypes == 0 &&
1603 	    cs->icase == 0)
1604 		return (cs->wides[0]);
1605 	/* Don't bother handling the other cases. */
1606 	return (OUT);
1607 }
1608 
1609 /*
1610  - CHadd - add character to character set.
1611  */
1612 static void
1613 CHadd(struct parse *p, cset *cs, wint_t ch)
1614 {
1615 	wint_t nch, *newwides;
1616 	assert(ch >= 0);
1617 	if (ch < NC)
1618 		cs->bmp[ch >> 3] |= 1 << (ch & 7);
1619 	else {
1620 		newwides = reallocarray(cs->wides, cs->nwides + 1,
1621 		    sizeof(*cs->wides));
1622 		if (newwides == NULL) {
1623 			SETERROR(REG_ESPACE);
1624 			return;
1625 		}
1626 		cs->wides = newwides;
1627 		cs->wides[cs->nwides++] = ch;
1628 	}
1629 	if (cs->icase) {
1630 		if ((nch = towlower(ch)) < NC)
1631 			cs->bmp[nch >> 3] |= 1 << (nch & 7);
1632 		if ((nch = towupper(ch)) < NC)
1633 			cs->bmp[nch >> 3] |= 1 << (nch & 7);
1634 	}
1635 }
1636 
1637 /*
1638  - CHaddrange - add all characters in the range [min,max] to a character set.
1639  */
1640 static void
1641 CHaddrange(struct parse *p, cset *cs, wint_t min, wint_t max)
1642 {
1643 	crange *newranges;
1644 
1645 	for (; min < NC && min <= max; min++)
1646 		CHadd(p, cs, min);
1647 	if (min >= max)
1648 		return;
1649 	newranges = reallocarray(cs->ranges, cs->nranges + 1,
1650 	    sizeof(*cs->ranges));
1651 	if (newranges == NULL) {
1652 		SETERROR(REG_ESPACE);
1653 		return;
1654 	}
1655 	cs->ranges = newranges;
1656 	cs->ranges[cs->nranges].min = min;
1657 	cs->ranges[cs->nranges].max = max;
1658 	cs->nranges++;
1659 }
1660 
1661 /*
1662  - CHaddtype - add all characters of a certain type to a character set.
1663  */
1664 static void
1665 CHaddtype(struct parse *p, cset *cs, wctype_t wct)
1666 {
1667 	wint_t i;
1668 	wctype_t *newtypes;
1669 
1670 	for (i = 0; i < NC; i++)
1671 		if (iswctype(i, wct))
1672 			CHadd(p, cs, i);
1673 	newtypes = reallocarray(cs->types, cs->ntypes + 1,
1674 	    sizeof(*cs->types));
1675 	if (newtypes == NULL) {
1676 		SETERROR(REG_ESPACE);
1677 		return;
1678 	}
1679 	cs->types = newtypes;
1680 	cs->types[cs->ntypes++] = wct;
1681 }
1682 
1683 /*
1684  - dupl - emit a duplicate of a bunch of sops
1685  == static sopno dupl(struct parse *p, sopno start, sopno finish);
1686  */
1687 static sopno			/* start of duplicate */
1688 dupl(struct parse *p,
1689 	sopno start,		/* from here */
1690 	sopno finish)		/* to this less one */
1691 {
1692 	sopno ret = HERE();
1693 	sopno len = finish - start;
1694 
1695 	assert(finish >= start);
1696 	if (len == 0)
1697 		return(ret);
1698 	if (!enlarge(p, p->ssize + len)) /* this many unexpected additions */
1699 		return(ret);
1700 	(void) memcpy((char *)(p->strip + p->slen),
1701 		(char *)(p->strip + start), (size_t)len*sizeof(sop));
1702 	p->slen += len;
1703 	return(ret);
1704 }
1705 
1706 /*
1707  - doemit - emit a strip operator
1708  == static void doemit(struct parse *p, sop op, size_t opnd);
1709  *
1710  * It might seem better to implement this as a macro with a function as
1711  * hard-case backup, but it's just too big and messy unless there are
1712  * some changes to the data structures.  Maybe later.
1713  */
1714 static void
1715 doemit(struct parse *p, sop op, size_t opnd)
1716 {
1717 	/* avoid making error situations worse */
1718 	if (p->error != 0)
1719 		return;
1720 
1721 	/* deal with oversize operands ("can't happen", more or less) */
1722 	assert(opnd < 1<<OPSHIFT);
1723 
1724 	/* deal with undersized strip */
1725 	if (p->slen >= p->ssize)
1726 		if (!enlarge(p, (p->ssize+1) / 2 * 3))	/* +50% */
1727 			return;
1728 
1729 	/* finally, it's all reduced to the easy case */
1730 	p->strip[p->slen++] = SOP(op, opnd);
1731 }
1732 
1733 /*
1734  - doinsert - insert a sop into the strip
1735  == static void doinsert(struct parse *p, sop op, size_t opnd, sopno pos);
1736  */
1737 static void
1738 doinsert(struct parse *p, sop op, size_t opnd, sopno pos)
1739 {
1740 	sopno sn;
1741 	sop s;
1742 	int i;
1743 
1744 	/* avoid making error situations worse */
1745 	if (p->error != 0)
1746 		return;
1747 
1748 	sn = HERE();
1749 	EMIT(op, opnd);		/* do checks, ensure space */
1750 	assert(HERE() == sn+1);
1751 	s = p->strip[sn];
1752 
1753 	/* adjust paren pointers */
1754 	assert(pos > 0);
1755 	for (i = 1; i < NPAREN; i++) {
1756 		if (p->pbegin[i] >= pos) {
1757 			p->pbegin[i]++;
1758 		}
1759 		if (p->pend[i] >= pos) {
1760 			p->pend[i]++;
1761 		}
1762 	}
1763 
1764 	memmove((char *)&p->strip[pos+1], (char *)&p->strip[pos],
1765 						(HERE()-pos-1)*sizeof(sop));
1766 	p->strip[pos] = s;
1767 }
1768 
1769 /*
1770  - dofwd - complete a forward reference
1771  == static void dofwd(struct parse *p, sopno pos, sop value);
1772  */
1773 static void
1774 dofwd(struct parse *p, sopno pos, sop value)
1775 {
1776 	/* avoid making error situations worse */
1777 	if (p->error != 0)
1778 		return;
1779 
1780 	assert(value < 1<<OPSHIFT);
1781 	p->strip[pos] = OP(p->strip[pos]) | value;
1782 }
1783 
1784 /*
1785  - enlarge - enlarge the strip
1786  == static int enlarge(struct parse *p, sopno size);
1787  */
1788 static int
1789 enlarge(struct parse *p, sopno size)
1790 {
1791 	sop *sp;
1792 
1793 	if (p->ssize >= size)
1794 		return 1;
1795 
1796 	sp = reallocarray(p->strip, size, sizeof(sop));
1797 	if (sp == NULL) {
1798 		SETERROR(REG_ESPACE);
1799 		return 0;
1800 	}
1801 	p->strip = sp;
1802 	p->ssize = size;
1803 	return 1;
1804 }
1805 
1806 /*
1807  - stripsnug - compact the strip
1808  == static void stripsnug(struct parse *p, struct re_guts *g);
1809  */
1810 static void
1811 stripsnug(struct parse *p, struct re_guts *g)
1812 {
1813 	g->nstates = p->slen;
1814 	g->strip = reallocarray((char *)p->strip, p->slen, sizeof(sop));
1815 	if (g->strip == NULL) {
1816 		SETERROR(REG_ESPACE);
1817 		g->strip = p->strip;
1818 	}
1819 }
1820 
1821 /*
1822  - findmust - fill in must and mlen with longest mandatory literal string
1823  == static void findmust(struct parse *p, struct re_guts *g);
1824  *
1825  * This algorithm could do fancy things like analyzing the operands of |
1826  * for common subsequences.  Someday.  This code is simple and finds most
1827  * of the interesting cases.
1828  *
1829  * Note that must and mlen got initialized during setup.
1830  */
1831 static void
1832 findmust(struct parse *p, struct re_guts *g)
1833 {
1834 	sop *scan;
1835 	sop *start = NULL;
1836 	sop *newstart = NULL;
1837 	sopno newlen;
1838 	sop s;
1839 	char *cp;
1840 	int offset;
1841 	char buf[MB_LEN_MAX];
1842 	size_t clen;
1843 	mbstate_t mbs;
1844 
1845 	/* avoid making error situations worse */
1846 	if (p->error != 0)
1847 		return;
1848 
1849 	/*
1850 	 * It's not generally safe to do a ``char'' substring search on
1851 	 * multibyte character strings, but it's safe for at least
1852 	 * UTF-8 (see RFC 3629).
1853 	 */
1854 	if (MB_CUR_MAX > 1 &&
1855 	    strcmp(_CurrentRuneLocale->__encoding, "UTF-8") != 0)
1856 		return;
1857 
1858 	/* find the longest OCHAR sequence in strip */
1859 	newlen = 0;
1860 	offset = 0;
1861 	g->moffset = 0;
1862 	scan = g->strip + 1;
1863 	do {
1864 		s = *scan++;
1865 		switch (OP(s)) {
1866 		case OCHAR:		/* sequence member */
1867 			if (newlen == 0) {		/* new sequence */
1868 				memset(&mbs, 0, sizeof(mbs));
1869 				newstart = scan - 1;
1870 			}
1871 			clen = wcrtomb(buf, OPND(s), &mbs);
1872 			if (clen == (size_t)-1)
1873 				goto toohard;
1874 			newlen += clen;
1875 			break;
1876 		case OPLUS_:		/* things that don't break one */
1877 		case OLPAREN:
1878 		case ORPAREN:
1879 			break;
1880 		case OQUEST_:		/* things that must be skipped */
1881 		case OCH_:
1882 			offset = altoffset(scan, offset);
1883 			scan--;
1884 			do {
1885 				scan += OPND(s);
1886 				s = *scan;
1887 				/* assert() interferes w debug printouts */
1888 				if (OP(s) != (sop)O_QUEST &&
1889 				    OP(s) != (sop)O_CH && OP(s) != (sop)OOR2) {
1890 					g->iflags |= BAD;
1891 					return;
1892 				}
1893 			} while (OP(s) != (sop)O_QUEST && OP(s) != (sop)O_CH);
1894 			/* FALLTHROUGH */
1895 		case OBOW:		/* things that break a sequence */
1896 		case OEOW:
1897 		case OBOL:
1898 		case OEOL:
1899 		case OBOS:
1900 		case OEOS:
1901 		case OWBND:
1902 		case ONWBND:
1903 		case O_QUEST:
1904 		case O_CH:
1905 		case OEND:
1906 			if (newlen > (sopno)g->mlen) {		/* ends one */
1907 				start = newstart;
1908 				g->mlen = newlen;
1909 				if (offset > -1) {
1910 					g->moffset += offset;
1911 					offset = newlen;
1912 				} else
1913 					g->moffset = offset;
1914 			} else {
1915 				if (offset > -1)
1916 					offset += newlen;
1917 			}
1918 			newlen = 0;
1919 			break;
1920 		case OANY:
1921 			if (newlen > (sopno)g->mlen) {		/* ends one */
1922 				start = newstart;
1923 				g->mlen = newlen;
1924 				if (offset > -1) {
1925 					g->moffset += offset;
1926 					offset = newlen;
1927 				} else
1928 					g->moffset = offset;
1929 			} else {
1930 				if (offset > -1)
1931 					offset += newlen;
1932 			}
1933 			if (offset > -1)
1934 				offset++;
1935 			newlen = 0;
1936 			break;
1937 		case OANYOF:		/* may or may not invalidate offset */
1938 			/* First, everything as OANY */
1939 			if (newlen > (sopno)g->mlen) {		/* ends one */
1940 				start = newstart;
1941 				g->mlen = newlen;
1942 				if (offset > -1) {
1943 					g->moffset += offset;
1944 					offset = newlen;
1945 				} else
1946 					g->moffset = offset;
1947 			} else {
1948 				if (offset > -1)
1949 					offset += newlen;
1950 			}
1951 			if (offset > -1)
1952 				offset++;
1953 			newlen = 0;
1954 			break;
1955 		toohard:
1956 		default:
1957 			/* Anything here makes it impossible or too hard
1958 			 * to calculate the offset -- so we give up;
1959 			 * save the last known good offset, in case the
1960 			 * must sequence doesn't occur later.
1961 			 */
1962 			if (newlen > (sopno)g->mlen) {		/* ends one */
1963 				start = newstart;
1964 				g->mlen = newlen;
1965 				if (offset > -1)
1966 					g->moffset += offset;
1967 				else
1968 					g->moffset = offset;
1969 			}
1970 			offset = -1;
1971 			newlen = 0;
1972 			break;
1973 		}
1974 	} while (OP(s) != OEND);
1975 
1976 	if (g->mlen == 0) {		/* there isn't one */
1977 		g->moffset = -1;
1978 		return;
1979 	}
1980 
1981 	/* turn it into a character string */
1982 	g->must = malloc((size_t)g->mlen + 1);
1983 	if (g->must == NULL) {		/* argh; just forget it */
1984 		g->mlen = 0;
1985 		g->moffset = -1;
1986 		return;
1987 	}
1988 	cp = g->must;
1989 	scan = start;
1990 	memset(&mbs, 0, sizeof(mbs));
1991 	while (cp < g->must + g->mlen) {
1992 		while (OP(s = *scan++) != OCHAR)
1993 			continue;
1994 		clen = wcrtomb(cp, OPND(s), &mbs);
1995 		assert(clen != (size_t)-1);
1996 		cp += clen;
1997 	}
1998 	assert(cp == g->must + g->mlen);
1999 	*cp++ = '\0';		/* just on general principles */
2000 }
2001 
2002 /*
2003  - altoffset - choose biggest offset among multiple choices
2004  == static int altoffset(sop *scan, int offset);
2005  *
2006  * Compute, recursively if necessary, the largest offset among multiple
2007  * re paths.
2008  */
2009 static int
2010 altoffset(sop *scan, int offset)
2011 {
2012 	int largest;
2013 	int try;
2014 	sop s;
2015 
2016 	/* If we gave up already on offsets, return */
2017 	if (offset == -1)
2018 		return -1;
2019 
2020 	largest = 0;
2021 	try = 0;
2022 	s = *scan++;
2023 	while (OP(s) != (sop)O_QUEST && OP(s) != (sop)O_CH) {
2024 		switch (OP(s)) {
2025 		case OOR1:
2026 			if (try > largest)
2027 				largest = try;
2028 			try = 0;
2029 			break;
2030 		case OQUEST_:
2031 		case OCH_:
2032 			try = altoffset(scan, try);
2033 			if (try == -1)
2034 				return -1;
2035 			scan--;
2036 			do {
2037 				scan += OPND(s);
2038 				s = *scan;
2039 				if (OP(s) != (sop)O_QUEST &&
2040 				    OP(s) != (sop)O_CH && OP(s) != (sop)OOR2)
2041 					return -1;
2042 			} while (OP(s) != (sop)O_QUEST && OP(s) != (sop)O_CH);
2043 			/* We must skip to the next position, or we'll
2044 			 * leave altoffset() too early.
2045 			 */
2046 			scan++;
2047 			break;
2048 		case OANYOF:
2049 		case OCHAR:
2050 		case OANY:
2051 			try++;
2052 		case OBOW:
2053 		case OEOW:
2054 		case OWBND:
2055 		case ONWBND:
2056 		case OLPAREN:
2057 		case ORPAREN:
2058 		case OOR2:
2059 			break;
2060 		default:
2061 			try = -1;
2062 			break;
2063 		}
2064 		if (try == -1)
2065 			return -1;
2066 		s = *scan++;
2067 	}
2068 
2069 	if (try > largest)
2070 		largest = try;
2071 
2072 	return largest+offset;
2073 }
2074 
2075 /*
2076  - computejumps - compute char jumps for BM scan
2077  == static void computejumps(struct parse *p, struct re_guts *g);
2078  *
2079  * This algorithm assumes g->must exists and is has size greater than
2080  * zero. It's based on the algorithm found on Computer Algorithms by
2081  * Sara Baase.
2082  *
2083  * A char jump is the number of characters one needs to jump based on
2084  * the value of the character from the text that was mismatched.
2085  */
2086 static void
2087 computejumps(struct parse *p, struct re_guts *g)
2088 {
2089 	int ch;
2090 	int mindex;
2091 
2092 	/* Avoid making errors worse */
2093 	if (p->error != 0)
2094 		return;
2095 
2096 	g->charjump = (int *)malloc((NC_MAX + 1) * sizeof(int));
2097 	if (g->charjump == NULL)	/* Not a fatal error */
2098 		return;
2099 	/* Adjust for signed chars, if necessary */
2100 	g->charjump = &g->charjump[-(CHAR_MIN)];
2101 
2102 	/* If the character does not exist in the pattern, the jump
2103 	 * is equal to the number of characters in the pattern.
2104 	 */
2105 	for (ch = CHAR_MIN; ch < (CHAR_MAX + 1); ch++)
2106 		g->charjump[ch] = g->mlen;
2107 
2108 	/* If the character does exist, compute the jump that would
2109 	 * take us to the last character in the pattern equal to it
2110 	 * (notice that we match right to left, so that last character
2111 	 * is the first one that would be matched).
2112 	 */
2113 	for (mindex = 0; mindex < g->mlen; mindex++)
2114 		g->charjump[(int)g->must[mindex]] = g->mlen - mindex - 1;
2115 }
2116 
2117 /*
2118  - computematchjumps - compute match jumps for BM scan
2119  == static void computematchjumps(struct parse *p, struct re_guts *g);
2120  *
2121  * This algorithm assumes g->must exists and is has size greater than
2122  * zero. It's based on the algorithm found on Computer Algorithms by
2123  * Sara Baase.
2124  *
2125  * A match jump is the number of characters one needs to advance based
2126  * on the already-matched suffix.
2127  * Notice that all values here are minus (g->mlen-1), because of the way
2128  * the search algorithm works.
2129  */
2130 static void
2131 computematchjumps(struct parse *p, struct re_guts *g)
2132 {
2133 	int mindex;		/* General "must" iterator */
2134 	int suffix;		/* Keeps track of matching suffix */
2135 	int ssuffix;		/* Keeps track of suffixes' suffix */
2136 	int* pmatches;		/* pmatches[k] points to the next i
2137 				 * such that i+1...mlen is a substring
2138 				 * of k+1...k+mlen-i-1
2139 				 */
2140 
2141 	/* Avoid making errors worse */
2142 	if (p->error != 0)
2143 		return;
2144 
2145 	pmatches = (int*) malloc(g->mlen * sizeof(int));
2146 	if (pmatches == NULL) {
2147 		g->matchjump = NULL;
2148 		return;
2149 	}
2150 
2151 	g->matchjump = (int*) malloc(g->mlen * sizeof(int));
2152 	if (g->matchjump == NULL) {	/* Not a fatal error */
2153 		free(pmatches);
2154 		return;
2155 	}
2156 
2157 	/* Set maximum possible jump for each character in the pattern */
2158 	for (mindex = 0; mindex < g->mlen; mindex++)
2159 		g->matchjump[mindex] = 2*g->mlen - mindex - 1;
2160 
2161 	/* Compute pmatches[] */
2162 	for (mindex = g->mlen - 1, suffix = g->mlen; mindex >= 0;
2163 	    mindex--, suffix--) {
2164 		pmatches[mindex] = suffix;
2165 
2166 		/* If a mismatch is found, interrupting the substring,
2167 		 * compute the matchjump for that position. If no
2168 		 * mismatch is found, then a text substring mismatched
2169 		 * against the suffix will also mismatch against the
2170 		 * substring.
2171 		 */
2172 		while (suffix < g->mlen
2173 		    && g->must[mindex] != g->must[suffix]) {
2174 			g->matchjump[suffix] = MIN(g->matchjump[suffix],
2175 			    g->mlen - mindex - 1);
2176 			suffix = pmatches[suffix];
2177 		}
2178 	}
2179 
2180 	/* Compute the matchjump up to the last substring found to jump
2181 	 * to the beginning of the largest must pattern prefix matching
2182 	 * it's own suffix.
2183 	 */
2184 	for (mindex = 0; mindex <= suffix; mindex++)
2185 		g->matchjump[mindex] = MIN(g->matchjump[mindex],
2186 		    g->mlen + suffix - mindex);
2187 
2188         ssuffix = pmatches[suffix];
2189         while (suffix < g->mlen) {
2190                 while (suffix <= ssuffix && suffix < g->mlen) {
2191                         g->matchjump[suffix] = MIN(g->matchjump[suffix],
2192 			    g->mlen + ssuffix - suffix);
2193                         suffix++;
2194                 }
2195 		if (suffix < g->mlen)
2196                 	ssuffix = pmatches[ssuffix];
2197         }
2198 
2199 	free(pmatches);
2200 }
2201 
2202 /*
2203  - pluscount - count + nesting
2204  == static sopno pluscount(struct parse *p, struct re_guts *g);
2205  */
2206 static sopno			/* nesting depth */
2207 pluscount(struct parse *p, struct re_guts *g)
2208 {
2209 	sop *scan;
2210 	sop s;
2211 	sopno plusnest = 0;
2212 	sopno maxnest = 0;
2213 
2214 	if (p->error != 0)
2215 		return(0);	/* there may not be an OEND */
2216 
2217 	scan = g->strip + 1;
2218 	do {
2219 		s = *scan++;
2220 		switch (OP(s)) {
2221 		case OPLUS_:
2222 			plusnest++;
2223 			break;
2224 		case O_PLUS:
2225 			if (plusnest > maxnest)
2226 				maxnest = plusnest;
2227 			plusnest--;
2228 			break;
2229 		}
2230 	} while (OP(s) != OEND);
2231 	if (plusnest != 0)
2232 		g->iflags |= BAD;
2233 	return(maxnest);
2234 }
2235