diff regexp.h @ 0:1493bea5ac22 0.1

Initial version of the standalone heirloom-ed
author markus schnalke <meillo@marmaro.de>
date Mon, 05 Sep 2011 16:31:35 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/regexp.h	Mon Sep 05 16:31:35 2011 +0200
@@ -0,0 +1,1211 @@
+/*
+ * Simple Regular Expression functions. Derived from Unix 7th Edition,
+ * /usr/src/cmd/expr.y
+ *
+ * Modified by Gunnar Ritter, Freiburg i. Br., Germany, February 2002.
+ *
+ * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *   Redistributions of source code and documentation must retain the
+ *    above copyright notice, this list of conditions and the following
+ *    disclaimer.
+ *   Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *   All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *      This product includes software developed or owned by Caldera
+ *      International, Inc.
+ *   Neither the name of Caldera International, Inc. nor the names of
+ *    other contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
+ * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
+ * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if __GNUC__ >= 3 && __GNUC_MINOR__ >= 4 || __GNUC__ >= 4
+#define	REGEXP_H_USED	__attribute__ ((used))
+#elif defined __GNUC__
+#define	REGEXP_H_USED	__attribute__ ((unused))
+#else
+#define	REGEXP_H_USED
+#endif
+static const char regexp_h_sccsid[] REGEXP_H_USED =
+	"@(#)regexp.sl	1.56 (gritter) 5/29/05";
+
+#if !defined (REGEXP_H_USED_FROM_VI) && !defined (__dietlibc__)
+#define	REGEXP_H_WCHARS
+#endif
+
+#define	CBRA	2
+#define	CCHR	4
+#define	CDOT	8
+#define	CCL	12
+/*	CLNUM	14	used in sed */
+/*	CEND	16	used in sed */
+#define	CDOL	20
+#define	CCEOF	22
+#define	CKET	24
+#define	CBACK	36
+#define	CNCL	40
+#define	CBRC	44
+#define	CLET	48
+#define	CCH1	52
+#define	CCH2	56
+#define	CCH3	60
+
+#define	STAR	01
+#define RNGE	03
+#define	REGEXP_H_LEAST	0100
+
+#ifdef	REGEXP_H_WCHARS
+#define	CMB	0200
+#else	/* !REGEXP_H_WCHARS */
+#define	CMB	0
+#endif	/* !REGEXP_H_WCHARS */
+
+#define	NBRA	9
+
+#define PLACE(c)	ep[c >> 3] |= bittab[c & 07]
+#define ISTHERE(c)	(ep[c >> 3] & bittab[c & 07])
+
+#ifdef	REGEXP_H_WCHARS
+#define	REGEXP_H_IS_THERE(ep, c)	((ep)[c >> 3] & bittab[c & 07])
+#endif
+
+#include	<ctype.h>
+#include	<string.h>
+#include	<limits.h>
+#ifdef	REGEXP_H_WCHARS
+#include	<stdlib.h>
+#include	<wchar.h>
+#include	<wctype.h>
+#endif	/* REGEXP_H_WCHARS */
+
+#define	regexp_h_uletter(c)	(isalpha(c) || (c) == '_')
+#ifdef	REGEXP_H_WCHARS
+#define	regexp_h_wuletter(c)	(iswalpha(c) || (c) == L'_')
+
+/*
+ * Used to allocate memory for the multibyte star algorithm.
+ */
+#ifndef	regexp_h_malloc
+#define	regexp_h_malloc(n)	malloc(n)
+#endif
+#ifndef	regexp_h_free
+#define	regexp_h_free(p)	free(p)
+#endif
+
+/*
+ * Can be predefined to 'inline' to inline some multibyte functions;
+ * may improve performance for files that contain many multibyte
+ * sequences.
+ */
+#ifndef	regexp_h_inline
+#define	regexp_h_inline
+#endif
+
+/*
+ * Mask to determine whether the first byte of a sequence possibly
+ * starts a multibyte character. Set to 0377 to force mbtowc() for
+ * any byte sequence (except 0).
+ */
+#ifndef	REGEXP_H_MASK
+#define	REGEXP_H_MASK	0200
+#endif
+#endif	/* REGEXP_H_WCHARS */
+
+/*
+ * For regexpr.h.
+ */
+#ifndef	regexp_h_static
+#define	regexp_h_static
+#endif
+#ifndef	REGEXP_H_STEP_INIT
+#define	REGEXP_H_STEP_INIT
+#endif
+#ifndef	REGEXP_H_ADVANCE_INIT
+#define	REGEXP_H_ADVANCE_INIT
+#endif
+
+char	*braslist[NBRA];
+char	*braelist[NBRA];
+int	nbra;
+char	*loc1, *loc2, *locs;
+int	sed;
+int	nodelim;
+
+regexp_h_static int	circf;
+regexp_h_static int	low;
+regexp_h_static int	size;
+
+regexp_h_static unsigned char	bittab[] = {
+	1,
+	2,
+	4,
+	8,
+	16,
+	32,
+	64,
+	128
+};
+static int	regexp_h_advance(register const char *lp,
+			register const char *ep);
+static void	regexp_h_getrnge(register const char *str, int least);
+
+static const char	*regexp_h_bol;	/* beginning of input line (for \<) */
+
+#ifdef	REGEXP_H_WCHARS
+static int	regexp_h_wchars;
+static int	regexp_h_mbcurmax;
+
+static const char	*regexp_h_firstwc;	/* location of first
+						   multibyte character
+						   on input line */
+
+#define	regexp_h_getwc(c)	{ \
+	if (regexp_h_wchars) { \
+		char mbbuf[MB_LEN_MAX + 1], *mbptr; \
+		wchar_t wcbuf; \
+		int mb, len; \
+		mbptr = mbbuf; \
+		do { \
+			mb = GETC(); \
+			*mbptr++ = mb; \
+			*mbptr = '\0'; \
+		} while ((len = mbtowc(&wcbuf, mbbuf, regexp_h_mbcurmax)) < 0 \
+			&& mb != eof && mbptr < mbbuf + MB_LEN_MAX); \
+		if (len == -1) \
+			ERROR(67); \
+		c = wcbuf; \
+	} else { \
+		c = GETC(); \
+	} \
+}
+
+#define	regexp_h_store(wc, mb, me)	{ \
+	int len; \
+	if (wc == WEOF) \
+		ERROR(67); \
+	if ((len = me - mb) <= regexp_h_mbcurmax) { \
+		char mt[MB_LEN_MAX]; \
+		if (wctomb(mt, wc) >= len) \
+			ERROR(50); \
+	} \
+	switch (len = wctomb(mb, wc)) { \
+	case -1: \
+		 ERROR(67); \
+	case 0: \
+		mb++; \
+		break; \
+	default: \
+		mb += len; \
+	} \
+}
+
+static regexp_h_inline wint_t
+regexp_h_fetchwc(const char **mb, int islp)
+{
+	wchar_t wc;
+	int len;
+
+	if ((len = mbtowc(&wc, *mb, regexp_h_mbcurmax)) < 0) {
+		(*mb)++;
+		return WEOF;
+	}
+	if (islp && regexp_h_firstwc == NULL)
+		regexp_h_firstwc = *mb;
+	/*if (len == 0) {
+		(*mb)++;
+		return L'\0';
+	} handled in singlebyte code */
+	*mb += len;
+	return wc;
+}
+
+#define	regexp_h_fetch(mb, islp)	((*(mb) & REGEXP_H_MASK) == 0 ? \
+						(*(mb)++&0377): \
+						regexp_h_fetchwc(&(mb), islp))
+
+static regexp_h_inline wint_t
+regexp_h_showwc(const char *mb)
+{
+	wchar_t wc;
+
+	if (mbtowc(&wc, mb, regexp_h_mbcurmax) < 0)
+		return WEOF;
+	return wc;
+}
+
+#define	regexp_h_show(mb)	((*(mb) & REGEXP_H_MASK) == 0 ? (*(mb)&0377): \
+					regexp_h_showwc(mb))
+
+/*
+ * Return the character immediately preceding mb. Since no byte is
+ * required to be the first byte of a character, the longest multibyte
+ * character ending at &[mb-1] is searched.
+ */
+static regexp_h_inline wint_t
+regexp_h_previous(const char *mb)
+{
+	const char *p = mb;
+	wchar_t wc, lastwc = WEOF;
+	int len, max = 0;
+
+	if (regexp_h_firstwc == NULL || mb <= regexp_h_firstwc)
+		return (mb > regexp_h_bol ? (mb[-1] & 0377) : WEOF);
+	while (p-- > regexp_h_bol) {
+		mbtowc(NULL, NULL, 0);
+		if ((len = mbtowc(&wc, p, mb - p)) >= 0) {
+			if (len < max || len < mb - p)
+				break;
+			max = len;
+			lastwc = wc;
+		} else if (len < 0 && max > 0)
+			break;
+	}
+	return lastwc;
+}
+
+#define	regexp_h_cclass(set, c, af)	\
+	((c) == 0 || (c) == WEOF ? 0 : ( \
+		((c) > 0177) ? \
+			regexp_h_cclass_wc(set, c, af) : ( \
+				REGEXP_H_IS_THERE((set)+1, (c)) ? (af) : !(af) \
+			) \
+		) \
+	)
+
+static regexp_h_inline int
+regexp_h_cclass_wc(const char *set, register wint_t c, int af)
+{
+	register wint_t wc, wl = WEOF;
+	const char *end;
+
+	end = &set[18] + set[0] - 1;
+	set += 17;
+	while (set < end) {
+		wc = regexp_h_fetch(set, 0);
+#ifdef	REGEXP_H_VI_BACKSLASH
+		if (wc == '\\' && set < end &&
+				(*set == ']' || *set == '-' ||
+				 *set == '^' || *set == '\\')) {
+			wc = regexp_h_fetch(set, 0);
+		} else
+#endif	/* REGEXP_H_VI_BACKSLASH */
+		if (wc == '-' && wl != WEOF && set < end) {
+			wc = regexp_h_fetch(set, 0);
+#ifdef	REGEXP_H_VI_BACKSLASH
+			if (wc == '\\' && set < end &&
+					(*set == ']' || *set == '-' ||
+					 *set == '^' || *set == '\\')) {
+				wc = regexp_h_fetch(set, 0);
+			}
+#endif	/* REGEXP_H_VI_BACKSLASH */
+			if (c > wl && c < wc)
+				return af;
+		}
+		if (c == wc)
+			return af;
+		wl = wc;
+	}
+	return !af;
+}
+#else	/* !REGEXP_H_WCHARS */
+#define	regexp_h_wchars		0
+#define	regexp_h_getwc(c)	{ c = GETC(); }
+#endif	/* !REGEXP_H_WCHARS */
+
+regexp_h_static char *
+compile(char *instring, char *ep, const char *endbuf, int seof)
+{
+	INIT	/* Dependent declarations and initializations */
+	register int c;
+	register int eof = seof;
+	char *lastep = instring;
+	int cclcnt;
+	char bracket[NBRA], *bracketp;
+	int closed;
+	char neg;
+	int lc;
+	int i, cflg;
+
+#ifdef	REGEXP_H_WCHARS
+	char *eq;
+	regexp_h_mbcurmax = MB_CUR_MAX;
+	regexp_h_wchars = regexp_h_mbcurmax > 1 ? CMB : 0;
+#endif
+	lastep = 0;
+	bracketp = bracket;
+	if((c = GETC()) == eof || c == '\n') {
+		if (c == '\n') {
+			UNGETC(c);
+			nodelim = 1;
+		}
+		if(*ep == 0 && !sed)
+			ERROR(41);
+		if (bracketp > bracket)
+			ERROR(42);
+		RETURN(ep);
+	}
+	circf = closed = nbra = 0;
+	if (c == '^')
+		circf++;
+	else
+		UNGETC(c);
+	for (;;) {
+		if (ep >= endbuf)
+			ERROR(50);
+		regexp_h_getwc(c);
+		if(c != '*' && ((c != '\\') || (PEEKC() != '{')))
+			lastep = ep;
+		if (c == eof) {
+			*ep++ = CCEOF;
+			if (bracketp > bracket)
+				ERROR(42);
+			RETURN(ep);
+		}
+		switch (c) {
+
+		case '.':
+			*ep++ = CDOT|regexp_h_wchars;
+			continue;
+
+		case '\n':
+			if (sed == 0) {
+				UNGETC(c);
+				*ep++ = CCEOF;
+				nodelim = 1;
+				RETURN(ep);
+			}
+			ERROR(36);
+		case '*':
+			if (lastep==0 || *lastep==CBRA || *lastep==CKET ||
+					*lastep==(CBRC|regexp_h_wchars) ||
+					*lastep==(CLET|regexp_h_wchars))
+				goto defchar;
+			*lastep |= STAR;
+			continue;
+
+		case '$':
+			if(PEEKC() != eof)
+				goto defchar;
+			*ep++ = CDOL;
+			continue;
+
+		case '[':
+#ifdef	REGEXP_H_WCHARS
+			if (regexp_h_wchars == 0) {
+#endif
+				if(&ep[33] >= endbuf)
+					ERROR(50);
+
+				*ep++ = CCL;
+				lc = 0;
+				for(i = 0; i < 32; i++)
+					ep[i] = 0;
+
+				neg = 0;
+				if((c = GETC()) == '^') {
+					neg = 1;
+					c = GETC();
+				}
+
+				do {
+					c &= 0377;
+					if(c == '\0' || c == '\n')
+						ERROR(49);
+#ifdef	REGEXP_H_VI_BACKSLASH
+					if(c == '\\' && ((c = PEEKC()) == ']' ||
+							c == '-' || c == '^' ||
+							c == '\\')) {
+						c = GETC();
+						c &= 0377;
+					} else
+#endif	/* REGEXP_H_VI_BACKSLASH */
+					if(c == '-' && lc != 0) {
+						if ((c = GETC()) == ']') {
+							PLACE('-');
+							break;
+						}
+#ifdef	REGEXP_H_VI_BACKSLASH
+						if(c == '\\' &&
+							((c = PEEKC()) == ']' ||
+								c == '-' ||
+								c == '^' ||
+								c == '\\'))
+							c = GETC();
+#endif	/* REGEXP_H_VI_BACKSLASH */
+						c &= 0377;
+						while(lc < c) {
+							PLACE(lc);
+							lc++;
+						}
+					}
+					lc = c;
+					PLACE(c);
+				} while((c = GETC()) != ']');
+				if(neg) {
+					for(cclcnt = 0; cclcnt < 32; cclcnt++)
+						ep[cclcnt] ^= 0377;
+					ep[0] &= 0376;
+				}
+
+				ep += 32;
+#ifdef	REGEXP_H_WCHARS
+			} else {
+				if (&ep[18] >= endbuf)
+					ERROR(50);
+				*ep++ = CCL|CMB;
+				*ep++ = 0;
+				lc = 0;
+				for (i = 0; i < 16; i++)
+					ep[i] = 0;
+				eq = &ep[16];
+				regexp_h_getwc(c);
+				if (c == L'^') {
+					regexp_h_getwc(c);
+					ep[-2] = CNCL|CMB;
+				}
+				do {
+					if (c == '\0' || c == '\n')
+						ERROR(49);
+#ifdef	REGEXP_H_VI_BACKSLASH
+					if(c == '\\' && ((c = PEEKC()) == ']' ||
+							c == '-' || c == '^' ||
+							c == '\\')) {
+						regexp_h_store(c, eq, endbuf);
+						regexp_h_getwc(c);
+					} else
+#endif	/* REGEXP_H_VI_BACKSLASH */
+					if (c == '-' && lc != 0 && lc <= 0177) {
+						regexp_h_store(c, eq, endbuf);
+						regexp_h_getwc(c);
+						if (c == ']') {
+							PLACE('-');
+							break;
+						}
+#ifdef	REGEXP_H_VI_BACKSLASH
+						if(c == '\\' &&
+							((c = PEEKC()) == ']' ||
+								c == '-' ||
+								c == '^' ||
+								c == '\\')) {
+							regexp_h_store(c, eq,
+								endbuf);
+							regexp_h_getwc(c);
+						}
+#endif	/* REGEXP_H_VI_BACKSLASH */
+						while (lc < (c & 0177)) {
+							PLACE(lc);
+							lc++;
+						}
+					}
+					lc = c;
+					if (c <= 0177)
+						PLACE(c);
+					regexp_h_store(c, eq, endbuf);
+					regexp_h_getwc(c);
+				} while (c != L']');
+				if ((i = eq - &ep[16]) > 255)
+					ERROR(50);
+				lastep[1] = i;
+				ep = eq;
+			}
+#endif	/* REGEXP_H_WCHARS */
+
+			continue;
+
+		case '\\':
+			regexp_h_getwc(c);
+			switch(c) {
+
+			case '(':
+				if(nbra >= NBRA)
+					ERROR(43);
+				*bracketp++ = nbra;
+				*ep++ = CBRA;
+				*ep++ = nbra++;
+				continue;
+
+			case ')':
+				if(bracketp <= bracket)
+					ERROR(42);
+				*ep++ = CKET;
+				*ep++ = *--bracketp;
+				closed++;
+				continue;
+
+			case '<':
+				*ep++ = CBRC|regexp_h_wchars;
+				continue;
+
+			case '>':
+				*ep++ = CLET|regexp_h_wchars;
+				continue;
+
+			case '{':
+				if(lastep == (char *) (0))
+					goto defchar;
+				*lastep |= RNGE;
+				cflg = 0;
+			nlim:
+				c = GETC();
+				i = 0;
+				do {
+					if ('0' <= c && c <= '9')
+						i = 10 * i + c - '0';
+					else
+						ERROR(16);
+				} while(((c = GETC()) != '\\') && (c != ','));
+				if (i > 255)
+					ERROR(11);
+				*ep++ = i;
+				if (c == ',') {
+					if(cflg++)
+						ERROR(44);
+					if((c = GETC()) == '\\') {
+						*ep++ = (char)255;
+						*lastep |= REGEXP_H_LEAST;
+					} else {
+						UNGETC(c);
+						goto nlim; /* get 2'nd number */
+					}
+				}
+				if(GETC() != '}')
+					ERROR(45);
+				if(!cflg)	/* one number */
+					*ep++ = i;
+				else if((ep[-1] & 0377) < (ep[-2] & 0377))
+					ERROR(46);
+				continue;
+
+			case '\n':
+				ERROR(36);
+
+			case 'n':
+				c = '\n';
+				goto defchar;
+
+			default:
+				if(c >= '1' && c <= '9') {
+					if((c -= '1') >= closed)
+						ERROR(25);
+					*ep++ = CBACK;
+					*ep++ = c;
+					continue;
+				}
+			}
+			/* Drop through to default to use \ to turn off special chars */
+
+		defchar:
+		default:
+			lastep = ep;
+#ifdef	REGEXP_H_WCHARS
+			if (regexp_h_wchars == 0) {
+#endif
+				*ep++ = CCHR;
+				*ep++ = c;
+#ifdef	REGEXP_H_WCHARS
+			} else {
+				char	mbbuf[MB_LEN_MAX];
+
+				switch (wctomb(mbbuf, c)) {
+				case 1: *ep++ = CCH1;
+					break;
+				case 2:	*ep++ = CCH2;
+					break;
+				case 3:	*ep++ = CCH3;
+					break;
+				default:
+					*ep++ = CCHR|CMB;
+				}
+				regexp_h_store(c, ep, endbuf);
+			}
+#endif	/* REGEXP_H_WCHARS */
+		}
+	}
+}
+
+int
+step(const char *p1, const char *p2)
+{
+	register int c;
+#ifdef	REGEXP_H_WCHARS
+	register int d;
+#endif	/* REGEXP_H_WCHARS */
+
+	REGEXP_H_STEP_INIT	/* get circf */
+	regexp_h_bol = p1;
+#ifdef	REGEXP_H_WCHARS
+	regexp_h_firstwc = NULL;
+#endif	/* REGEXP_H_WCHARS */
+	if (circf) {
+		loc1 = (char *)p1;
+		return(regexp_h_advance(p1, p2));
+	}
+	/* fast check for first character */
+	if (*p2==CCHR) {
+		c = p2[1] & 0377;
+		do {
+			if ((*p1 & 0377) != c)
+				continue;
+			if (regexp_h_advance(p1, p2)) {
+				loc1 = (char *)p1;
+				return(1);
+			}
+		} while (*p1++);
+		return(0);
+	}
+#ifdef	REGEXP_H_WCHARS
+	else if (*p2==CCH1) {
+		do {
+			if (p1[0] == p2[1] && regexp_h_advance(p1, p2)) {
+				loc1 = (char *)p1;
+				return(1);
+			}
+			c = regexp_h_fetch(p1, 1);
+		} while (c);
+		return(0);
+	} else if (*p2==CCH2) {
+		do {
+			if (p1[0] == p2[1] && p1[1] == p2[2] &&
+					regexp_h_advance(p1, p2)) {
+				loc1 = (char *)p1;
+				return(1);
+			}
+			c = regexp_h_fetch(p1, 1);
+		} while (c);
+		return(0);
+	} else if (*p2==CCH3) {
+		do {
+			if (p1[0] == p2[1] && p1[1] == p2[2] && p1[2] == p2[3]&&
+					regexp_h_advance(p1, p2)) {
+				loc1 = (char *)p1;
+				return(1);
+			}
+			c = regexp_h_fetch(p1, 1);
+		} while (c);
+		return(0);
+	} else if ((*p2&0377)==(CCHR|CMB)) {
+		d = regexp_h_fetch(p2, 0);
+		do {
+			c = regexp_h_fetch(p1, 1);
+			if (c == d && regexp_h_advance(p1, p2)) {
+				loc1 = (char *)p1;
+				return(1);
+			}
+		} while(c);
+		return(0);
+	}
+		/* regular algorithm */
+	if (regexp_h_wchars)
+		do {
+			if (regexp_h_advance(p1, p2)) {
+				loc1 = (char *)p1;
+				return(1);
+			}
+			c = regexp_h_fetch(p1, 1);
+		} while (c);
+	else
+#endif	/* REGEXP_H_WCHARS */
+		do {
+			if (regexp_h_advance(p1, p2)) {
+				loc1 = (char *)p1;
+				return(1);
+			}
+		} while (*p1++);
+	return(0);
+}
+
+#ifdef	REGEXP_H_WCHARS
+/*
+ * It is painfully slow to read character-wise backwards in a
+ * multibyte string (see regexp_h_previous() above). For the star
+ * algorithm, we therefore keep track of every character as it is
+ * read in forward direction.
+ *
+ * Don't use alloca() for stack blocks since there is no measurable
+ * speedup and huge amounts of memory are used up for long input
+ * lines.
+ */
+#ifndef	REGEXP_H_STAKBLOK
+#define	REGEXP_H_STAKBLOK	1000
+#endif
+
+struct	regexp_h_stack {
+	struct regexp_h_stack	*s_nxt;
+	struct regexp_h_stack	*s_prv;
+	const char	*s_ptr[REGEXP_H_STAKBLOK];
+};
+
+#define	regexp_h_push(sb, sp, sc, lp)	(regexp_h_wchars ? \
+			regexp_h_pushwc(sb, sp, sc, lp) : (void)0)
+
+static regexp_h_inline void
+regexp_h_pushwc(struct regexp_h_stack **sb,
+		struct regexp_h_stack **sp,
+		const char ***sc, const char *lp)
+{
+	if (regexp_h_firstwc == NULL || lp < regexp_h_firstwc)
+		return;
+	if (*sb == NULL) {
+		if ((*sb = regexp_h_malloc(sizeof **sb)) == NULL)
+			return;
+		(*sb)->s_nxt = (*sb)->s_prv = NULL;
+		*sp = *sb;
+		*sc = &(*sb)->s_ptr[0];
+	} else if (*sc >= &(*sp)->s_ptr[REGEXP_H_STAKBLOK]) {
+		if ((*sp)->s_nxt == NULL) {
+			struct regexp_h_stack	*bq;
+
+			if ((bq = regexp_h_malloc(sizeof *bq)) == NULL)
+				return;
+			bq->s_nxt = NULL;
+			bq->s_prv = *sp;
+			(*sp)->s_nxt = bq;
+			*sp = bq;
+		} else
+			*sp = (*sp)->s_nxt;
+		*sc = &(*sp)->s_ptr[0];
+	}
+	*(*sc)++ = lp;
+}
+
+static regexp_h_inline const char *
+regexp_h_pop(struct regexp_h_stack **sb, struct regexp_h_stack **sp,
+		const char ***sc, const char *lp)
+{
+	if (regexp_h_firstwc == NULL || lp <= regexp_h_firstwc)
+		return &lp[-1];
+	if (*sp == NULL)
+		return regexp_h_firstwc;
+	if (*sc == &(*sp)->s_ptr[0]) {
+		if ((*sp)->s_prv == NULL) {
+			regexp_h_free(*sp);
+			*sp = NULL;
+			*sb = NULL;
+			return regexp_h_firstwc;
+		}
+		*sp = (*sp)->s_prv;
+		regexp_h_free((*sp)->s_nxt);
+		(*sp)->s_nxt = NULL ;
+		*sc = &(*sp)->s_ptr[REGEXP_H_STAKBLOK];
+	}
+	return *(--(*sc));
+}
+
+static void
+regexp_h_zerostak(struct regexp_h_stack **sb, struct regexp_h_stack **sp)
+{
+	for (*sp = *sb; *sp && (*sp)->s_nxt; *sp = (*sp)->s_nxt)
+		if ((*sp)->s_prv)
+			regexp_h_free((*sp)->s_prv);
+	if (*sp) {
+		if ((*sp)->s_prv)
+			regexp_h_free((*sp)->s_prv);
+		regexp_h_free(*sp);
+	}
+	*sp = *sb = NULL;
+}
+#else	/* !REGEXP_H_WCHARS */
+#define	regexp_h_push(sb, sp, sc, lp)
+#endif	/* !REGEXP_H_WCHARS */
+
+static int
+regexp_h_advance(const char *lp, const char *ep)
+{
+	register const char *curlp;
+	int c, least;
+#ifdef	REGEXP_H_WCHARS
+	int d;
+	struct regexp_h_stack	*sb = NULL, *sp = NULL;
+	const char	**sc;
+#endif	/* REGEXP_H_WCHARS */
+	char *bbeg;
+	int ct;
+
+	for (;;) switch (least = *ep++ & 0377, least & ~REGEXP_H_LEAST) {
+
+	case CCHR:
+#ifdef	REGEXP_H_WCHARS
+	case CCH1:
+#endif
+		if (*ep++ == *lp++)
+			continue;
+		return(0);
+
+#ifdef	REGEXP_H_WCHARS
+	case CCHR|CMB:
+		if (regexp_h_fetch(ep, 0) == regexp_h_fetch(lp, 1))
+			continue;
+		return(0);
+
+	case CCH2:
+		if (ep[0] == lp[0] && ep[1] == lp[1]) {
+			ep += 2, lp += 2;
+			continue;
+		}
+		return(0);
+
+	case CCH3:
+		if (ep[0] == lp[0] && ep[1] == lp[1] && ep[2] == lp[2]) {
+			ep += 3, lp += 3;
+			continue;
+		}
+		return(0);
+#endif	/* REGEXP_H_WCHARS */
+
+	case CDOT:
+		if (*lp++)
+			continue;
+		return(0);
+#ifdef	REGEXP_H_WCHARS
+	case CDOT|CMB:
+		if ((c = regexp_h_fetch(lp, 1)) != L'\0' && c != WEOF)
+			continue;
+		return(0);
+#endif	/* REGEXP_H_WCHARS */
+
+	case CDOL:
+		if (*lp==0)
+			continue;
+		return(0);
+
+	case CCEOF:
+		loc2 = (char *)lp;
+		return(1);
+
+	case CCL:
+		c = *lp++ & 0377;
+		if(ISTHERE(c)) {
+			ep += 32;
+			continue;
+		}
+		return(0);
+
+#ifdef	REGEXP_H_WCHARS
+	case CCL|CMB:
+	case CNCL|CMB:
+		c = regexp_h_fetch(lp, 1);
+		if (regexp_h_cclass(ep, c, (ep[-1] & 0377) == (CCL|CMB))) {
+			ep += (*ep & 0377) + 17;
+			continue;
+		}
+		return 0;
+#endif	/* REGEXP_H_WCHARS */
+
+	case CBRA:
+		braslist[*ep++ & 0377] = (char *)lp;
+		continue;
+
+	case CKET:
+		braelist[*ep++ & 0377] = (char *)lp;
+		continue;
+
+	case CBRC:
+		if (lp == regexp_h_bol && locs == NULL)
+			continue;
+		if ((isdigit(lp[0] & 0377) || regexp_h_uletter(lp[0] & 0377))
+				&& !regexp_h_uletter(lp[-1] & 0377)
+				&& !isdigit(lp[-1] & 0377))
+			continue;
+		return(0);
+
+#ifdef	REGEXP_H_WCHARS
+	case CBRC|CMB:
+		c = regexp_h_show(lp);
+		d = regexp_h_previous(lp);
+		if ((iswdigit(c) || regexp_h_wuletter(c))
+				&& !regexp_h_wuletter(d)
+				&& !iswdigit(d))
+			continue;
+		return(0);
+#endif	/* REGEXP_H_WCHARS */
+
+	case CLET:
+		if (!regexp_h_uletter(lp[0] & 0377) && !isdigit(lp[0] & 0377))
+			continue;
+		return(0);
+
+#ifdef	REGEXP_H_WCHARS
+	case CLET|CMB:
+		c = regexp_h_show(lp);
+		if (!regexp_h_wuletter(c) && !iswdigit(c))
+			continue;
+		return(0);
+#endif	/* REGEXP_H_WCHARS */
+
+	case CCHR|RNGE:
+		c = *ep++;
+		regexp_h_getrnge(ep, least);
+		while(low--)
+			if(*lp++ != c)
+				return(0);
+		curlp = lp;
+		while(size--) {
+			regexp_h_push(&sb, &sp, &sc, lp);
+			if(*lp++ != c)
+				break;
+		}
+		if(size < 0) {
+			regexp_h_push(&sb, &sp, &sc, lp);
+			lp++;
+		}
+		ep += 2;
+		goto star;
+
+#ifdef	REGEXP_H_WCHARS
+	case CCHR|RNGE|CMB:
+	case CCH1|RNGE:
+	case CCH2|RNGE:
+	case CCH3|RNGE:
+		c = regexp_h_fetch(ep, 0);
+		regexp_h_getrnge(ep, least);
+		while (low--)
+			if (regexp_h_fetch(lp, 1) != c)
+				return 0;
+		curlp = lp;
+		while (size--) {
+			regexp_h_push(&sb, &sp, &sc, lp);
+			if (regexp_h_fetch(lp, 1) != c)
+				break;
+		}
+		if(size < 0) {
+			regexp_h_push(&sb, &sp, &sc, lp);
+			regexp_h_fetch(lp, 1);
+		}
+		ep += 2;
+		goto star;
+#endif	/* REGEXP_H_WCHARS */
+
+	case CDOT|RNGE:
+		regexp_h_getrnge(ep, least);
+		while(low--)
+			if(*lp++ == '\0')
+				return(0);
+		curlp = lp;
+		while(size--) {
+			regexp_h_push(&sb, &sp, &sc, lp);
+			if(*lp++ == '\0')
+				break;
+		}
+		if(size < 0) {
+			regexp_h_push(&sb, &sp, &sc, lp);
+			lp++;
+		}
+		ep += 2;
+		goto star;
+
+#ifdef	REGEXP_H_WCHARS
+	case CDOT|RNGE|CMB:
+		regexp_h_getrnge(ep, least);
+		while (low--)
+			if ((c = regexp_h_fetch(lp, 1)) == L'\0' || c == WEOF)
+				return 0;
+		curlp = lp;
+		while (size--) {
+			regexp_h_push(&sb, &sp, &sc, lp);
+			if ((c = regexp_h_fetch(lp, 1)) == L'\0' || c == WEOF)
+				break;
+		}
+		if (size < 0) {
+			regexp_h_push(&sb, &sp, &sc, lp);
+			regexp_h_fetch(lp, 1);
+		}
+		ep += 2;
+		goto star;
+#endif	/* REGEXP_H_WCHARS */
+
+	case CCL|RNGE:
+		regexp_h_getrnge(ep + 32, least);
+		while(low--) {
+			c = *lp++ & 0377;
+			if(!ISTHERE(c))
+				return(0);
+		}
+		curlp = lp;
+		while(size--) {
+			regexp_h_push(&sb, &sp, &sc, lp);
+			c = *lp++ & 0377;
+			if(!ISTHERE(c))
+				break;
+		}
+		if(size < 0) {
+			regexp_h_push(&sb, &sp, &sc, lp);
+			lp++;
+		}
+		ep += 34;		/* 32 + 2 */
+		goto star;
+
+#ifdef	REGEXP_H_WCHARS
+	case CCL|RNGE|CMB:
+	case CNCL|RNGE|CMB:
+		regexp_h_getrnge(ep + (*ep & 0377) + 17, least);
+		while (low--) {
+			c = regexp_h_fetch(lp, 1);
+			if (!regexp_h_cclass(ep, c,
+					(ep[-1] & 0377 & ~REGEXP_H_LEAST)
+					== (CCL|RNGE|CMB)))
+				return 0;
+		}
+		curlp = lp;
+		while (size--) {
+			regexp_h_push(&sb, &sp, &sc, lp);
+			c = regexp_h_fetch(lp, 1);
+			if (!regexp_h_cclass(ep, c,
+					(ep[-1] & 0377 & ~REGEXP_H_LEAST)
+					== (CCL|RNGE|CMB)))
+				break;
+		}
+		if (size < 0) {
+			regexp_h_push(&sb, &sp, &sc, lp);
+			regexp_h_fetch(lp, 1);
+		}
+		ep += (*ep & 0377) + 19;
+		goto star;
+#endif	/* REGEXP_H_WCHARS */
+
+	case CBACK:
+		bbeg = braslist[*ep & 0377];
+		ct = braelist[*ep++ & 0377] - bbeg;
+
+		if(strncmp(bbeg, lp, ct) == 0) {
+			lp += ct;
+			continue;
+		}
+		return(0);
+
+	case CBACK|STAR:
+		bbeg = braslist[*ep & 0377];
+		ct = braelist[*ep++ & 0377] - bbeg;
+		curlp = lp;
+		while(strncmp(bbeg, lp, ct) == 0)
+			lp += ct;
+
+		while(lp >= curlp) {
+			if(regexp_h_advance(lp, ep))	return(1);
+			lp -= ct;
+		}
+		return(0);
+
+
+	case CDOT|STAR:
+		curlp = lp;
+		do
+			regexp_h_push(&sb, &sp, &sc, lp);
+		while (*lp++);
+		goto star;
+
+#ifdef	REGEXP_H_WCHARS
+	case CDOT|STAR|CMB:
+		curlp = lp;
+		do
+			regexp_h_push(&sb, &sp, &sc, lp);
+		while ((c = regexp_h_fetch(lp, 1)) != L'\0' && c != WEOF);
+		goto star;
+#endif	/* REGEXP_H_WCHARS */
+
+	case CCHR|STAR:
+		curlp = lp;
+		do
+			regexp_h_push(&sb, &sp, &sc, lp);
+		while (*lp++ == *ep);
+		ep++;
+		goto star;
+
+#ifdef	REGEXP_H_WCHARS
+	case CCHR|STAR|CMB:
+	case CCH1|STAR:
+	case CCH2|STAR:
+	case CCH3|STAR:
+		curlp = lp;
+		d = regexp_h_fetch(ep, 0);
+		do
+			regexp_h_push(&sb, &sp, &sc, lp);
+		while (regexp_h_fetch(lp, 1) == d);
+		goto star;
+#endif	/* REGEXP_H_WCHARS */
+
+	case CCL|STAR:
+		curlp = lp;
+		do {
+			regexp_h_push(&sb, &sp, &sc, lp);
+			c = *lp++ & 0377;
+		} while(ISTHERE(c));
+		ep += 32;
+		goto star;
+
+#ifdef	REGEXP_H_WCHARS
+	case CCL|STAR|CMB:
+	case CNCL|STAR|CMB:
+		curlp = lp;
+		do {
+			regexp_h_push(&sb, &sp, &sc, lp);
+			c = regexp_h_fetch(lp, 1);
+		} while (regexp_h_cclass(ep, c, (ep[-1] & 0377)
+					== (CCL|STAR|CMB)));
+		ep += (*ep & 0377) + 17;
+		goto star;
+#endif	/* REGEXP_H_WCHARS */
+
+	star:
+#ifdef	REGEXP_H_WCHARS
+		if (regexp_h_wchars == 0) {
+#endif
+			do {
+				if(--lp == locs)
+					break;
+				if (regexp_h_advance(lp, ep))
+					return(1);
+			} while (lp > curlp);
+#ifdef	REGEXP_H_WCHARS
+		} else {
+			do {
+				lp = regexp_h_pop(&sb, &sp, &sc, lp);
+				if (lp <= locs)
+					break;
+				if (regexp_h_advance(lp, ep)) {
+					regexp_h_zerostak(&sb, &sp);
+					return(1);
+				}
+			} while (lp > curlp);
+			regexp_h_zerostak(&sb, &sp);
+		}
+#endif	/* REGEXP_H_WCHARS */
+		return(0);
+
+	}
+}
+
+static void
+regexp_h_getrnge(register const char *str, int least)
+{
+	low = *str++ & 0377;
+	size = least & REGEXP_H_LEAST ? /*20000*/INT_MAX : (*str & 0377) - low;
+}
+
+int
+advance(const char *lp, const char *ep)
+{
+	REGEXP_H_ADVANCE_INIT	/* skip past circf */
+	regexp_h_bol = lp;
+#ifdef	REGEXP_H_WCHARS
+	regexp_h_firstwc = NULL;
+#endif	/* REGEXP_H_WCHARS */
+	return regexp_h_advance(lp, ep);
+}