packages feed

regex-posix 0.94.2 → 0.94.4

raw patch · 14 files changed

+4319/−19 lines, 14 filesdep ~arraydep ~bytestringdep ~containersPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: array, bytestring, containers

API changes (from Hackage documentation)

Files

Text/Regex/Posix.hs view
@@ -68,6 +68,6 @@  getVersion_Text_Regex_Posix :: Version getVersion_Text_Regex_Posix =-  Version { versionBranch = [0,93,2]  -- Keep in sync with regex-posix.cabal+  Version { versionBranch = [0,94,4]  -- Keep in sync with regex-posix.cabal           , versionTags = ["unstable"]           }
Text/Regex/Posix/Wrap.hsc view
@@ -29,7 +29,7 @@ -- 2009-January : wrapMatchAll and wrapCount now adjust the execution -- option execNotBOL after the first result to take into account '\n' -- in the text immediately before the next matches. (version 0.93.3)--- +-- -- 2009-January : wrapMatchAll and wrapCount have been changed to -- return all non-overlapping matches, including empty matches even if -- they coincide with the end of the previous non-empty match.  The@@ -92,9 +92,7 @@ #ifdef HAVE_REGEX_H #define HAVE_REGCOMP 1 #else-#ifndef __NHC__-#include "HsRegexPosixConfig.h"-#else+#ifdef __NHC__ #define HAVE_REGEX_H 1 #define HAVE_REGCOMP 1 #endif@@ -102,11 +100,14 @@  #include <sys/types.h> +#ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 1+#endif+ #if HAVE_REGEX_H && HAVE_REGCOMP #include "regex.h" #else-#include "regex/regex.h"+#include "regex.h"  -- CFILES stuff is Hugs only {-# CFILES cbits/reallocf.c #-}
+ cbits/cclass.h view
@@ -0,0 +1,62 @@+/*-+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.+ * Copyright (c) 1992, 1993, 1994+ *	The Regents of the University of California.  All rights reserved.+ *+ * This code is derived from software contributed to Berkeley by+ * Henry Spencer.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. 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.+ * 3. All advertising materials mentioning features or use of this software+ *    must display the following acknowledgement:+ *	This product includes software developed by the University of+ *	California, Berkeley and its contributors.+ * 4. Neither the name of the University nor the names of its contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS OR CONTRIBUTORS 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.+ *+ *	@(#)cclass.h	8.3 (Berkeley) 3/20/94+ */+++typedef enum {CALNUM, CALPHA, CBLANK, CCNTRL, CDIGIT, CGRAPH,+	      CLOWER, CPRINT, CPUNCT, CSPACE, CUPPER, CXDIGIT} citype;++/* character-class table */+static struct cclass {+	char *name;+	citype fidx;+} cclasses[] = {+	{"alnum",       CALNUM},+	{"alpha",       CALPHA},+	{"blank",       CBLANK},+	{"cntrl",       CCNTRL},+	{"digit",       CDIGIT},+	{"graph",       CGRAPH},+	{"lower",       CLOWER},+	{"print",       CPRINT},+	{"punct",       CPUNCT},+	{"space",       CSPACE},+	{"upper",       CUPPER},+	{"xdigit",      CXDIGIT},+	{NULL,          }+};
+ cbits/cname.h view
@@ -0,0 +1,141 @@+/*-+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.+ * Copyright (c) 1992, 1993, 1994+ *	The Regents of the University of California.  All rights reserved.+ *+ * This code is derived from software contributed to Berkeley by+ * Henry Spencer.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. 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.+ * 3. All advertising materials mentioning features or use of this software+ *    must display the following acknowledgement:+ *	This product includes software developed by the University of+ *	California, Berkeley and its contributors.+ * 4. Neither the name of the University nor the names of its contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS OR CONTRIBUTORS 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.+ *+ *	@(#)cname.h	8.3 (Berkeley) 3/20/94+ */++/* character-name table */+static struct cname {+	char *name;+	char code;+} cnames[] = {+	{"NUL",			'\0'},+	{"SOH",			'\001'},+	{"STX",			'\002'},+	{"ETX",			'\003'},+	{"EOT",			'\004'},+	{"ENQ",			'\005'},+	{"ACK",			'\006'},+	{"BEL",			'\007'},+	{"alert",		'\007'},+	{"BS",			'\010'},+	{"backspace",		'\b'},+	{"HT",			'\011'},+	{"tab",			'\t'},+	{"LF",			'\012'},+	{"newline",		'\n'},+	{"VT",			'\013'},+	{"vertical-tab",	'\v'},+	{"FF",			'\014'},+	{"form-feed",		'\f'},+	{"CR",			'\015'},+	{"carriage-return",	'\r'},+	{"SO",			'\016'},+	{"SI",			'\017'},+	{"DLE",			'\020'},+	{"DC1",			'\021'},+	{"DC2",			'\022'},+	{"DC3",			'\023'},+	{"DC4",			'\024'},+	{"NAK",			'\025'},+	{"SYN",			'\026'},+	{"ETB",			'\027'},+	{"CAN",			'\030'},+	{"EM",			'\031'},+	{"SUB",			'\032'},+	{"ESC",			'\033'},+	{"IS4",			'\034'},+	{"FS",			'\034'},+	{"IS3",			'\035'},+	{"GS",			'\035'},+	{"IS2",			'\036'},+	{"RS",			'\036'},+	{"IS1",			'\037'},+	{"US",			'\037'},+	{"space",		' '},+	{"exclamation-mark",	'!'},+	{"quotation-mark",	'"'},+	{"number-sign",		'#'},+	{"dollar-sign",		'$'},+	{"percent-sign",	'%'},+	{"ampersand",		'&'},+	{"apostrophe",		'\''},+	{"left-parenthesis",	'('},+	{"right-parenthesis",	')'},+	{"asterisk",		'*'},+	{"plus-sign",		'+'},+	{"comma",		','},+	{"hyphen",		'-'},+	{"hyphen-minus",	'-'},+	{"period",		'.'},+	{"full-stop",		'.'},+	{"slash",		'/'},+	{"solidus",		'/'},+	{"zero",		'0'},+	{"one",			'1'},+	{"two",			'2'},+	{"three",		'3'},+	{"four",		'4'},+	{"five",		'5'},+	{"six",			'6'},+	{"seven",      		'7'},+	{"eight",		'8'},+	{"nine",		'9'},+	{"colon",		':'},+	{"semicolon",		';'},+	{"less-than-sign",	'<'},+	{"equals-sign",		'='},+	{"greater-than-sign",	'>'},+	{"question-mark",	'?'},+	{"commercial-at",	'@'},+	{"left-square-bracket",	'['},+	{"backslash",		'\\'},+	{"reverse-solidus",	'\\'},+	{"right-square-bracket",']'},+	{"circumflex",		'^'},+	{"circumflex-accent",	'^'},+	{"underscore",		'_'},+	{"low-line",		'_'},+	{"grave-accent",	'`'},+	{"left-brace",		'{'},+	{"left-curly-bracket",	'{'},+	{"vertical-line",	'|'},+	{"right-brace",		'}'},+	{"right-curly-bracket",	'}'},+	{"tilde",		'~'},+	{"DEL",	'\177'},+	{NULL,	0}+};
+ cbits/engine.c view
@@ -0,0 +1,1139 @@+/*-+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.+ * Copyright (c) 1992, 1993, 1994+ *	The Regents of the University of California.  All rights reserved.+ *+ * This code is derived from software contributed to Berkeley by+ * Henry Spencer.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. 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.+ * 3. All advertising materials mentioning features or use of this software+ *    must display the following acknowledgement:+ *	This product includes software developed by the University of+ *	California, Berkeley and its contributors.+ * 4. Neither the name of the University nor the names of its contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS OR CONTRIBUTORS 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.+ *+ *	@(#)engine.c	8.5 (Berkeley) 3/20/94+ *+ * $FreeBSD: src/lib/libc/regex/engine.c,v 1.5.8.1 2000/07/31 06:30:37 dcs Exp $+ */++/*+ * The matching engine and friends.  This file is #included by regexec.c+ * after suitable #defines of a variety of macros used herein, so that+ * different state representations can be used without duplicating masses+ * of code.+ */++#ifdef SNAMES+#define	matcher	smatcher+#define	fast	sfast+#define	slow	sslow+#define	dissect	sdissect+#define	backref	sbackref+#define	step	sstep+#define	print	sprint+#define	at	sat+#define	match	smat+#endif+#ifdef LNAMES+#define	matcher	lmatcher+#define	fast	lfast+#define	slow	lslow+#define	dissect	ldissect+#define	backref	lbackref+#define	step	lstep+#define	print	lprint+#define	at	lat+#define	match	lmat+#endif++/* another structure passed up and down to avoid zillions of parameters */+struct match {+	struct re_guts *g;+	int eflags;+	regmatch_t *pmatch;	/* [nsub+1] (0 element unused) */+	char *offp;		/* offsets work from here */+	char *beginp;		/* start of string -- virtual NUL precedes */+	char *endp;		/* end of string -- virtual NUL here */+	char *coldp;		/* can be no match starting before here */+	char **lastpos;		/* [nplus+1] */+	STATEVARS;+	states st;		/* current states */+	states fresh;		/* states for a fresh start */+	states tmp;		/* temporary */+	states empty;		/* empty set of states */+};++/* ========= begin header generated by ./mkh ========= */+#ifdef __cplusplus+extern "C" {+#endif++/* === engine.c === */+static int matcher (struct re_guts *g, char *string, size_t nmatch, regmatch_t pmatch[], int eflags);+static char *dissect (struct match *m, char *start, char *stop, sopno startst, sopno stopst);+static char *backref (struct match *m, char *start, char *stop, sopno startst, sopno stopst, sopno lev);+static char *fast (struct match *m, char *start, char *stop, sopno startst, sopno stopst);+static char *slow (struct match *m, char *start, char *stop, sopno startst, sopno stopst);+static states step (struct re_guts *g, sopno start, sopno stop, states bef, int ch, states aft);+#define	BOL	(OUT+1)+#define	EOL	(BOL+1)+#define	BOLEOL	(BOL+2)+#define	NOTHING	(BOL+3)+#define	BOW	(BOL+4)+#define	EOW	(BOL+5)+#define	CODEMAX	(BOL+5)		/* highest code used */+#define	NONCHAR(c)	((c) > CHAR_MAX)+#define	NNONCHAR	(CODEMAX-CHAR_MAX)+#ifdef REDEBUG+static void print (struct match *m, char *caption, states st, int ch, FILE *d);+#endif+#ifdef REDEBUG+static void at __P((struct match *m, char *title, char *start, char *stop, sopno startst, sopno stopst));+#endif+#ifdef REDEBUG+static char *pchar __P((int ch));+#endif++#ifdef __cplusplus+}+#endif+/* ========= end header generated by ./mkh ========= */++#ifdef REDEBUG+#define	SP(t, s, c)	print(m, t, s, c, stdout)+#define	AT(t, p1, p2, s1, s2)	at(m, t, p1, p2, s1, s2)+#define	NOTE(str)	{ if (m->eflags&REG_TRACE) printf("=%s\n", (str)); }+#else+#define	SP(t, s, c)	/* nothing */+#define	AT(t, p1, p2, s1, s2)	/* nothing */+#define	NOTE(s)	/* nothing */+#endif++/*+ - matcher - the actual matching engine+ == static int matcher(register struct re_guts *g, char *string, \+ ==	size_t nmatch, regmatch_t pmatch[], int eflags);+ */+static int			/* 0 success, REG_NOMATCH failure */+matcher(g, string, nmatch, pmatch, eflags)+register struct re_guts *g;+char *string;+size_t nmatch;+regmatch_t pmatch[];+int eflags;+{+	register char *endp;+	register int i;+	struct match mv;+	register struct match *m = &mv;+	register char *dp;+	register const sopno gf = g->firststate+1;	/* +1 for OEND */+	register const sopno gl = g->laststate;+	char *start;+	char *stop;+	/* Boyer-Moore algorithms variables */+	register char *pp;+	int cj, mj;+	register char *mustfirst;+	register char *mustlast;+	register int *matchjump;+	register int *charjump;++	/* simplify the situation where possible */+	if (g->cflags&REG_NOSUB)+		nmatch = 0;+	if (eflags&REG_STARTEND) {+		start = string + pmatch[0].rm_so;+		stop = string + pmatch[0].rm_eo;+	} else {+		start = string;+		stop = start + strlen(start);+	}+	if (stop < start)+		return(REG_INVARG);++	/* prescreening; this does wonders for this rather slow code */+	if (g->must != NULL) {+		if (g->charjump != NULL && g->matchjump != NULL) {+			mustfirst = g->must;+			mustlast = g->must + g->mlen - 1;+			charjump = g->charjump;+			matchjump = g->matchjump;+			pp = mustlast;+			for (dp = start+g->mlen-1; dp < stop;) {+				/* Fast skip non-matches */+				while (dp < stop && charjump[*dp])+					dp += charjump[*dp];++				if (dp >= stop)+					break;++				/* Greedy matcher */+				/* We depend on not being used for+				 * for strings of length 1+				 */+				while (*--dp == *--pp && pp != mustfirst);++				if (*dp == *pp)+					break;++				/* Jump to next possible match */+				mj = matchjump[pp - mustfirst];+				cj = charjump[*dp];+				dp += (cj < mj ? mj : cj);+				pp = mustlast;+			}+			if (pp != mustfirst)+				return(REG_NOMATCH);+		} else {+			for (dp = start; dp < stop; dp++)+				if (*dp == g->must[0] &&+				    stop - dp >= g->mlen &&+				    memcmp(dp, g->must, (size_t)g->mlen) == 0)+					break;+			if (dp == stop)		/* we didn't find g->must */+				return(REG_NOMATCH);+		}+	}++	/* match struct setup */+	m->g = g;+	m->eflags = eflags;+	m->pmatch = NULL;+	m->lastpos = NULL;+	m->offp = string;+	m->beginp = start;+	m->endp = stop;+	STATESETUP(m, 4);+	SETUP(m->st);+	SETUP(m->fresh);+	SETUP(m->tmp);+	SETUP(m->empty);+	CLEAR(m->empty);++	/* Adjust start according to moffset, to speed things up */+	if (g->moffset > -1)+		start = ((dp - g->moffset) < start) ? start : dp - g->moffset;++	/* this loop does only one repetition except for backrefs */+	for (;;) {+		endp = fast(m, start, stop, gf, gl);+		if (endp == NULL) {		/* a miss */+			STATETEARDOWN(m);+			return(REG_NOMATCH);+		}+		if (nmatch == 0 && !g->backrefs)+			break;		/* no further info needed */++		/* where? */+		assert(m->coldp != NULL);+		for (;;) {+			NOTE("finding start");+			endp = slow(m, m->coldp, stop, gf, gl);+			if (endp != NULL)+				break;+			assert(m->coldp < m->endp);+			m->coldp++;+		}+		if (nmatch == 1 && !g->backrefs)+			break;		/* no further info needed */++		/* oh my, he wants the subexpressions... */+		if (m->pmatch == NULL)+			m->pmatch = (regmatch_t *)malloc((m->g->nsub + 1) *+							sizeof(regmatch_t));+		if (m->pmatch == NULL) {+			STATETEARDOWN(m);+			return(REG_ESPACE);+		}+		for (i = 1; i <= m->g->nsub; i++)+			m->pmatch[i].rm_so = m->pmatch[i].rm_eo = -1;+		if (!g->backrefs && !(m->eflags&REG_BACKR)) {+			NOTE("dissecting");+			dp = dissect(m, m->coldp, endp, gf, gl);+		} else {+			if (g->nplus > 0 && m->lastpos == NULL)+				m->lastpos = (char **)malloc((g->nplus+1) *+							sizeof(char *));+			if (g->nplus > 0 && m->lastpos == NULL) {+				free(m->pmatch);+				STATETEARDOWN(m);+				return(REG_ESPACE);+			}+			NOTE("backref dissect");+			dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);+		}+		if (dp != NULL)+			break;++		/* uh-oh... we couldn't find a subexpression-level match */+		assert(g->backrefs);	/* must be back references doing it */+		assert(g->nplus == 0 || m->lastpos != NULL);+		for (;;) {+			if (dp != NULL || endp <= m->coldp)+				break;		/* defeat */+			NOTE("backoff");+			endp = slow(m, m->coldp, endp-1, gf, gl);+			if (endp == NULL)+				break;		/* defeat */+			/* try it on a shorter possibility */+#ifndef NDEBUG+			for (i = 1; i <= m->g->nsub; i++) {+				assert(m->pmatch[i].rm_so == -1);+				assert(m->pmatch[i].rm_eo == -1);+			}+#endif+			NOTE("backoff dissect");+			dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);+		}+		assert(dp == NULL || dp == endp);+		if (dp != NULL)		/* found a shorter one */+			break;++		/* despite initial appearances, there is no match here */+		NOTE("false alarm");+		start = m->coldp + 1;	/* recycle starting later */+		assert(start <= stop);+	}++	/* fill in the details if requested */+	if (nmatch > 0) {+		pmatch[0].rm_so = m->coldp - m->offp;+		pmatch[0].rm_eo = endp - m->offp;+	}+	if (nmatch > 1) {+		assert(m->pmatch != NULL);+		for (i = 1; i < nmatch; i++)+			if (i <= m->g->nsub)+				pmatch[i] = m->pmatch[i];+			else {+				pmatch[i].rm_so = -1;+				pmatch[i].rm_eo = -1;+			}+	}++	if (m->pmatch != NULL)+		free((char *)m->pmatch);+	if (m->lastpos != NULL)+		free((char *)m->lastpos);+	STATETEARDOWN(m);+	return(0);+}++/*+ - dissect - figure out what matched what, no back references+ == static char *dissect(register struct match *m, char *start, \+ ==	char *stop, sopno startst, sopno stopst);+ */+static char *			/* == stop (success) always */+dissect(m, start, stop, startst, stopst)+register struct match *m;+char *start;+char *stop;+sopno startst;+sopno stopst;+{+	register int i;+	register sopno ss;	/* start sop of current subRE */+	register sopno es;	/* end sop of current subRE */+	register char *sp;	/* start of string matched by it */+	register char *stp;	/* string matched by it cannot pass here */+	register char *rest;	/* start of rest of string */+	register char *tail;	/* string unmatched by rest of RE */+	register sopno ssub;	/* start sop of subsubRE */+	register sopno esub;	/* end sop of subsubRE */+	register char *ssp;	/* start of string matched by subsubRE */+	register char *sep;	/* end of string matched by subsubRE */+	register char *oldssp;	/* previous ssp */+	register char *dp;++	AT("diss", start, stop, startst, stopst);+	sp = start;+	for (ss = startst; ss < stopst; ss = es) {+		/* identify end of subRE */+		es = ss;+		switch (OP(m->g->strip[es])) {+		case OPLUS_:+		case OQUEST_:+			es += OPND(m->g->strip[es]);+			break;+		case OCH_:+			while (OP(m->g->strip[es]) != O_CH)+				es += OPND(m->g->strip[es]);+			break;+		}+		es++;++		/* figure out what it matched */+		switch (OP(m->g->strip[ss])) {+		case OEND:+			assert(nope);+			break;+		case OCHAR:+			sp++;+			break;+		case OBOL:+		case OEOL:+		case OBOW:+		case OEOW:+			break;+		case OANY:+		case OANYOF:+			sp++;+			break;+		case OBACK_:+		case O_BACK:+			assert(nope);+			break;+		/* cases where length of match is hard to find */+		case OQUEST_:+			stp = stop;+			for (;;) {+				/* how long could this one be? */+				rest = slow(m, sp, stp, ss, es);+				assert(rest != NULL);	/* it did match */+				/* could the rest match the rest? */+				tail = slow(m, rest, stop, es, stopst);+				if (tail == stop)+					break;		/* yes! */+				/* no -- try a shorter match for this one */+				stp = rest - 1;+				assert(stp >= sp);	/* it did work */+			}+			ssub = ss + 1;+			esub = es - 1;+			/* did innards match? */+			if (slow(m, sp, rest, ssub, esub) != NULL) {+				dp = dissect(m, sp, rest, ssub, esub);+				assert(dp == rest);+			} else		/* no */+				assert(sp == rest);+			sp = rest;+			break;+		case OPLUS_:+			stp = stop;+			for (;;) {+				/* how long could this one be? */+				rest = slow(m, sp, stp, ss, es);+				assert(rest != NULL);	/* it did match */+				/* could the rest match the rest? */+				tail = slow(m, rest, stop, es, stopst);+				if (tail == stop)+					break;		/* yes! */+				/* no -- try a shorter match for this one */+				stp = rest - 1;+				assert(stp >= sp);	/* it did work */+			}+			ssub = ss + 1;+			esub = es - 1;+			ssp = sp;+			oldssp = ssp;+			for (;;) {	/* find last match of innards */+				sep = slow(m, ssp, rest, ssub, esub);+				if (sep == NULL || sep == ssp)+					break;	/* failed or matched null */+				oldssp = ssp;	/* on to next try */+				ssp = sep;+			}+			if (sep == NULL) {+				/* last successful match */+				sep = ssp;+				ssp = oldssp;+			}+			assert(sep == rest);	/* must exhaust substring */+			assert(slow(m, ssp, sep, ssub, esub) == rest);+			dp = dissect(m, ssp, sep, ssub, esub);+			assert(dp == sep);+			sp = rest;+			break;+		case OCH_:+			stp = stop;+			for (;;) {+				/* how long could this one be? */+				rest = slow(m, sp, stp, ss, es);+				assert(rest != NULL);	/* it did match */+				/* could the rest match the rest? */+				tail = slow(m, rest, stop, es, stopst);+				if (tail == stop)+					break;		/* yes! */+				/* no -- try a shorter match for this one */+				stp = rest - 1;+				assert(stp >= sp);	/* it did work */+			}+			ssub = ss + 1;+			esub = ss + OPND(m->g->strip[ss]) - 1;+			assert(OP(m->g->strip[esub]) == OOR1);+			for (;;) {	/* find first matching branch */+				if (slow(m, sp, rest, ssub, esub) == rest)+					break;	/* it matched all of it */+				/* that one missed, try next one */+				assert(OP(m->g->strip[esub]) == OOR1);+				esub++;+				assert(OP(m->g->strip[esub]) == OOR2);+				ssub = esub + 1;+				esub += OPND(m->g->strip[esub]);+				if (OP(m->g->strip[esub]) == OOR2)+					esub--;+				else+					assert(OP(m->g->strip[esub]) == O_CH);+			}+			dp = dissect(m, sp, rest, ssub, esub);+			assert(dp == rest);+			sp = rest;+			break;+		case O_PLUS:+		case O_QUEST:+		case OOR1:+		case OOR2:+		case O_CH:+			assert(nope);+			break;+		case OLPAREN:+			i = OPND(m->g->strip[ss]);+			assert(0 < i && i <= m->g->nsub);+			m->pmatch[i].rm_so = sp - m->offp;+			break;+		case ORPAREN:+			i = OPND(m->g->strip[ss]);+			assert(0 < i && i <= m->g->nsub);+			m->pmatch[i].rm_eo = sp - m->offp;+			break;+		default:		/* uh oh */+			assert(nope);+			break;+		}+	}++	assert(sp == stop);+	return(sp);+}++/*+ - backref - figure out what matched what, figuring in back references+ == static char *backref(register struct match *m, char *start, \+ ==	char *stop, sopno startst, sopno stopst, sopno lev);+ */+static char *			/* == stop (success) or NULL (failure) */+backref(m, start, stop, startst, stopst, lev)+register struct match *m;+char *start;+char *stop;+sopno startst;+sopno stopst;+sopno lev;			/* PLUS nesting level */+{+	register int i;+	register sopno ss;	/* start sop of current subRE */+	register char *sp;	/* start of string matched by it */+	register sopno ssub;	/* start sop of subsubRE */+	register sopno esub;	/* end sop of subsubRE */+	register char *ssp;	/* start of string matched by subsubRE */+	register char *dp;+	register size_t len;+	register int hard;+	register sop s;+	register regoff_t offsave;+	register cset *cs;++	AT("back", start, stop, startst, stopst);+	sp = start;++	/* get as far as we can with easy stuff */+	hard = 0;+	for (ss = startst; !hard && ss < stopst; ss++)+		switch (OP(s = m->g->strip[ss])) {+		case OCHAR:+			if (sp == stop || *sp++ != (char)OPND(s))+				return(NULL);+			break;+		case OANY:+			if (sp == stop)+				return(NULL);+			sp++;+			break;+		case OANYOF:+			cs = &m->g->sets[OPND(s)];+			if (sp == stop || !CHIN(cs, *sp++))+				return(NULL);+			break;+		case OBOL:+			if ( (sp == m->beginp && !(m->eflags&REG_NOTBOL)) ||+					(sp < m->endp && *(sp-1) == '\n' &&+						(m->g->cflags&REG_NEWLINE)) )+				{ /* yes */ }+			else+				return(NULL);+			break;+		case OEOL:+			if ( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||+					(sp < m->endp && *sp == '\n' &&+						(m->g->cflags&REG_NEWLINE)) )+				{ /* yes */ }+			else+				return(NULL);+			break;+		case OBOW:+			if (( (sp == m->beginp && !(m->eflags&REG_NOTBOL)) ||+					(sp < m->endp && *(sp-1) == '\n' &&+						(m->g->cflags&REG_NEWLINE)) ||+					(sp > m->beginp &&+							!ISWORD(*(sp-1))) ) &&+					(sp < m->endp && ISWORD(*sp)) )+				{ /* yes */ }+			else+				return(NULL);+			break;+		case OEOW:+			if (( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||+					(sp < m->endp && *sp == '\n' &&+						(m->g->cflags&REG_NEWLINE)) ||+					(sp < m->endp && !ISWORD(*sp)) ) &&+					(sp > m->beginp && ISWORD(*(sp-1))) )+				{ /* yes */ }+			else+				return(NULL);+			break;+		case O_QUEST:+			break;+		case OOR1:	/* matches null but needs to skip */+			ss++;+			s = m->g->strip[ss];+			do {+				assert(OP(s) == OOR2);+				ss += OPND(s);+			} while (OP(s = m->g->strip[ss]) != O_CH);+			/* note that the ss++ gets us past the O_CH */+			break;+		default:	/* have to make a choice */+			hard = 1;+			break;+		}+	if (!hard) {		/* that was it! */+		if (sp != stop)+			return(NULL);+		return(sp);+	}+	ss--;			/* adjust for the for's final increment */++	/* the hard stuff */+	AT("hard", sp, stop, ss, stopst);+	s = m->g->strip[ss];+	switch (OP(s)) {+	case OBACK_:		/* the vilest depths */+		i = OPND(s);+		assert(0 < i && i <= m->g->nsub);+		if (m->pmatch[i].rm_eo == -1)+			return(NULL);+		assert(m->pmatch[i].rm_so != -1);+		len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so;+		assert(stop - m->beginp >= len);+		if (sp > stop - len)+			return(NULL);	/* not enough left to match */+		ssp = m->offp + m->pmatch[i].rm_so;+		if (memcmp(sp, ssp, len) != 0)+			return(NULL);+		while (m->g->strip[ss] != SOP(O_BACK, i))+			ss++;+		return(backref(m, sp+len, stop, ss+1, stopst, lev));+		break;+	case OQUEST_:		/* to null or not */+		dp = backref(m, sp, stop, ss+1, stopst, lev);+		if (dp != NULL)+			return(dp);	/* not */+		return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev));+		break;+	case OPLUS_:+		assert(m->lastpos != NULL);+		assert(lev+1 <= m->g->nplus);+		m->lastpos[lev+1] = sp;+		return(backref(m, sp, stop, ss+1, stopst, lev+1));+		break;+	case O_PLUS:+		if (sp == m->lastpos[lev])	/* last pass matched null */+			return(backref(m, sp, stop, ss+1, stopst, lev-1));+		/* try another pass */+		m->lastpos[lev] = sp;+		dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev);+		if (dp == NULL)+			return(backref(m, sp, stop, ss+1, stopst, lev-1));+		else+			return(dp);+		break;+	case OCH_:		/* find the right one, if any */+		ssub = ss + 1;+		esub = ss + OPND(s) - 1;+		assert(OP(m->g->strip[esub]) == OOR1);+		for (;;) {	/* find first matching branch */+			dp = backref(m, sp, stop, ssub, esub, lev);+			if (dp != NULL)+				return(dp);+			/* that one missed, try next one */+			if (OP(m->g->strip[esub]) == O_CH)+				return(NULL);	/* there is none */+			esub++;+			assert(OP(m->g->strip[esub]) == OOR2);+			ssub = esub + 1;+			esub += OPND(m->g->strip[esub]);+			if (OP(m->g->strip[esub]) == OOR2)+				esub--;+			else+				assert(OP(m->g->strip[esub]) == O_CH);+		}+		break;+	case OLPAREN:		/* must undo assignment if rest fails */+		i = OPND(s);+		assert(0 < i && i <= m->g->nsub);+		offsave = m->pmatch[i].rm_so;+		m->pmatch[i].rm_so = sp - m->offp;+		dp = backref(m, sp, stop, ss+1, stopst, lev);+		if (dp != NULL)+			return(dp);+		m->pmatch[i].rm_so = offsave;+		return(NULL);+		break;+	case ORPAREN:		/* must undo assignment if rest fails */+		i = OPND(s);+		assert(0 < i && i <= m->g->nsub);+		offsave = m->pmatch[i].rm_eo;+		m->pmatch[i].rm_eo = sp - m->offp;+		dp = backref(m, sp, stop, ss+1, stopst, lev);+		if (dp != NULL)+			return(dp);+		m->pmatch[i].rm_eo = offsave;+		return(NULL);+		break;+	default:		/* uh oh */+		assert(nope);+		break;+	}++	/* "can't happen" */+	assert(nope);+	/* NOTREACHED */+	return "shut up gcc";+}++/*+ - fast - step through the string at top speed+ == static char *fast(register struct match *m, char *start, \+ ==	char *stop, sopno startst, sopno stopst);+ */+static char *			/* where tentative match ended, or NULL */+fast(m, start, stop, startst, stopst)+register struct match *m;+char *start;+char *stop;+sopno startst;+sopno stopst;+{+	register states st = m->st;+	register states fresh = m->fresh;+	register states tmp = m->tmp;+	register char *p = start;+	register int c = (start == m->beginp) ? OUT : *(start-1);+	register int lastc;	/* previous c */+	register int flagch;+	register int i;+	register char *coldp;	/* last p after which no match was underway */++	CLEAR(st);+	SET1(st, startst);+	st = step(m->g, startst, stopst, st, NOTHING, st);+	ASSIGN(fresh, st);+	SP("start", st, *p);+	coldp = NULL;+	for (;;) {+		/* next character */+		lastc = c;+		c = (p == m->endp) ? OUT : *p;+		if (EQ(st, fresh))+			coldp = p;++		/* is there an EOL and/or BOL between lastc and c? */+		flagch = '\0';+		i = 0;+		if ( (lastc == '\n' && m->g->cflags&REG_NEWLINE) ||+				(lastc == OUT && !(m->eflags&REG_NOTBOL)) ) {+			flagch = BOL;+			i = m->g->nbol;+		}+		if ( (c == '\n' && m->g->cflags&REG_NEWLINE) ||+				(c == OUT && !(m->eflags&REG_NOTEOL)) ) {+			flagch = (flagch == BOL) ? BOLEOL : EOL;+			i += m->g->neol;+		}+		if (i != 0) {+			for (; i > 0; i--)+				st = step(m->g, startst, stopst, st, flagch, st);+			SP("boleol", st, c);+		}++		/* how about a word boundary? */+		if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) &&+					(c != OUT && ISWORD(c)) ) {+			flagch = BOW;+		}+		if ( (lastc != OUT && ISWORD(lastc)) &&+				(flagch == EOL || (c != OUT && !ISWORD(c))) ) {+			flagch = EOW;+		}+		if (flagch == BOW || flagch == EOW) {+			st = step(m->g, startst, stopst, st, flagch, st);+			SP("boweow", st, c);+		}++		/* are we done? */+		if (ISSET(st, stopst) || p == stop)+			break;		/* NOTE BREAK OUT */++		/* no, we must deal with this character */+		ASSIGN(tmp, st);+		ASSIGN(st, fresh);+		assert(c != OUT);+		st = step(m->g, startst, stopst, tmp, c, st);+		SP("aft", st, c);+		assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st));+		p++;+	}++	assert(coldp != NULL);+	m->coldp = coldp;+	if (ISSET(st, stopst))+		return(p+1);+	else+		return(NULL);+}++/*+ - slow - step through the string more deliberately+ == static char *slow(register struct match *m, char *start, \+ ==	char *stop, sopno startst, sopno stopst);+ */+static char *			/* where it ended */+slow(m, start, stop, startst, stopst)+register struct match *m;+char *start;+char *stop;+sopno startst;+sopno stopst;+{+	register states st = m->st;+	register states empty = m->empty;+	register states tmp = m->tmp;+	register char *p = start;+	register int c = (start == m->beginp) ? OUT : *(start-1);+	register int lastc;	/* previous c */+	register int flagch;+	register int i;+	register char *matchp;	/* last p at which a match ended */++	AT("slow", start, stop, startst, stopst);+	CLEAR(st);+	SET1(st, startst);+	SP("sstart", st, *p);+	st = step(m->g, startst, stopst, st, NOTHING, st);+	matchp = NULL;+	for (;;) {+		/* next character */+		lastc = c;+		c = (p == m->endp) ? OUT : *p;++		/* is there an EOL and/or BOL between lastc and c? */+		flagch = '\0';+		i = 0;+		if ( (lastc == '\n' && m->g->cflags&REG_NEWLINE) ||+				(lastc == OUT && !(m->eflags&REG_NOTBOL)) ) {+			flagch = BOL;+			i = m->g->nbol;+		}+		if ( (c == '\n' && m->g->cflags&REG_NEWLINE) ||+				(c == OUT && !(m->eflags&REG_NOTEOL)) ) {+			flagch = (flagch == BOL) ? BOLEOL : EOL;+			i += m->g->neol;+		}+		if (i != 0) {+			for (; i > 0; i--)+				st = step(m->g, startst, stopst, st, flagch, st);+			SP("sboleol", st, c);+		}++		/* how about a word boundary? */+		if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) &&+					(c != OUT && ISWORD(c)) ) {+			flagch = BOW;+		}+		if ( (lastc != OUT && ISWORD(lastc)) &&+				(flagch == EOL || (c != OUT && !ISWORD(c))) ) {+			flagch = EOW;+		}+		if (flagch == BOW || flagch == EOW) {+			st = step(m->g, startst, stopst, st, flagch, st);+			SP("sboweow", st, c);+		}++		/* are we done? */+		if (ISSET(st, stopst))+			matchp = p;+		if (EQ(st, empty) || p == stop)+			break;		/* NOTE BREAK OUT */++		/* no, we must deal with this character */+		ASSIGN(tmp, st);+		ASSIGN(st, empty);+		assert(c != OUT);+		st = step(m->g, startst, stopst, tmp, c, st);+		SP("saft", st, c);+		assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st));+		p++;+	}++	return(matchp);+}+++/*+ - step - map set of states reachable before char to set reachable after+ == static states step(register struct re_guts *g, sopno start, sopno stop, \+ ==	register states bef, int ch, register states aft);+ == #define	BOL	(OUT+1)+ == #define	EOL	(BOL+1)+ == #define	BOLEOL	(BOL+2)+ == #define	NOTHING	(BOL+3)+ == #define	BOW	(BOL+4)+ == #define	EOW	(BOL+5)+ == #define	CODEMAX	(BOL+5)		// highest code used+ == #define	NONCHAR(c)	((c) > CHAR_MAX)+ == #define	NNONCHAR	(CODEMAX-CHAR_MAX)+ */+static states+step(g, start, stop, bef, ch, aft)+register struct re_guts *g;+sopno start;			/* start state within strip */+sopno stop;			/* state after stop state within strip */+register states bef;		/* states reachable before */+int ch;				/* character or NONCHAR code */+register states aft;		/* states already known reachable after */+{+	register cset *cs;+	register sop s;+	register sopno pc;+	register onestate here;		/* note, macros know this name */+	register sopno look;+	register int i;++	for (pc = start, INIT(here, pc); pc != stop; pc++, INC(here)) {+		s = g->strip[pc];+		switch (OP(s)) {+		case OEND:+			assert(pc == stop-1);+			break;+		case OCHAR:+			/* only characters can match */+			assert(!NONCHAR(ch) || ch != (char)OPND(s));+			if (ch == (char)OPND(s))+				FWD(aft, bef, 1);+			break;+		case OBOL:+			if (ch == BOL || ch == BOLEOL)+				FWD(aft, bef, 1);+			break;+		case OEOL:+			if (ch == EOL || ch == BOLEOL)+				FWD(aft, bef, 1);+			break;+		case OBOW:+			if (ch == BOW)+				FWD(aft, bef, 1);+			break;+		case OEOW:+			if (ch == EOW)+				FWD(aft, bef, 1);+			break;+		case OANY:+			if (!NONCHAR(ch))+				FWD(aft, bef, 1);+			break;+		case OANYOF:+			cs = &g->sets[OPND(s)];+			if (!NONCHAR(ch) && CHIN(cs, ch))+				FWD(aft, bef, 1);+			break;+		case OBACK_:		/* ignored here */+		case O_BACK:+			FWD(aft, aft, 1);+			break;+		case OPLUS_:		/* forward, this is just an empty */+			FWD(aft, aft, 1);+			break;+		case O_PLUS:		/* both forward and back */+			FWD(aft, aft, 1);+			i = ISSETBACK(aft, OPND(s));+			BACK(aft, aft, OPND(s));+			if (!i && ISSETBACK(aft, OPND(s))) {+				/* oho, must reconsider loop body */+				pc -= OPND(s) + 1;+				INIT(here, pc);+			}+			break;+		case OQUEST_:		/* two branches, both forward */+			FWD(aft, aft, 1);+			FWD(aft, aft, OPND(s));+			break;+		case O_QUEST:		/* just an empty */+			FWD(aft, aft, 1);+			break;+		case OLPAREN:		/* not significant here */+		case ORPAREN:+			FWD(aft, aft, 1);+			break;+		case OCH_:		/* mark the first two branches */+			FWD(aft, aft, 1);+			assert(OP(g->strip[pc+OPND(s)]) == OOR2);+			FWD(aft, aft, OPND(s));+			break;+		case OOR1:		/* done a branch, find the O_CH */+			if (ISSTATEIN(aft, here)) {+				for (look = 1;+						OP(s = g->strip[pc+look]) != O_CH;+						look += OPND(s))+					assert(OP(s) == OOR2);+				FWD(aft, aft, look);+			}+			break;+		case OOR2:		/* propagate OCH_'s marking */+			FWD(aft, aft, 1);+			if (OP(g->strip[pc+OPND(s)]) != O_CH) {+				assert(OP(g->strip[pc+OPND(s)]) == OOR2);+				FWD(aft, aft, OPND(s));+			}+			break;+		case O_CH:		/* just empty */+			FWD(aft, aft, 1);+			break;+		default:		/* ooooops... */+			assert(nope);+			break;+		}+	}++	return(aft);+}++#ifdef REDEBUG+/*+ - print - print a set of states+ == #ifdef REDEBUG+ == static void print(struct match *m, char *caption, states st, \+ ==	int ch, FILE *d);+ == #endif+ */+static void+print(m, caption, st, ch, d)+struct match *m;+char *caption;+states st;+int ch;+FILE *d;+{+	register struct re_guts *g = m->g;+	register int i;+	register int first = 1;++	if (!(m->eflags&REG_TRACE))+		return;++	fprintf(d, "%s", caption);+	if (ch != '\0')+		fprintf(d, " %s", pchar(ch));+	for (i = 0; i < g->nstates; i++)+		if (ISSET(st, i)) {+			fprintf(d, "%s%d", (first) ? "\t" : ", ", i);+			first = 0;+		}+	fprintf(d, "\n");+}++/*+ - at - print current situation+ == #ifdef REDEBUG+ == static void at(struct match *m, char *title, char *start, char *stop, \+ ==						sopno startst, sopno stopst);+ == #endif+ */+static void+at(m, title, start, stop, startst, stopst)+struct match *m;+char *title;+char *start;+char *stop;+sopno startst;+sopno stopst;+{+	if (!(m->eflags&REG_TRACE))+		return;++	printf("%s %s-", title, pchar(*start));+	printf("%s ", pchar(*stop));+	printf("%ld-%ld\n", (long)startst, (long)stopst);+}++#ifndef PCHARDONE+#define	PCHARDONE	/* never again */+/*+ - pchar - make a character printable+ == #ifdef REDEBUG+ == static char *pchar(int ch);+ == #endif+ *+ * Is this identical to regchar() over in debug.c?  Well, yes.  But a+ * duplicate here avoids having a debugging-capable regexec.o tied to+ * a matching debug.o, and this is convenient.  It all disappears in+ * the non-debug compilation anyway, so it doesn't matter much.+ */+static char *			/* -> representation */+pchar(ch)+int ch;+{+	static char pbuf[10];++	if (isprint((uch)ch) || ch == ' ')+		sprintf(pbuf, "%c", ch);+	else+		sprintf(pbuf, "\\%o", ch);+	return(pbuf);+}+#endif+#endif++#undef	matcher+#undef	fast+#undef	slow+#undef	dissect+#undef	backref+#undef	step+#undef	print+#undef	at+#undef	match
+ cbits/reallocf.c view
@@ -0,0 +1,39 @@+/*-+ * Copyright (c) 1998, M. Warner Losh <imp@freebsd.org>+ * All rights reserved.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. 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.+ *+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 THE AUTHOR OR CONTRIBUTORS 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.+ *+ * $FreeBSD: src/lib/libc/stdlib/reallocf.c,v 1.3 1999/08/28 00:01:37 peter Exp $+ */+#include <stdlib.h>++void *+reallocf(void *ptr, size_t size)+{+	void *nptr;++	nptr = realloc(ptr, size);+	if (!nptr && ptr)+		free(ptr);+	return (nptr);+}
+ cbits/regcomp.c view
@@ -0,0 +1,2102 @@+/*-+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.+ * Copyright (c) 1992, 1993, 1994+ *	The Regents of the University of California.  All rights reserved.+ *+ * This code is derived from software contributed to Berkeley by+ * Henry Spencer.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. 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.+ * 3. All advertising materials mentioning features or use of this software+ *    must display the following acknowledgement:+ *	This product includes software developed by the University of+ *	California, Berkeley and its contributors.+ * 4. Neither the name of the University nor the names of its contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS OR CONTRIBUTORS 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.+ *+ *	@(#)regcomp.c	8.5 (Berkeley) 3/20/94+ *+ * $FreeBSD: src/lib/libc/regex/regcomp.c,v 1.13.2.1 2000/07/31 06:30:37 dcs Exp $+ */++#if defined(LIBC_SCCS) && !defined(lint)+static char sccsid[] = "@(#)regcomp.c	8.5 (Berkeley) 3/20/94";+#endif /* LIBC_SCCS and not lint */++#include <sys/types.h>+#include <stdio.h>+#include <string.h>+#include <ctype.h>+#include <limits.h>+#include <stdlib.h>+#include "regex.h"++// removed collate stuff --SDM+// #include "collate.h"++#ifdef _WIN32+#define isblank(c) ((c) == ' ' || (c) == '\t')+#endif++#include "utils.h"+#include "regex2.h"++#include "cclass.h"+#include "cname.h"++/*+ * parse structure, passed up and down to avoid global variables and+ * other clumsinesses+ */+struct parse {+	char *next;		/* next character in RE */+	char *end;		/* end of string (-> NUL normally) */+	int error;		/* has an error been seen? */+	sop *strip;		/* malloced strip */+	sopno ssize;		/* malloced strip size (allocated) */+	sopno slen;		/* malloced strip length (used) */+	int ncsalloc;		/* number of csets allocated */+	struct re_guts *g;+#	define	NPAREN	10	/* we need to remember () 1-9 for back refs */+	sopno pbegin[NPAREN];	/* -> ( ([0] unused) */+	sopno pend[NPAREN];	/* -> ) ([0] unused) */+};++/* === reallocf.c === */+void * reallocf(void *ptr, size_t size);++/* ========= begin header generated by ./mkh ========= */+#ifdef __cplusplus+extern "C" {+#endif++/* === regcomp.c === */+static void p_ere (struct parse *p, int stop);+static void p_ere_exp (struct parse *p);+static void p_str (struct parse *p);+static void p_bre (struct parse *p, int end1, int end2);+static int p_simp_re (struct parse *p, int starordinary);+static int p_count (struct parse *p);+static void p_bracket (struct parse *p);+static void p_b_term (struct parse *p, cset *cs);+static void p_b_cclass (struct parse *p, cset *cs);+static void p_b_eclass (struct parse *p, cset *cs);+static char p_b_symbol (struct parse *p);+static char p_b_coll_elem (struct parse *p, int endc);+static char othercase (int ch);+static void bothcases (struct parse *p, int ch);+static void ordinary (struct parse *p, int ch);+static void nonnewline (struct parse *p);+static void repeat (struct parse *p, sopno start, int from, int to);+static int seterr (struct parse *p, int e);+static cset *allocset (struct parse *p);+static void freeset (struct parse *p, cset *cs);+static int freezeset (struct parse *p, cset *cs);+static int firstch (struct parse *p, cset *cs);+static int nch (struct parse *p, cset *cs);+static void mcadd (struct parse *p, cset *cs, char *cp);+#if used+static void mcsub (cset *cs, char *cp);+static int mcin (cset *cs, char *cp);+static char *mcfind (cset *cs, char *cp);+#endif+static void mcinvert (struct parse *p, cset *cs);+static void mccase (struct parse *p, cset *cs);+static int isinsets (struct re_guts *g, int c);+static int samesets (struct re_guts *g, int c1, int c2);+static void categorize (struct parse *p, struct re_guts *g);+static sopno dupl (struct parse *p, sopno start, sopno finish);+static void doemit (struct parse *p, sop op, size_t opnd);+static void doinsert (struct parse *p, sop op, size_t opnd, sopno pos);+static void dofwd (struct parse *p, sopno pos, sop value);+static void enlarge (struct parse *p, sopno size);+static void stripsnug (struct parse *p, struct re_guts *g);+static void findmust (struct parse *p, struct re_guts *g);+static int altoffset (sop *scan, int offset, int mccs);+static void computejumps (struct parse *p, struct re_guts *g);+static void computematchjumps (struct parse *p, struct re_guts *g);+static sopno pluscount (struct parse *p, struct re_guts *g);++#ifdef __cplusplus+}+#endif+/* ========= end header generated by ./mkh ========= */++static char nuls[10];		/* place to point scanner in event of error */++/*+ * macros for use with parse structure+ * BEWARE:  these know that the parse structure is named `p' !!!+ */+#define	PEEK()	(*p->next)+#define	PEEK2()	(*(p->next+1))+#define	MORE()	(p->next < p->end)+#define	MORE2()	(p->next+1 < p->end)+#define	SEE(c)	(MORE() && PEEK() == (c))+#define	SEETWO(a, b)	(MORE() && MORE2() && PEEK() == (a) && PEEK2() == (b))+#define	EAT(c)	((SEE(c)) ? (NEXT(), 1) : 0)+#define	EATTWO(a, b)	((SEETWO(a, b)) ? (NEXT2(), 1) : 0)+#define	NEXT()	(p->next++)+#define	NEXT2()	(p->next += 2)+#define	NEXTn(n)	(p->next += (n))+#define	GETNEXT()	(*p->next++)+#define	SETERROR(e)	seterr(p, (e))+#define	REQUIRE(co, e)	((co) || SETERROR(e))+#define	MUSTSEE(c, e)	(REQUIRE(MORE() && PEEK() == (c), e))+#define	MUSTEAT(c, e)	(REQUIRE(MORE() && GETNEXT() == (c), e))+#define	MUSTNOTSEE(c, e)	(REQUIRE(!MORE() || PEEK() != (c), e))+#define	EMIT(op, sopnd)	doemit(p, (sop)(op), (size_t)(sopnd))+#define	INSERT(op, pos)	doinsert(p, (sop)(op), HERE()-(pos)+1, pos)+#define	AHEAD(pos)		dofwd(p, pos, HERE()-(pos))+#define	ASTERN(sop, pos)	EMIT(sop, HERE()-pos)+#define	HERE()		(p->slen)+#define	THERE()		(p->slen - 1)+#define	THERETHERE()	(p->slen - 2)+#define	DROP(n)	(p->slen -= (n))++#ifndef NDEBUG+static int never = 0;		/* for use in asserts; shuts lint up */+#else+#define	never	0		/* some <assert.h>s have bugs too */+#endif++/* Macro used by computejump()/computematchjump() */+#define MIN(a,b)	((a)<(b)?(a):(b))++/*+ - regcomp - interface for parser and compilation+ = extern int regcomp(regex_t *, const char *, int);+ = #define	REG_BASIC	0000+ = #define	REG_EXTENDED	0001+ = #define	REG_ICASE	0002+ = #define	REG_NOSUB	0004+ = #define	REG_NEWLINE	0010+ = #define	REG_NOSPEC	0020+ = #define	REG_PEND	0040+ = #define	REG_DUMP	0200+ */+int				/* 0 success, otherwise REG_something */+regcomp(preg, pattern, cflags)+regex_t *preg;+const char *pattern;+int cflags;+{+	struct parse pa;+	register struct re_guts *g;+	register struct parse *p = &pa;+	register int i;+	register size_t len;+#ifdef REDEBUG+#	define	GOODFLAGS(f)	(f)+#else+#	define	GOODFLAGS(f)	((f)&~REG_DUMP)+#endif++	cflags = GOODFLAGS(cflags);+	if ((cflags&REG_EXTENDED) && (cflags&REG_NOSPEC))+		return(REG_INVARG);++	if (cflags&REG_PEND) {+		if (preg->re_endp < pattern)+			return(REG_INVARG);+		len = preg->re_endp - pattern;+	} else+		len = strlen((char *)pattern);++	/* do the mallocs early so failure handling is easy */+	g = (struct re_guts *)malloc(sizeof(struct re_guts) ++							(NC-1)*sizeof(cat_t));+	if (g == NULL)+		return(REG_ESPACE);+	p->ssize = len/(size_t)2*(size_t)3 + (size_t)1;	/* ugh */+	p->strip = (sop *)malloc(p->ssize * sizeof(sop));+	p->slen = 0;+	if (p->strip == NULL) {+		free((char *)g);+		return(REG_ESPACE);+	}++	/* set things up */+	p->g = g;+	p->next = (char *)pattern;	/* convenience; we do not modify it */+	p->end = p->next + len;+	p->error = 0;+	p->ncsalloc = 0;+	for (i = 0; i < NPAREN; i++) {+		p->pbegin[i] = 0;+		p->pend[i] = 0;+	}+	g->csetsize = NC;+	g->sets = NULL;+	g->setbits = NULL;+	g->ncsets = 0;+	g->cflags = cflags;+	g->iflags = 0;+	g->nbol = 0;+	g->neol = 0;+	g->must = NULL;+	g->moffset = -1;+	g->charjump = NULL;+	g->matchjump = NULL;+	g->mlen = 0;+	g->nsub = 0;+	g->ncategories = 1;	/* category 0 is "everything else" */+	g->categories = &g->catspace[-(CHAR_MIN)];+	(void) memset((char *)g->catspace, 0, NC*sizeof(cat_t));+	g->backrefs = 0;++	/* do it */+	EMIT(OEND, 0);+	g->firststate = THERE();+	if (cflags&REG_EXTENDED)+		p_ere(p, OUT);+	else if (cflags&REG_NOSPEC)+		p_str(p);+	else+		p_bre(p, OUT, OUT);+	EMIT(OEND, 0);+	g->laststate = THERE();++	/* tidy up loose ends and fill things in */+	categorize(p, g);+	stripsnug(p, g);+	findmust(p, g);+	/* only use Boyer-Moore algorithm if the pattern is bigger+	 * than three characters+	 */+	if(g->mlen > 3) {+		computejumps(p, g);+		computematchjumps(p, g);+		if(g->matchjump == NULL && g->charjump != NULL) {+			free(g->charjump);+			g->charjump = NULL;+		}+	}+	g->nplus = pluscount(p, g);+	g->magic = MAGIC2;+	preg->re_nsub = g->nsub;+	preg->re_g = g;+	preg->re_magic = MAGIC1;+#ifndef REDEBUG+	/* not debugging, so can't rely on the assert() in regexec() */+	if (g->iflags&BAD)+		SETERROR(REG_ASSERT);+#endif++	/* win or lose, we're done */+	if (p->error != 0)	/* lose */+		regfree(preg);+	return(p->error);+}++/*+ - p_ere - ERE parser top level, concatenation and alternation+ == static void p_ere(register struct parse *p, int stop);+ */+static void+p_ere(p, stop)+register struct parse *p;+int stop;			/* character this ERE should end at */+{+	register char c;+	register sopno prevback;+	register sopno prevfwd;+	register sopno conc;+	register int first = 1;		/* is this the first alternative? */++	for (;;) {+		/* do a bunch of concatenated expressions */+		conc = HERE();+		while (MORE() && (c = PEEK()) != '|' && c != stop)+			p_ere_exp(p);+		(void)REQUIRE(HERE() != conc, REG_EMPTY);	/* require nonempty */++		if (!EAT('|'))+			break;		/* NOTE BREAK OUT */++		if (first) {+			INSERT(OCH_, conc);	/* offset is wrong */+			prevfwd = conc;+			prevback = conc;+			first = 0;+		}+		ASTERN(OOR1, prevback);+		prevback = THERE();+		AHEAD(prevfwd);			/* fix previous offset */+		prevfwd = HERE();+		EMIT(OOR2, 0);			/* offset is very wrong */+	}++	if (!first) {		/* tail-end fixups */+		AHEAD(prevfwd);+		ASTERN(O_CH, prevback);+	}++	assert(!MORE() || SEE(stop));+}++/*+ - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op+ == static void p_ere_exp(register struct parse *p);+ */+static void+p_ere_exp(p)+register struct parse *p;+{+	register char c;+	register sopno pos;+	register int count;+	register int count2;+	register sopno subno;+	int wascaret = 0;++	assert(MORE());		/* caller should have ensured this */+	c = GETNEXT();++	pos = HERE();+	switch (c) {+	case '(':+		(void)REQUIRE(MORE(), REG_EPAREN);+		p->g->nsub++;+		subno = p->g->nsub;+		if (subno < NPAREN)+			p->pbegin[subno] = HERE();+		EMIT(OLPAREN, subno);+		if (!SEE(')'))+			p_ere(p, ')');+		if (subno < NPAREN) {+			p->pend[subno] = HERE();+			assert(p->pend[subno] != 0);+		}+		EMIT(ORPAREN, subno);+		(void)MUSTEAT(')', REG_EPAREN);+		break;+#ifndef POSIX_MISTAKE+	case ')':		/* happens only if no current unmatched ( */+		/*+		 * You may ask, why the ifndef?  Because I didn't notice+		 * this until slightly too late for 1003.2, and none of the+		 * other 1003.2 regular-expression reviewers noticed it at+		 * all.  So an unmatched ) is legal POSIX, at least until+		 * we can get it fixed.+		 */+		SETERROR(REG_EPAREN);+		break;+#endif+	case '^':+		EMIT(OBOL, 0);+		p->g->iflags |= USEBOL;+		p->g->nbol++;+		wascaret = 1;+		break;+	case '$':+		EMIT(OEOL, 0);+		p->g->iflags |= USEEOL;+		p->g->neol++;+		break;+	case '|':+		SETERROR(REG_EMPTY);+		break;+	case '*':+	case '+':+	case '?':+		SETERROR(REG_BADRPT);+		break;+	case '.':+		if (p->g->cflags&REG_NEWLINE)+			nonnewline(p);+		else+			EMIT(OANY, 0);+		break;+	case '[':+		p_bracket(p);+		break;+	case '\\':+		(void)REQUIRE(MORE(), REG_EESCAPE);+		c = GETNEXT();+		ordinary(p, c);+		break;+	case '{':		/* okay as ordinary except if digit follows */+		(void)REQUIRE(!MORE() || !isdigit((uch)PEEK()), REG_BADRPT);+		/* FALLTHROUGH */+	default:+		ordinary(p, c);+		break;+	}++	if (!MORE())+		return;+	c = PEEK();+	/* we call { a repetition if followed by a digit */+	if (!( c == '*' || c == '+' || c == '?' ||+				(c == '{' && MORE2() && isdigit((uch)PEEK2())) ))+		return;		/* no repetition, we're done */+	NEXT();++	(void)REQUIRE(!wascaret, REG_BADRPT);+	switch (c) {+	case '*':	/* implemented as +? */+		/* this case does not require the (y|) trick, noKLUDGE */+		INSERT(OPLUS_, pos);+		ASTERN(O_PLUS, pos);+		INSERT(OQUEST_, pos);+		ASTERN(O_QUEST, pos);+		break;+	case '+':+		INSERT(OPLUS_, pos);+		ASTERN(O_PLUS, pos);+		break;+	case '?':+		/* KLUDGE: emit y? as (y|) until subtle bug gets fixed */+		INSERT(OCH_, pos);		/* offset slightly wrong */+		ASTERN(OOR1, pos);		/* this one's right */+		AHEAD(pos);			/* fix the OCH_ */+		EMIT(OOR2, 0);			/* offset very wrong... */+		AHEAD(THERE());			/* ...so fix it */+		ASTERN(O_CH, THERETHERE());+		break;+	case '{':+		count = p_count(p);+		if (EAT(',')) {+			if (isdigit((uch)PEEK())) {+				count2 = p_count(p);+				(void)REQUIRE(count <= count2, REG_BADBR);+			} else		/* single number with comma */+				count2 = INFINITY;+		} else		/* just a single number */+			count2 = count;+		repeat(p, pos, count, count2);+		if (!EAT('}')) {	/* error heuristics */+			while (MORE() && PEEK() != '}')+				NEXT();+			(void)REQUIRE(MORE(), REG_EBRACE);+			SETERROR(REG_BADBR);+		}+		break;+	}++	if (!MORE())+		return;+	c = PEEK();+	if (!( c == '*' || c == '+' || c == '?' ||+				(c == '{' && MORE2() && isdigit((uch)PEEK2())) ) )+		return;+	SETERROR(REG_BADRPT);+}++/*+ - p_str - string (no metacharacters) "parser"+ == static void p_str(register struct parse *p);+ */+static void+p_str(p)+register struct parse *p;+{+	(void)REQUIRE(MORE(), REG_EMPTY);+	while (MORE())+		ordinary(p, GETNEXT());+}++/*+ - p_bre - BRE parser top level, anchoring and concatenation+ == static void p_bre(register struct parse *p, register int end1, \+ ==	register int end2);+ * Giving end1 as OUT essentially eliminates the end1/end2 check.+ *+ * This implementation is a bit of a kludge, in that a trailing $ is first+ * taken as an ordinary character and then revised to be an anchor.  The+ * only undesirable side effect is that '$' gets included as a character+ * category in such cases.  This is fairly harmless; not worth fixing.+ * The amount of lookahead needed to avoid this kludge is excessive.+ */+static void+p_bre(p, end1, end2)+register struct parse *p;+register int end1;		/* first terminating character */+register int end2;		/* second terminating character */+{+	register sopno start = HERE();+	register int first = 1;			/* first subexpression? */+	register int wasdollar = 0;++	if (EAT('^')) {+		EMIT(OBOL, 0);+		p->g->iflags |= USEBOL;+		p->g->nbol++;+	}+	while (MORE() && !SEETWO(end1, end2)) {+		wasdollar = p_simp_re(p, first);+		first = 0;+	}+	if (wasdollar) {	/* oops, that was a trailing anchor */+		DROP(1);+		EMIT(OEOL, 0);+		p->g->iflags |= USEEOL;+		p->g->neol++;+	}++	(void)REQUIRE(HERE() != start, REG_EMPTY);	/* require nonempty */+}++/*+ - p_simp_re - parse a simple RE, an atom possibly followed by a repetition+ == static int p_simp_re(register struct parse *p, int starordinary);+ */+static int			/* was the simple RE an unbackslashed $? */+p_simp_re(p, starordinary)+register struct parse *p;+int starordinary;		/* is a leading * an ordinary character? */+{+	register int c;+	register int count;+	register int count2;+	register sopno pos;+	register int i;+	register sopno subno;+#	define	BACKSL	(1<<CHAR_BIT)++	pos = HERE();		/* repetion op, if any, covers from here */++	assert(MORE());		/* caller should have ensured this */+	c = GETNEXT();+	if (c == '\\') {+		(void)REQUIRE(MORE(), REG_EESCAPE);+		c = BACKSL | GETNEXT();+	}+	switch (c) {+	case '.':+		if (p->g->cflags&REG_NEWLINE)+			nonnewline(p);+		else+			EMIT(OANY, 0);+		break;+	case '[':+		p_bracket(p);+		break;+	case BACKSL|'{':+		SETERROR(REG_BADRPT);+		break;+	case BACKSL|'(':+		p->g->nsub++;+		subno = p->g->nsub;+		if (subno < NPAREN)+			p->pbegin[subno] = HERE();+		EMIT(OLPAREN, subno);+		/* the MORE here is an error heuristic */+		if (MORE() && !SEETWO('\\', ')'))+			p_bre(p, '\\', ')');+		if (subno < NPAREN) {+			p->pend[subno] = HERE();+			assert(p->pend[subno] != 0);+		}+		EMIT(ORPAREN, subno);+		(void)REQUIRE(EATTWO('\\', ')'), REG_EPAREN);+		break;+	case BACKSL|')':	/* should not get here -- must be user */+	case BACKSL|'}':+		SETERROR(REG_EPAREN);+		break;+	case BACKSL|'1':+	case BACKSL|'2':+	case BACKSL|'3':+	case BACKSL|'4':+	case BACKSL|'5':+	case BACKSL|'6':+	case BACKSL|'7':+	case BACKSL|'8':+	case BACKSL|'9':+		i = (c&~BACKSL) - '0';+		assert(i < NPAREN);+		if (p->pend[i] != 0) {+			assert(i <= p->g->nsub);+			EMIT(OBACK_, i);+			assert(p->pbegin[i] != 0);+			assert(OP(p->strip[p->pbegin[i]]) == OLPAREN);+			assert(OP(p->strip[p->pend[i]]) == ORPAREN);+			(void) dupl(p, p->pbegin[i]+1, p->pend[i]);+			EMIT(O_BACK, i);+		} else+			SETERROR(REG_ESUBREG);+		p->g->backrefs = 1;+		break;+	case '*':+		(void)REQUIRE(starordinary, REG_BADRPT);+		/* FALLTHROUGH */+	default:+		ordinary(p, (char)c);+		break;+	}++	if (EAT('*')) {		/* implemented as +? */+		/* this case does not require the (y|) trick, noKLUDGE */+		INSERT(OPLUS_, pos);+		ASTERN(O_PLUS, pos);+		INSERT(OQUEST_, pos);+		ASTERN(O_QUEST, pos);+	} else if (EATTWO('\\', '{')) {+		count = p_count(p);+		if (EAT(',')) {+			if (MORE() && isdigit((uch)PEEK())) {+				count2 = p_count(p);+				(void)REQUIRE(count <= count2, REG_BADBR);+			} else		/* single number with comma */+				count2 = INFINITY;+		} else		/* just a single number */+			count2 = count;+		repeat(p, pos, count, count2);+		if (!EATTWO('\\', '}')) {	/* error heuristics */+			while (MORE() && !SEETWO('\\', '}'))+				NEXT();+			(void)REQUIRE(MORE(), REG_EBRACE);+			SETERROR(REG_BADBR);+		}+	} else if (c == '$')     /* $ (but not \$) ends it */+		return(1);++	return(0);+}++/*+ - p_count - parse a repetition count+ == static int p_count(register struct parse *p);+ */+static int			/* the value */+p_count(p)+register struct parse *p;+{+	register int count = 0;+	register int ndigits = 0;++	while (MORE() && isdigit((uch)PEEK()) && count <= DUPMAX) {+		count = count*10 + (GETNEXT() - '0');+		ndigits++;+	}++	(void)REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR);+	return(count);+}++/*+ - p_bracket - parse a bracketed character list+ == static void p_bracket(register struct parse *p);+ *+ * Note a significant property of this code:  if the allocset() did SETERROR,+ * no set operations are done.+ */+static void+p_bracket(p)+register struct parse *p;+{+	register cset *cs = allocset(p);+	register int invert = 0;++	/* Dept of Truly Sickening Special-Case Kludges */+	if (p->next + 5 < p->end && strncmp(p->next, "[:<:]]", 6) == 0) {+		EMIT(OBOW, 0);+		NEXTn(6);+		return;+	}+	if (p->next + 5 < p->end && strncmp(p->next, "[:>:]]", 6) == 0) {+		EMIT(OEOW, 0);+		NEXTn(6);+		return;+	}++	if (EAT('^'))+		invert++;	/* make note to invert set at end */+	if (EAT(']'))+		CHadd(cs, ']');+	else if (EAT('-'))+		CHadd(cs, '-');+	while (MORE() && PEEK() != ']' && !SEETWO('-', ']'))+		p_b_term(p, cs);+	if (EAT('-'))+		CHadd(cs, '-');+	(void)MUSTEAT(']', REG_EBRACK);++	if (p->error != 0)	/* don't mess things up further */+		return;++	if (p->g->cflags&REG_ICASE) {+		register int i;+		register int ci;++		for (i = p->g->csetsize - 1; i >= 0; i--)+			if (CHIN(cs, i) && isalpha(i)) {+				ci = othercase(i);+				if (ci != i)+					CHadd(cs, ci);+			}+		if (cs->multis != NULL)+			mccase(p, cs);+	}+	if (invert) {+		register int i;++		for (i = p->g->csetsize - 1; i >= 0; i--)+			if (CHIN(cs, i))+				CHsub(cs, i);+			else+				CHadd(cs, i);+		if (p->g->cflags&REG_NEWLINE)+			CHsub(cs, '\n');+		if (cs->multis != NULL)+			mcinvert(p, cs);+	}++	assert(cs->multis == NULL);		/* xxx */++	if (nch(p, cs) == 1) {		/* optimize singleton sets */+		ordinary(p, firstch(p, cs));+		freeset(p, cs);+	} else+		EMIT(OANYOF, freezeset(p, cs));+}++/*+ - p_b_term - parse one term of a bracketed character list+ == static void p_b_term(register struct parse *p, register cset *cs);+ */+static void+p_b_term(p, cs)+register struct parse *p;+register cset *cs;+{+	register char c;+	register char start, finish;+	register int i;++	/* classify what we've got */+	switch ((MORE()) ? PEEK() : '\0') {+	case '[':+		c = (MORE2()) ? PEEK2() : '\0';+		break;+	case '-':+		SETERROR(REG_ERANGE);+		return;			/* NOTE RETURN */+		break;+	default:+		c = '\0';+		break;+	}++	switch (c) {+	case ':':		/* character class */+		NEXT2();+		(void)REQUIRE(MORE(), REG_EBRACK);+		c = PEEK();+		(void)REQUIRE(c != '-' && c != ']', REG_ECTYPE);+		p_b_cclass(p, cs);+		(void)REQUIRE(MORE(), REG_EBRACK);+		(void)REQUIRE(EATTWO(':', ']'), REG_ECTYPE);+		break;+	case '=':		/* equivalence class */+		NEXT2();+		(void)REQUIRE(MORE(), REG_EBRACK);+		c = PEEK();+		(void)REQUIRE(c != '-' && c != ']', REG_ECOLLATE);+		p_b_eclass(p, cs);+		(void)REQUIRE(MORE(), REG_EBRACK);+		(void)REQUIRE(EATTWO('=', ']'), REG_ECOLLATE);+		break;+	default:		/* symbol, ordinary character, or range */+/* xxx revision needed for multichar stuff */+		start = p_b_symbol(p);+		if (SEE('-') && MORE2() && PEEK2() != ']') {+			/* range */+			NEXT();+			if (EAT('-'))+				finish = '-';+			else+				finish = p_b_symbol(p);+		} else+			finish = start;+		if (start == finish)+			CHadd(cs, start);+		else {+// remove collate stuff --SDM+#if 0+			if (__collate_load_error) {+				(void)REQUIRE((uch)start <= (uch)finish, REG_ERANGE);+#endif+				for (i = (uch)start; i <= (uch)finish; i++)+					CHadd(cs, i);+#if 0+			} else {+				(void)REQUIRE(__collate_range_cmp(start, finish) <= 0, REG_ERANGE);+				for (i = CHAR_MIN; i <= CHAR_MAX; i++) {+					if (   __collate_range_cmp(start, i) <= 0+					    && __collate_range_cmp(i, finish) <= 0+					   )+						CHadd(cs, i);+				}+			}+#endif+		}+		break;+	}+}++/*+ - p_b_cclass - parse a character-class name and deal with it+ == static void p_b_cclass(register struct parse *p, register cset *cs);+ */+static void+p_b_cclass(p, cs)+register struct parse *p;+register cset *cs;+{+	register int c;+	register char *sp = p->next;+	register struct cclass *cp;+	register size_t len;++	while (MORE() && isalpha((uch)PEEK()))+		NEXT();+	len = p->next - sp;+	for (cp = cclasses; cp->name != NULL; cp++)+		if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0')+			break;+	if (cp->name == NULL) {+		/* oops, didn't find it */+		SETERROR(REG_ECTYPE);+		return;+	}++	switch (cp->fidx) {+	case CALNUM:+		for (c = CHAR_MIN; c <= CHAR_MAX; c++)+			if (isalnum((uch)c))+				CHadd(cs, c);+		break;+	case CALPHA:+		for (c = CHAR_MIN; c <= CHAR_MAX; c++)+			if (isalpha((uch)c))+				CHadd(cs, c);+		break;+	case CBLANK:+		for (c = CHAR_MIN; c <= CHAR_MAX; c++)+			if (isblank((uch)c))+				CHadd(cs, c);+		break;+	case CCNTRL:+		for (c = CHAR_MIN; c <= CHAR_MAX; c++)+			if (iscntrl((uch)c))+				CHadd(cs, c);+		break;+	case CDIGIT:+		for (c = CHAR_MIN; c <= CHAR_MAX; c++)+			if (isdigit((uch)c))+				CHadd(cs, c);+		break;+	case CGRAPH:+		for (c = CHAR_MIN; c <= CHAR_MAX; c++)+			if (isgraph((uch)c))+				CHadd(cs, c);+		break;+	case CLOWER:+		for (c = CHAR_MIN; c <= CHAR_MAX; c++)+			if (islower((uch)c))+				CHadd(cs, c);+		break;+	case CPRINT:+		for (c = CHAR_MIN; c <= CHAR_MAX; c++)+			if (isprint((uch)c))+				CHadd(cs, c);+		break;+	case CPUNCT:+		for (c = CHAR_MIN; c <= CHAR_MAX; c++)+			if (ispunct((uch)c))+				CHadd(cs, c);+		break;+	case CSPACE:+		for (c = CHAR_MIN; c <= CHAR_MAX; c++)+			if (isspace((uch)c))+				CHadd(cs, c);+		break;+	case CUPPER:+		for (c = CHAR_MIN; c <= CHAR_MAX; c++)+			if (isupper((uch)c))+				CHadd(cs, c);+		break;+	case CXDIGIT:+		for (c = CHAR_MIN; c <= CHAR_MAX; c++)+			if (isxdigit((uch)c))+				CHadd(cs, c);+		break;+	}+#if 0+	for (u = cp->multis; *u != '\0'; u += strlen(u) + 1)+		MCadd(p, cs, u);+#endif+}++/*+ - p_b_eclass - parse an equivalence-class name and deal with it+ == static void p_b_eclass(register struct parse *p, register cset *cs);+ *+ * This implementation is incomplete. xxx+ */+static void+p_b_eclass(p, cs)+register struct parse *p;+register cset *cs;+{+	register char c;++	c = p_b_coll_elem(p, '=');+	CHadd(cs, c);+}++/*+ - p_b_symbol - parse a character or [..]ed multicharacter collating symbol+ == static char p_b_symbol(register struct parse *p);+ */+static char			/* value of symbol */+p_b_symbol(p)+register struct parse *p;+{+	register char value;++	(void)REQUIRE(MORE(), REG_EBRACK);+	if (!EATTWO('[', '.'))+		return(GETNEXT());++	/* collating symbol */+	value = p_b_coll_elem(p, '.');+	(void)REQUIRE(EATTWO('.', ']'), REG_ECOLLATE);+	return(value);+}++/*+ - p_b_coll_elem - parse a collating-element name and look it up+ == static char p_b_coll_elem(register struct parse *p, int endc);+ */+static char			/* value of collating element */+p_b_coll_elem(p, endc)+register struct parse *p;+int endc;			/* name ended by endc,']' */+{+	register char *sp = p->next;+	register struct cname *cp;+	register int len;++	while (MORE() && !SEETWO(endc, ']'))+		NEXT();+	if (!MORE()) {+		SETERROR(REG_EBRACK);+		return(0);+	}+	len = p->next - sp;+	for (cp = cnames; cp->name != NULL; cp++)+		if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0')+			return(cp->code);	/* known name */+	if (len == 1)+		return(*sp);	/* single character */+	SETERROR(REG_ECOLLATE);			/* neither */+	return(0);+}++/*+ - othercase - return the case counterpart of an alphabetic+ == static char othercase(int ch);+ */+static char			/* if no counterpart, return ch */+othercase(ch)+int ch;+{+	ch = (uch)ch;+	assert(isalpha(ch));+	if (isupper(ch))+		return(tolower(ch));+	else if (islower(ch))+		return(toupper(ch));+	else			/* peculiar, but could happen */+		return(ch);+}++/*+ - bothcases - emit a dualcase version of a two-case character+ == static void bothcases(register struct parse *p, int ch);+ *+ * Boy, is this implementation ever a kludge...+ */+static void+bothcases(p, ch)+register struct parse *p;+int ch;+{+	register char *oldnext = p->next;+	register char *oldend = p->end;+	char bracket[3];++	ch = (uch)ch;+	assert(othercase(ch) != ch);	/* p_bracket() would recurse */+	p->next = bracket;+	p->end = bracket+2;+	bracket[0] = ch;+	bracket[1] = ']';+	bracket[2] = '\0';+	p_bracket(p);+	assert(p->next == bracket+2);+	p->next = oldnext;+	p->end = oldend;+}++/*+ - ordinary - emit an ordinary character+ == static void ordinary(register struct parse *p, register int ch);+ */+static void+ordinary(p, ch)+register struct parse *p;+register int ch;+{+	register cat_t *cap = p->g->categories;++	if ((p->g->cflags&REG_ICASE) && isalpha((uch)ch) && othercase(ch) != ch)+		bothcases(p, ch);+	else {+		EMIT(OCHAR, (uch)ch);+		if (cap[ch] == 0)+			cap[ch] = p->g->ncategories++;+	}+}++/*+ - nonnewline - emit REG_NEWLINE version of OANY+ == static void nonnewline(register struct parse *p);+ *+ * Boy, is this implementation ever a kludge...+ */+static void+nonnewline(p)+register struct parse *p;+{+	register char *oldnext = p->next;+	register char *oldend = p->end;+	char bracket[4];++	p->next = bracket;+	p->end = bracket+3;+	bracket[0] = '^';+	bracket[1] = '\n';+	bracket[2] = ']';+	bracket[3] = '\0';+	p_bracket(p);+	assert(p->next == bracket+3);+	p->next = oldnext;+	p->end = oldend;+}++/*+ - repeat - generate code for a bounded repetition, recursively if needed+ == static void repeat(register struct parse *p, sopno start, int from, int to);+ */+static void+repeat(p, start, from, to)+register struct parse *p;+sopno start;			/* operand from here to end of strip */+int from;			/* repeated from this number */+int to;				/* to this number of times (maybe INFINITY) */+{+	register sopno finish = HERE();+#	define	N	2+#	define	INF	3+#	define	REP(f, t)	((f)*8 + (t))+#	define	MAP(n)	(((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N)+	register sopno copy;++	if (p->error != 0)	/* head off possible runaway recursion */+		return;++	assert(from <= to);++	switch (REP(MAP(from), MAP(to))) {+	case REP(0, 0):			/* must be user doing this */+		DROP(finish-start);	/* drop the operand */+		break;+	case REP(0, 1):			/* as x{1,1}? */+	case REP(0, N):			/* as x{1,n}? */+	case REP(0, INF):		/* as x{1,}? */+		/* KLUDGE: emit y? as (y|) until subtle bug gets fixed */+		INSERT(OCH_, start);		/* offset is wrong... */+		repeat(p, start+1, 1, to);+		ASTERN(OOR1, start);+		AHEAD(start);			/* ... fix it */+		EMIT(OOR2, 0);+		AHEAD(THERE());+		ASTERN(O_CH, THERETHERE());+		break;+	case REP(1, 1):			/* trivial case */+		/* done */+		break;+	case REP(1, N):			/* as x?x{1,n-1} */+		/* KLUDGE: emit y? as (y|) until subtle bug gets fixed */+		INSERT(OCH_, start);+		ASTERN(OOR1, start);+		AHEAD(start);+		EMIT(OOR2, 0);			/* offset very wrong... */+		AHEAD(THERE());			/* ...so fix it */+		ASTERN(O_CH, THERETHERE());+		copy = dupl(p, start+1, finish+1);+		assert(copy == finish+4);+		repeat(p, copy, 1, to-1);+		break;+	case REP(1, INF):		/* as x+ */+		INSERT(OPLUS_, start);+		ASTERN(O_PLUS, start);+		break;+	case REP(N, N):			/* as xx{m-1,n-1} */+		copy = dupl(p, start, finish);+		repeat(p, copy, from-1, to-1);+		break;+	case REP(N, INF):		/* as xx{n-1,INF} */+		copy = dupl(p, start, finish);+		repeat(p, copy, from-1, to);+		break;+	default:			/* "can't happen" */+		SETERROR(REG_ASSERT);	/* just in case */+		break;+	}+}++/*+ - seterr - set an error condition+ == static int seterr(register struct parse *p, int e);+ */+static int			/* useless but makes type checking happy */+seterr(p, e)+register struct parse *p;+int e;+{+	if (p->error == 0)	/* keep earliest error condition */+		p->error = e;+	p->next = nuls;		/* try to bring things to a halt */+	p->end = nuls;+	return(0);		/* make the return value well-defined */+}++/*+ - allocset - allocate a set of characters for []+ == static cset *allocset(register struct parse *p);+ */+static cset *+allocset(p)+register struct parse *p;+{+	register int no = p->g->ncsets++;+	register size_t nc;+	register size_t nbytes;+	register cset *cs;+	register size_t css = (size_t)p->g->csetsize;+	register int i;++	if (no >= p->ncsalloc) {	/* need another column of space */+		p->ncsalloc += CHAR_BIT;+		nc = p->ncsalloc;+		assert(nc % CHAR_BIT == 0);+		nbytes = nc / CHAR_BIT * css;+		if (p->g->sets == NULL)+			p->g->sets = (cset *)malloc(nc * sizeof(cset));+		else+			p->g->sets = (cset *)reallocf((char *)p->g->sets,+							nc * sizeof(cset));+		if (p->g->setbits == NULL)+			p->g->setbits = (uch *)malloc(nbytes);+		else {+			p->g->setbits = (uch *)reallocf((char *)p->g->setbits,+								nbytes);+			/* xxx this isn't right if setbits is now NULL */+			for (i = 0; i < no; i++)+				p->g->sets[i].ptr = p->g->setbits + css*(i/CHAR_BIT);+		}+		if (p->g->sets != NULL && p->g->setbits != NULL)+			(void) memset((char *)p->g->setbits + (nbytes - css),+								0, css);+		else {+			no = 0;+			SETERROR(REG_ESPACE);+			/* caller's responsibility not to do set ops */+		}+	}++	assert(p->g->sets != NULL);	/* xxx */+	cs = &p->g->sets[no];+	cs->ptr = p->g->setbits + css*((no)/CHAR_BIT);+	cs->mask = 1 << ((no) % CHAR_BIT);+	cs->hash = 0;+	cs->smultis = 0;+	cs->multis = NULL;++	return(cs);+}++/*+ - freeset - free a now-unused set+ == static void freeset(register struct parse *p, register cset *cs);+ */+static void+freeset(p, cs)+register struct parse *p;+register cset *cs;+{+	register int i;+	register cset *top = &p->g->sets[p->g->ncsets];+	register size_t css = (size_t)p->g->csetsize;++	for (i = 0; i < css; i++)+		CHsub(cs, i);+	if (cs == top-1)	/* recover only the easy case */+		p->g->ncsets--;+}++/*+ - freezeset - final processing on a set of characters+ == static int freezeset(register struct parse *p, register cset *cs);+ *+ * The main task here is merging identical sets.  This is usually a waste+ * of time (although the hash code minimizes the overhead), but can win+ * big if REG_ICASE is being used.  REG_ICASE, by the way, is why the hash+ * is done using addition rather than xor -- all ASCII [aA] sets xor to+ * the same value!+ */+static int			/* set number */+freezeset(p, cs)+register struct parse *p;+register cset *cs;+{+	register short h = cs->hash;+	register int i;+	register cset *top = &p->g->sets[p->g->ncsets];+	register cset *cs2;+	register size_t css = (size_t)p->g->csetsize;++	/* look for an earlier one which is the same */+	for (cs2 = &p->g->sets[0]; cs2 < top; cs2++)+		if (cs2->hash == h && cs2 != cs) {+			/* maybe */+			for (i = 0; i < css; i++)+				if (!!CHIN(cs2, i) != !!CHIN(cs, i))+					break;		/* no */+			if (i == css)+				break;			/* yes */+		}++	if (cs2 < top) {	/* found one */+		freeset(p, cs);+		cs = cs2;+	}++	return((int)(cs - p->g->sets));+}++/*+ - firstch - return first character in a set (which must have at least one)+ == static int firstch(register struct parse *p, register cset *cs);+ */+static int			/* character; there is no "none" value */+firstch(p, cs)+register struct parse *p;+register cset *cs;+{+	register int i;+	register size_t css = (size_t)p->g->csetsize;++	for (i = 0; i < css; i++)+		if (CHIN(cs, i))+			return((char)i);+	assert(never);+	return(0);		/* arbitrary */+}++/*+ - nch - number of characters in a set+ == static int nch(register struct parse *p, register cset *cs);+ */+static int+nch(p, cs)+register struct parse *p;+register cset *cs;+{+	register int i;+	register size_t css = (size_t)p->g->csetsize;+	register int n = 0;++	for (i = 0; i < css; i++)+		if (CHIN(cs, i))+			n++;+	return(n);+}++/*+ - mcadd - add a collating element to a cset+ == static void mcadd(register struct parse *p, register cset *cs, \+ ==	register char *cp);+ */+static void+mcadd(p, cs, cp)+register struct parse *p;+register cset *cs;+register char *cp;+{+	register size_t oldend = cs->smultis;++	cs->smultis += strlen(cp) + 1;+	if (cs->multis == NULL)+		cs->multis = malloc(cs->smultis);+	else+		cs->multis = reallocf(cs->multis, cs->smultis);+	if (cs->multis == NULL) {+		SETERROR(REG_ESPACE);+		return;+	}++	(void) strcpy(cs->multis + oldend - 1, cp);+	cs->multis[cs->smultis - 1] = '\0';+}++#if used+/*+ - mcsub - subtract a collating element from a cset+ == static void mcsub(register cset *cs, register char *cp);+ */+static void+mcsub(cs, cp)+register cset *cs;+register char *cp;+{+	register char *fp = mcfind(cs, cp);+	register size_t len = strlen(fp);++	assert(fp != NULL);+	(void) memmove(fp, fp + len + 1,+				cs->smultis - (fp + len + 1 - cs->multis));+	cs->smultis -= len;++	if (cs->smultis == 0) {+		free(cs->multis);+		cs->multis = NULL;+		return;+	}++	cs->multis = reallocf(cs->multis, cs->smultis);+	assert(cs->multis != NULL);+}++/*+ - mcin - is a collating element in a cset?+ == static int mcin(register cset *cs, register char *cp);+ */+static int+mcin(cs, cp)+register cset *cs;+register char *cp;+{+	return(mcfind(cs, cp) != NULL);+}++/*+ - mcfind - find a collating element in a cset+ == static char *mcfind(register cset *cs, register char *cp);+ */+static char *+mcfind(cs, cp)+register cset *cs;+register char *cp;+{+	register char *p;++	if (cs->multis == NULL)+		return(NULL);+	for (p = cs->multis; *p != '\0'; p += strlen(p) + 1)+		if (strcmp(cp, p) == 0)+			return(p);+	return(NULL);+}+#endif++/*+ - mcinvert - invert the list of collating elements in a cset+ == static void mcinvert(register struct parse *p, register cset *cs);+ *+ * This would have to know the set of possibilities.  Implementation+ * is deferred.+ */+static void+mcinvert(p, cs)+register struct parse *p;+register cset *cs;+{+	assert(cs->multis == NULL);	/* xxx */+}++/*+ - mccase - add case counterparts of the list of collating elements in a cset+ == static void mccase(register struct parse *p, register cset *cs);+ *+ * This would have to know the set of possibilities.  Implementation+ * is deferred.+ */+static void+mccase(p, cs)+register struct parse *p;+register cset *cs;+{+	assert(cs->multis == NULL);	/* xxx */+}++/*+ - isinsets - is this character in any sets?+ == static int isinsets(register struct re_guts *g, int c);+ */+static int			/* predicate */+isinsets(g, c)+register struct re_guts *g;+int c;+{+	register uch *col;+	register int i;+	register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT;+	register unsigned uc = (uch)c;++	for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize)+		if (col[uc] != 0)+			return(1);+	return(0);+}++/*+ - samesets - are these two characters in exactly the same sets?+ == static int samesets(register struct re_guts *g, int c1, int c2);+ */+static int			/* predicate */+samesets(g, c1, c2)+register struct re_guts *g;+int c1;+int c2;+{+	register uch *col;+	register int i;+	register int ncols = (g->ncsets+(CHAR_BIT-1)) / CHAR_BIT;+	register unsigned uc1 = (uch)c1;+	register unsigned uc2 = (uch)c2;++	for (i = 0, col = g->setbits; i < ncols; i++, col += g->csetsize)+		if (col[uc1] != col[uc2])+			return(0);+	return(1);+}++/*+ - categorize - sort out character categories+ == static void categorize(struct parse *p, register struct re_guts *g);+ */+static void+categorize(p, g)+struct parse *p;+register struct re_guts *g;+{+	register cat_t *cats = g->categories;+	register int c;+	register int c2;+	register cat_t cat;++	/* avoid making error situations worse */+	if (p->error != 0)+		return;++	for (c = CHAR_MIN; c <= CHAR_MAX; c++)+		if (cats[c] == 0 && isinsets(g, c)) {+			cat = g->ncategories++;+			cats[c] = cat;+			for (c2 = c+1; c2 <= CHAR_MAX; c2++)+				if (cats[c2] == 0 && samesets(g, c, c2))+					cats[c2] = cat;+		}+}++/*+ - dupl - emit a duplicate of a bunch of sops+ == static sopno dupl(register struct parse *p, sopno start, sopno finish);+ */+static sopno			/* start of duplicate */+dupl(p, start, finish)+register struct parse *p;+sopno start;			/* from here */+sopno finish;			/* to this less one */+{+	register sopno ret = HERE();+	register sopno len = finish - start;++	assert(finish >= start);+	if (len == 0)+		return(ret);+	enlarge(p, p->ssize + len);	/* this many unexpected additions */+	assert(p->ssize >= p->slen + len);+	(void) memcpy((char *)(p->strip + p->slen),+		(char *)(p->strip + start), (size_t)len*sizeof(sop));+	p->slen += len;+	return(ret);+}++/*+ - doemit - emit a strip operator+ == static void doemit(register struct parse *p, sop op, size_t opnd);+ *+ * It might seem better to implement this as a macro with a function as+ * hard-case backup, but it's just too big and messy unless there are+ * some changes to the data structures.  Maybe later.+ */+static void+doemit(p, op, opnd)+register struct parse *p;+sop op;+size_t opnd;+{+	/* avoid making error situations worse */+	if (p->error != 0)+		return;++	/* deal with oversize operands ("can't happen", more or less) */+	assert(opnd < 1<<OPSHIFT);++	/* deal with undersized strip */+	if (p->slen >= p->ssize)+		enlarge(p, (p->ssize+1) / 2 * 3);	/* +50% */+	assert(p->slen < p->ssize);++	/* finally, it's all reduced to the easy case */+	p->strip[p->slen++] = SOP(op, opnd);+}++/*+ - doinsert - insert a sop into the strip+ == static void doinsert(register struct parse *p, sop op, size_t opnd, sopno pos);+ */+static void+doinsert(p, op, opnd, pos)+register struct parse *p;+sop op;+size_t opnd;+sopno pos;+{+	register sopno sn;+	register sop s;+	register int i;++	/* avoid making error situations worse */+	if (p->error != 0)+		return;++	sn = HERE();+	EMIT(op, opnd);		/* do checks, ensure space */+	assert(HERE() == sn+1);+	s = p->strip[sn];++	/* adjust paren pointers */+	assert(pos > 0);+	for (i = 1; i < NPAREN; i++) {+		if (p->pbegin[i] >= pos) {+			p->pbegin[i]++;+		}+		if (p->pend[i] >= pos) {+			p->pend[i]++;+		}+	}++	memmove((char *)&p->strip[pos+1], (char *)&p->strip[pos],+						(HERE()-pos-1)*sizeof(sop));+	p->strip[pos] = s;+}++/*+ - dofwd - complete a forward reference+ == static void dofwd(register struct parse *p, sopno pos, sop value);+ */+static void+dofwd(p, pos, value)+register struct parse *p;+register sopno pos;+sop value;+{+	/* avoid making error situations worse */+	if (p->error != 0)+		return;++	assert(value < 1<<OPSHIFT);+	p->strip[pos] = OP(p->strip[pos]) | value;+}++/*+ - enlarge - enlarge the strip+ == static void enlarge(register struct parse *p, sopno size);+ */+static void+enlarge(p, size)+register struct parse *p;+register sopno size;+{+	register sop *sp;++	if (p->ssize >= size)+		return;++	sp = (sop *)realloc(p->strip, size*sizeof(sop));+	if (sp == NULL) {+		SETERROR(REG_ESPACE);+		return;+	}+	p->strip = sp;+	p->ssize = size;+}++/*+ - stripsnug - compact the strip+ == static void stripsnug(register struct parse *p, register struct re_guts *g);+ */+static void+stripsnug(p, g)+register struct parse *p;+register struct re_guts *g;+{+	g->nstates = p->slen;+	g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop));+	if (g->strip == NULL) {+		SETERROR(REG_ESPACE);+		g->strip = p->strip;+	}+}++/*+ - findmust - fill in must and mlen with longest mandatory literal string+ == static void findmust(register struct parse *p, register struct re_guts *g);+ *+ * This algorithm could do fancy things like analyzing the operands of |+ * for common subsequences.  Someday.  This code is simple and finds most+ * of the interesting cases.+ *+ * Note that must and mlen got initialized during setup.+ */+static void+findmust(p, g)+struct parse *p;+register struct re_guts *g;+{+	register sop *scan;+	sop *start;+	register sop *newstart;+	register sopno newlen;+	register sop s;+	register char *cp;+	register sopno i;+	int offset;+	int cs, mccs;++	/* avoid making error situations worse */+	if (p->error != 0)+		return;++	/* Find out if we can handle OANYOF or not */+	mccs = 0;+	for (cs = 0; cs < g->ncsets; cs++)+		if (g->sets[cs].multis != NULL)+			mccs = 1;++	/* find the longest OCHAR sequence in strip */+	newlen = 0;+	offset = 0;+	g->moffset = 0;+	scan = g->strip + 1;+	do {+		s = *scan++;+		switch (OP(s)) {+		case OCHAR:		/* sequence member */+			if (newlen == 0)		/* new sequence */+				newstart = scan - 1;+			newlen++;+			break;+		case OPLUS_:		/* things that don't break one */+		case OLPAREN:+		case ORPAREN:+			break;+		case OQUEST_:		/* things that must be skipped */+		case OCH_:+			offset = altoffset(scan, offset, mccs);+			scan--;+			do {+				scan += OPND(s);+				s = *scan;+				/* assert() interferes w debug printouts */+				if (OP(s) != O_QUEST && OP(s) != O_CH &&+							OP(s) != OOR2) {+					g->iflags |= BAD;+					return;+				}+			} while (OP(s) != O_QUEST && OP(s) != O_CH);+			/* fallthrough */+		case OBOW:		/* things that break a sequence */+		case OEOW:+		case OBOL:+		case OEOL:+		case O_QUEST:+		case O_CH:+		case OEND:+			if (newlen > g->mlen) {		/* ends one */+				start = newstart;+				g->mlen = newlen;+				if (offset > -1) {+					g->moffset += offset;+					offset = newlen;+				} else+					g->moffset = offset;+			} else {+				if (offset > -1)+					offset += newlen;+			}+			newlen = 0;+			break;+		case OANY:+			if (newlen > g->mlen) {		/* ends one */+				start = newstart;+				g->mlen = newlen;+				if (offset > -1) {+					g->moffset += offset;+					offset = newlen;+				} else+					g->moffset = offset;+			} else {+				if (offset > -1)+					offset += newlen;+			}+			if (offset > -1)+				offset++;+			newlen = 0;+			break;+		case OANYOF:		/* may or may not invalidate offset */+			/* First, everything as OANY */+			if (newlen > g->mlen) {		/* ends one */+				start = newstart;+				g->mlen = newlen;+				if (offset > -1) {+					g->moffset += offset;+					offset = newlen;+				} else+					g->moffset = offset;+			} else {+				if (offset > -1)+					offset += newlen;+			}+			if (offset > -1)+				offset++;+			newlen = 0;+			/* And, now, if we found out we can't deal with+			 * it, make offset = -1.+			 */+			if (mccs)+				offset = -1;+			break;+		default:+			/* Anything here makes it impossible or too hard+			 * to calculate the offset -- so we give up;+			 * save the last known good offset, in case the+			 * must sequence doesn't occur later.+			 */+			if (newlen > g->mlen) {		/* ends one */+				start = newstart;+				g->mlen = newlen;+				if (offset > -1)+					g->moffset += offset;+				else+					g->moffset = offset;+			}+			offset = -1;+			newlen = 0;+			break;+		}+	} while (OP(s) != OEND);++	if (g->mlen == 0) {		/* there isn't one */+		g->moffset = -1;+		return;+	}++	/* turn it into a character string */+	g->must = malloc((size_t)g->mlen + 1);+	if (g->must == NULL) {		/* argh; just forget it */+		g->mlen = 0;+		g->moffset = -1;+		return;+	}+	cp = g->must;+	scan = start;+	for (i = g->mlen; i > 0; i--) {+		while (OP(s = *scan++) != OCHAR)+			continue;+		assert(cp < g->must + g->mlen);+		*cp++ = (char)OPND(s);+	}+	assert(cp == g->must + g->mlen);+	*cp++ = '\0';		/* just on general principles */+}++/*+ - altoffset - choose biggest offset among multiple choices+ == static int altoffset(sop *scan, int offset, int mccs);+ *+ * Compute, recursively if necessary, the largest offset among multiple+ * re paths.+ */+static int+altoffset(scan, offset, mccs)+sop *scan;+int offset;+int mccs;+{+	int largest;+	int try;+	sop s;++	/* If we gave up already on offsets, return */+	if (offset == -1)+		return -1;++	largest = 0;+	try = 0;+	s = *scan++;+	while (OP(s) != O_QUEST && OP(s) != O_CH) {+		switch (OP(s)) {+		case OOR1:+			if (try > largest)+				largest = try;+			try = 0;+			break;+		case OQUEST_:+		case OCH_:+			try = altoffset(scan, try, mccs);+			if (try == -1)+				return -1;+			scan--;+			do {+				scan += OPND(s);+				s = *scan;+				if (OP(s) != O_QUEST && OP(s) != O_CH &&+							OP(s) != OOR2)+					return -1;+			} while (OP(s) != O_QUEST && OP(s) != O_CH);+			/* We must skip to the next position, or we'll+			 * leave altoffset() too early.+			 */+			scan++;+			break;+		case OANYOF:+			if (mccs)+				return -1;+		case OCHAR:+		case OANY:+			try++;+		case OBOW:+		case OEOW:+		case OLPAREN:+		case ORPAREN:+		case OOR2:+			break;+		default:+			try = -1;+			break;+		}+		if (try == -1)+			return -1;+		s = *scan++;+	}++	if (try > largest)+		largest = try;++	return largest+offset;+}++/*+ - computejumps - compute char jumps for BM scan+ == static void computejumps(register struct parse *p, register struct re_guts *g);+ *+ * This algorithm assumes g->must exists and is has size greater than+ * zero. It's based on the algorithm found on Computer Algorithms by+ * Sara Baase.+ *+ * A char jump is the number of characters one needs to jump based on+ * the value of the character from the text that was mismatched.+ */+static void+computejumps(p, g)+struct parse *p;+struct re_guts *g;+{+	int ch;+	int mindex;++	/* Avoid making errors worse */+	if (p->error != 0)+		return;++	g->charjump = (int*) malloc((NC + 1) * sizeof(int));+	if (g->charjump == NULL)	/* Not a fatal error */+		return;+	/* Adjust for signed chars, if necessary */+	g->charjump = &g->charjump[-(CHAR_MIN)];++	/* If the character does not exist in the pattern, the jump+	 * is equal to the number of characters in the pattern.+	 */+	for (ch = CHAR_MIN; ch < (CHAR_MAX + 1); ch++)+		g->charjump[ch] = g->mlen;++	/* If the character does exist, compute the jump that would+	 * take us to the last character in the pattern equal to it+	 * (notice that we match right to left, so that last character+	 * is the first one that would be matched).+	 */+	for (mindex = 0; mindex < g->mlen; mindex++)+		g->charjump[g->must[mindex]] = g->mlen - mindex - 1;+}++/*+ - computematchjumps - compute match jumps for BM scan+ == static void computematchjumps(register struct parse *p, register struct re_guts *g);+ *+ * This algorithm assumes g->must exists and is has size greater than+ * zero. It's based on the algorithm found on Computer Algorithms by+ * Sara Baase.+ *+ * A match jump is the number of characters one needs to advance based+ * on the already-matched suffix.+ * Notice that all values here are minus (g->mlen-1), because of the way+ * the search algorithm works.+ */+static void+computematchjumps(p, g)+struct parse *p;+struct re_guts *g;+{+	int mindex;		/* General "must" iterator */+	int suffix;		/* Keeps track of matching suffix */+	int ssuffix;		/* Keeps track of suffixes' suffix */+	int* pmatches;		/* pmatches[k] points to the next i+				 * such that i+1...mlen is a substring+				 * of k+1...k+mlen-i-1+				 */++	/* Avoid making errors worse */+	if (p->error != 0)+		return;++	pmatches = (int*) malloc(g->mlen * sizeof(unsigned int));+	if (pmatches == NULL) {+		g->matchjump = NULL;+		return;+	}++	g->matchjump = (int*) malloc(g->mlen * sizeof(unsigned int));+	if (g->matchjump == NULL)	/* Not a fatal error */+		return;++	/* Set maximum possible jump for each character in the pattern */+	for (mindex = 0; mindex < g->mlen; mindex++)+		g->matchjump[mindex] = 2*g->mlen - mindex - 1;++	/* Compute pmatches[] */+	for (mindex = g->mlen - 1, suffix = g->mlen; mindex >= 0;+	    mindex--, suffix--) {+		pmatches[mindex] = suffix;++		/* If a mismatch is found, interrupting the substring,+		 * compute the matchjump for that position. If no+		 * mismatch is found, then a text substring mismatched+		 * against the suffix will also mismatch against the+		 * substring.+		 */+		while (suffix < g->mlen+		    && g->must[mindex] != g->must[suffix]) {+			g->matchjump[suffix] = MIN(g->matchjump[suffix],+			    g->mlen - mindex - 1);+			suffix = pmatches[suffix];+		}+	}++	/* Compute the matchjump up to the last substring found to jump+	 * to the beginning of the largest must pattern prefix matching+	 * it's own suffix.+	 */+	for (mindex = 0; mindex <= suffix; mindex++)+		g->matchjump[mindex] = MIN(g->matchjump[mindex],+		    g->mlen + suffix - mindex);++        ssuffix = pmatches[suffix];+        while (suffix < g->mlen) {+                while (suffix <= ssuffix && suffix < g->mlen) {+                        g->matchjump[suffix] = MIN(g->matchjump[suffix],+			    g->mlen + ssuffix - suffix);+                        suffix++;+                }+		if (suffix < g->mlen)+                	ssuffix = pmatches[ssuffix];+        }++	free(pmatches);+}++/*+ - pluscount - count + nesting+ == static sopno pluscount(register struct parse *p, register struct re_guts *g);+ */+static sopno			/* nesting depth */+pluscount(p, g)+struct parse *p;+register struct re_guts *g;+{+	register sop *scan;+	register sop s;+	register sopno plusnest = 0;+	register sopno maxnest = 0;++	if (p->error != 0)+		return(0);	/* there may not be an OEND */++	scan = g->strip + 1;+	do {+		s = *scan++;+		switch (OP(s)) {+		case OPLUS_:+			plusnest++;+			break;+		case O_PLUS:+			if (plusnest > maxnest)+				maxnest = plusnest;+			plusnest--;+			break;+		}+	} while (OP(s) != OEND);+	if (plusnest != 0)+		g->iflags |= BAD;+	return(maxnest);+}
+ cbits/regerror.c view
@@ -0,0 +1,177 @@+/*-+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.+ * Copyright (c) 1992, 1993, 1994+ *	The Regents of the University of California.  All rights reserved.+ *+ * This code is derived from software contributed to Berkeley by+ * Henry Spencer.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. 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.+ * 3. All advertising materials mentioning features or use of this software+ *    must display the following acknowledgement:+ *	This product includes software developed by the University of+ *	California, Berkeley and its contributors.+ * 4. Neither the name of the University nor the names of its contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS OR CONTRIBUTORS 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.+ *+ *	@(#)regerror.c	8.4 (Berkeley) 3/20/94+ */++#if defined(LIBC_SCCS) && !defined(lint)+static char sccsid[] = "@(#)regerror.c	8.4 (Berkeley) 3/20/94";+#endif /* LIBC_SCCS and not lint */++#include <sys/types.h>+#include <stdio.h>+#include <string.h>+#include <limits.h>+#include <stdlib.h>+#include "regex.h"++#include "utils.h"++/* ========= begin header generated by ./mkh ========= */+#ifdef __cplusplus+extern "C" {+#endif++/* === regerror.c === */+static char *regatoi (const regex_t *preg, char *localbuf);++#ifdef __cplusplus+}+#endif+/* ========= end header generated by ./mkh ========= */+/*+ = #define	REG_NOMATCH	 1+ = #define	REG_BADPAT	 2+ = #define	REG_ECOLLATE	 3+ = #define	REG_ECTYPE	 4+ = #define	REG_EESCAPE	 5+ = #define	REG_ESUBREG	 6+ = #define	REG_EBRACK	 7+ = #define	REG_EPAREN	 8+ = #define	REG_EBRACE	 9+ = #define	REG_BADBR	10+ = #define	REG_ERANGE	11+ = #define	REG_ESPACE	12+ = #define	REG_BADRPT	13+ = #define	REG_EMPTY	14+ = #define	REG_ASSERT	15+ = #define	REG_INVARG	16+ = #define	REG_ATOI	255	// convert name to number (!)+ = #define	REG_ITOA	0400	// convert number to name (!)+ */+static struct rerr {+	int code;+	char *name;+	char *explain;+} rerrs[] = {+	{REG_NOMATCH,	"REG_NOMATCH",	"regexec() failed to match"},+	{REG_BADPAT,	"REG_BADPAT",	"invalid regular expression"},+	{REG_ECOLLATE,	"REG_ECOLLATE",	"invalid collating element"},+	{REG_ECTYPE,	"REG_ECTYPE",	"invalid character class"},+	{REG_EESCAPE,	"REG_EESCAPE",	"trailing backslash (\\)"},+	{REG_ESUBREG,	"REG_ESUBREG",	"invalid backreference number"},+	{REG_EBRACK,	"REG_EBRACK",	"brackets ([ ]) not balanced"},+	{REG_EPAREN,	"REG_EPAREN",	"parentheses not balanced"},+	{REG_EBRACE,	"REG_EBRACE",	"braces not balanced"},+	{REG_BADBR,	"REG_BADBR",	"invalid repetition count(s)"},+	{REG_ERANGE,	"REG_ERANGE",	"invalid character range"},+	{REG_ESPACE,	"REG_ESPACE",	"out of memory"},+	{REG_BADRPT,	"REG_BADRPT",	"repetition-operator operand invalid"},+	{REG_EMPTY,	"REG_EMPTY",	"empty (sub)expression"},+	{REG_ASSERT,	"REG_ASSERT",	"\"can't happen\" -- you found a bug"},+	{REG_INVARG,	"REG_INVARG",	"invalid argument to regex routine"},+	{0,		"",		"*** unknown regexp error code ***"}+};++/*+ - regerror - the interface to error numbers+ = extern size_t regerror(int, const regex_t *, char *, size_t);+ */+/* ARGSUSED */+size_t+regerror(errcode, preg, errbuf, errbuf_size)+int errcode;+const regex_t *preg;+char *errbuf;+size_t errbuf_size;+{+	register struct rerr *r;+	register size_t len;+	register int target = errcode &~ REG_ITOA;+	register char *s;+	char convbuf[50];++	if (errcode == REG_ATOI)+		s = regatoi(preg, convbuf);+	else {+		for (r = rerrs; r->code != 0; r++)+			if (r->code == target)+				break;++		if (errcode&REG_ITOA) {+			if (r->code != 0)+				(void) strcpy(convbuf, r->name);+			else+				sprintf(convbuf, "REG_0x%x", target);+			assert(strlen(convbuf) < sizeof(convbuf));+			s = convbuf;+		} else+			s = r->explain;+	}++	len = strlen(s) + 1;+	if (errbuf_size > 0) {+		if (errbuf_size > len)+			(void) strcpy(errbuf, s);+		else {+			(void) strncpy(errbuf, s, errbuf_size-1);+			errbuf[errbuf_size-1] = '\0';+		}+	}++	return(len);+}++/*+ - regatoi - internal routine to implement REG_ATOI+ == static char *regatoi(const regex_t *preg, char *localbuf);+ */+static char *+regatoi(preg, localbuf)+const regex_t *preg;+char *localbuf;+{+	register struct rerr *r;++	for (r = rerrs; r->code != 0; r++)+		if (strcmp(r->name, preg->re_endp) == 0)+			break;+	if (r->code == 0)+		return("0");++	sprintf(localbuf, "%d", r->code);+	return(localbuf);+}
+ cbits/regex.h view
@@ -0,0 +1,112 @@+/*-+ * Copyright (c) 1992 Henry Spencer.+ * Copyright (c) 1992, 1993+ *	The Regents of the University of California.  All rights reserved.+ *+ * This code is derived from software contributed to Berkeley by+ * Henry Spencer of the University of Toronto.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. 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.+ * 3. All advertising materials mentioning features or use of this software+ *    must display the following acknowledgement:+ *	This product includes software developed by the University of+ *	California, Berkeley and its contributors.+ * 4. Neither the name of the University nor the names of its contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS OR CONTRIBUTORS 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.+ *+ *	@(#)regex.h	8.2 (Berkeley) 1/3/94+ */++#ifndef _REGEX_H_+#define	_REGEX_H_++#include <sys/types.h>++/* types */+typedef off_t regoff_t;++typedef struct {+	int re_magic;+	size_t re_nsub;		/* number of parenthesized subexpressions */+	__const char *re_endp;	/* end pointer for REG_PEND */+	struct re_guts *re_g;	/* none of your business :-) */+} regex_t;++typedef struct {+	regoff_t rm_so;		/* start of match */+	regoff_t rm_eo;		/* end of match */+} regmatch_t;++/* regcomp() flags */+#define	REG_BASIC	0000+#define	REG_EXTENDED	0001+#define	REG_ICASE	0002+#define	REG_NOSUB	0004+#define	REG_NEWLINE	0010+#define	REG_NOSPEC	0020+#define	REG_PEND	0040+#define	REG_DUMP	0200++/* regerror() flags */+#define	REG_NOMATCH	 1+#define	REG_BADPAT	 2+#define	REG_ECOLLATE	 3+#define	REG_ECTYPE	 4+#define	REG_EESCAPE	 5+#define	REG_ESUBREG	 6+#define	REG_EBRACK	 7+#define	REG_EPAREN	 8+#define	REG_EBRACE	 9+#define	REG_BADBR	10+#define	REG_ERANGE	11+#define	REG_ESPACE	12+#define	REG_BADRPT	13+#define	REG_EMPTY	14+#define	REG_ASSERT	15+#define	REG_INVARG	16+#define	REG_ATOI	255	/* convert name to number (!) */+#define	REG_ITOA	0400	/* convert number to name (!) */++/* regexec() flags */+#define	REG_NOTBOL	00001+#define	REG_NOTEOL	00002+#define	REG_STARTEND	00004+#define	REG_TRACE	00400	/* tracing of execution */+#define	REG_LARGE	01000	/* force large representation */+#define	REG_BACKR	02000	/* force use of backref code */++#ifdef __cplusplus+extern "C" {+#endif++int	regcomp (regex_t *, const char *, int);+size_t	regerror (int, const regex_t *, char *, size_t);+int	regexec (const regex_t *,+	    const char *, size_t, regmatch_t [], int);+void	regfree (regex_t *);++#ifdef __cplusplus+}+#endif++#endif /* !_REGEX_H_ */
+ cbits/regex2.h view
@@ -0,0 +1,178 @@+/*-+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.+ * Copyright (c) 1992, 1993, 1994+ *	The Regents of the University of California.  All rights reserved.+ *+ * This code is derived from software contributed to Berkeley by+ * Henry Spencer.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. 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.+ * 3. All advertising materials mentioning features or use of this software+ *    must display the following acknowledgement:+ *	This product includes software developed by the University of+ *	California, Berkeley and its contributors.+ * 4. Neither the name of the University nor the names of its contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS OR CONTRIBUTORS 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.+ *+ *	@(#)regex2.h	8.4 (Berkeley) 3/20/94+ *+ * $FreeBSD: src/lib/libc/regex/regex2.h,v 1.3.6.1 2000/07/31 06:30:37 dcs Exp $+ */++/*+ * First, the stuff that ends up in the outside-world include file+ = typedef off_t regoff_t;+ = typedef struct {+ = 	int re_magic;+ = 	size_t re_nsub;		// number of parenthesized subexpressions+ = 	const char *re_endp;	// end pointer for REG_PEND+ = 	struct re_guts *re_g;	// none of your business :-)+ = } regex_t;+ = typedef struct {+ = 	regoff_t rm_so;		// start of match+ = 	regoff_t rm_eo;		// end of match+ = } regmatch_t;+ */+/*+ * internals of regex_t+ */+#define	MAGIC1	((('r'^0200)<<8) | 'e')++/*+ * The internal representation is a *strip*, a sequence of+ * operators ending with an endmarker.  (Some terminology etc. is a+ * historical relic of earlier versions which used multiple strips.)+ * Certain oddities in the representation are there to permit running+ * the machinery backwards; in particular, any deviation from sequential+ * flow must be marked at both its source and its destination.  Some+ * fine points:+ *+ * - OPLUS_ and O_PLUS are *inside* the loop they create.+ * - OQUEST_ and O_QUEST are *outside* the bypass they create.+ * - OCH_ and O_CH are *outside* the multi-way branch they create, while+ *   OOR1 and OOR2 are respectively the end and the beginning of one of+ *   the branches.  Note that there is an implicit OOR2 following OCH_+ *   and an implicit OOR1 preceding O_CH.+ *+ * In state representations, an operator's bit is on to signify a state+ * immediately *preceding* "execution" of that operator.+ */+typedef unsigned long sop;	/* strip operator */+typedef long sopno;+#define	OPRMASK	0xf8000000L+#define	OPDMASK	0x07ffffffL+#define	OPSHIFT	((unsigned)27)+#define	OP(n)	((n)&OPRMASK)+#define	OPND(n)	((n)&OPDMASK)+#define	SOP(op, opnd)	((op)|(opnd))+/* operators			   meaning	operand			*/+/*						(back, fwd are offsets)	*/+#define	OEND	(1L<<OPSHIFT)	/* endmarker	-			*/+#define	OCHAR	(2L<<OPSHIFT)	/* character	unsigned char		*/+#define	OBOL	(3L<<OPSHIFT)	/* left anchor	-			*/+#define	OEOL	(4L<<OPSHIFT)	/* right anchor	-			*/+#define	OANY	(5L<<OPSHIFT)	/* .		-			*/+#define	OANYOF	(6L<<OPSHIFT)	/* [...]	set number		*/+#define	OBACK_	(7L<<OPSHIFT)	/* begin \d	paren number		*/+#define	O_BACK	(8L<<OPSHIFT)	/* end \d	paren number		*/+#define	OPLUS_	(9L<<OPSHIFT)	/* + prefix	fwd to suffix		*/+#define	O_PLUS	(10L<<OPSHIFT)	/* + suffix	back to prefix		*/+#define	OQUEST_	(11L<<OPSHIFT)	/* ? prefix	fwd to suffix		*/+#define	O_QUEST	(12L<<OPSHIFT)	/* ? suffix	back to prefix		*/+#define	OLPAREN	(13L<<OPSHIFT)	/* (		fwd to )		*/+#define	ORPAREN	(14L<<OPSHIFT)	/* )		back to (		*/+#define	OCH_	(15L<<OPSHIFT)	/* begin choice	fwd to OOR2		*/+#define	OOR1	(16L<<OPSHIFT)	/* | pt. 1	back to OOR1 or OCH_	*/+#define	OOR2	(17L<<OPSHIFT)	/* | pt. 2	fwd to OOR2 or O_CH	*/+#define	O_CH	(18L<<OPSHIFT)	/* end choice	back to OOR1		*/+#define	OBOW	(19L<<OPSHIFT)	/* begin word	-			*/+#define	OEOW	(20L<<OPSHIFT)	/* end word	-			*/++/*+ * Structure for [] character-set representation.  Character sets are+ * done as bit vectors, grouped 8 to a byte vector for compactness.+ * The individual set therefore has both a pointer to the byte vector+ * and a mask to pick out the relevant bit of each byte.  A hash code+ * simplifies testing whether two sets could be identical.+ *+ * This will get trickier for multicharacter collating elements.  As+ * preliminary hooks for dealing with such things, we also carry along+ * a string of multi-character elements, and decide the size of the+ * vectors at run time.+ */+typedef struct {+	uch *ptr;		/* -> uch [csetsize] */+	uch mask;		/* bit within array */+	short hash;             /* hash code */+	size_t smultis;+	char *multis;		/* -> char[smulti]  ab\0cd\0ef\0\0 */+} cset;+/* note that CHadd and CHsub are unsafe, and CHIN doesn't yield 0/1 */+#define CHadd(cs, c)    ((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (uch)(c))+#define CHsub(cs, c)    ((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (uch)(c))+#define	CHIN(cs, c)	((cs)->ptr[(uch)(c)] & (cs)->mask)+#define	MCadd(p, cs, cp)	mcadd(p, cs, cp)	/* regcomp() internal fns */+#define	MCsub(p, cs, cp)	mcsub(p, cs, cp)+#define	MCin(p, cs, cp)	mcin(p, cs, cp)++/* stuff for character categories */+typedef unsigned char cat_t;++/*+ * main compiled-expression structure+ */+struct re_guts {+	int magic;+#		define	MAGIC2	((('R'^0200)<<8)|'E')+	sop *strip;		/* malloced area for strip */+	int csetsize;		/* number of bits in a cset vector */+	int ncsets;		/* number of csets in use */+	cset *sets;		/* -> cset [ncsets] */+	uch *setbits;		/* -> uch[csetsize][ncsets/CHAR_BIT] */+	int cflags;		/* copy of regcomp() cflags argument */+	sopno nstates;		/* = number of sops */+	sopno firststate;	/* the initial OEND (normally 0) */+	sopno laststate;	/* the final OEND */+	int iflags;		/* internal flags */+#		define	USEBOL	01	/* used ^ */+#		define	USEEOL	02	/* used $ */+#		define	BAD	04	/* something wrong */+	int nbol;		/* number of ^ used */+	int neol;		/* number of $ used */+	int ncategories;	/* how many character categories */+	cat_t *categories;	/* ->catspace[-CHAR_MIN] */+	char *must;		/* match must contain this string */+	int moffset;		/* latest point at which must may be located */+	int *charjump;		/* Boyer-Moore char jump table */+	int *matchjump;		/* Boyer-Moore match jump table */+	int mlen;		/* length of must */+	size_t nsub;		/* copy of re_nsub */+	int backrefs;		/* does it use back references? */+	sopno nplus;		/* how deep does it nest +s? */+	/* catspace must be last */+	cat_t catspace[1];	/* actually [NC] */+};++/* misc utilities */+#define	OUT	(CHAR_MAX+1)	/* a non-character value */+#define ISWORD(c)       (isalnum((uch)(c)) || (c) == '_')
+ cbits/regexec.c view
@@ -0,0 +1,181 @@+/*-+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.+ * Copyright (c) 1992, 1993, 1994+ *	The Regents of the University of California.  All rights reserved.+ *+ * This code is derived from software contributed to Berkeley by+ * Henry Spencer.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. 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.+ * 3. All advertising materials mentioning features or use of this software+ *    must display the following acknowledgement:+ *	This product includes software developed by the University of+ *	California, Berkeley and its contributors.+ * 4. Neither the name of the University nor the names of its contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS OR CONTRIBUTORS 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.+ *+ *	@(#)regexec.c	8.3 (Berkeley) 3/20/94+ */++#if defined(LIBC_SCCS) && !defined(lint)+static char sccsid[] = "@(#)regexec.c	8.3 (Berkeley) 3/20/94";+#endif /* LIBC_SCCS and not lint */++/*+ * the outer shell of regexec()+ *+ * This file includes engine.c *twice*, after muchos fiddling with the+ * macros that code uses.  This lets the same code operate on two different+ * representations for state sets.+ */+#include <sys/types.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>+#include <limits.h>+#include <ctype.h>+#include "regex.h"++#include "utils.h"+#include "regex2.h"++static int nope = 0;		/* for use in asserts; shuts lint up */++/* macros for manipulating states, small version */+#define	states	long+#define	states1	states		/* for later use in regexec() decision */+#define	CLEAR(v)	((v) = 0)+#define	SET0(v, n)	((v) &= ~((unsigned long)1 << (n)))+#define	SET1(v, n)	((v) |= (unsigned long)1 << (n))+#define	ISSET(v, n)	(((v) & ((unsigned long)1 << (n))) != 0)+#define	ASSIGN(d, s)	((d) = (s))+#define	EQ(a, b)	((a) == (b))+#define	STATEVARS	long dummy	/* dummy version */+#define	STATESETUP(m, n)	/* nothing */+#define	STATETEARDOWN(m)	/* nothing */+#define	SETUP(v)	((v) = 0)+#define	onestate	long+#define	INIT(o, n)	((o) = (unsigned long)1 << (n))+#define	INC(o)	((o) <<= 1)+#define	ISSTATEIN(v, o)	(((v) & (o)) != 0)+/* some abbreviations; note that some of these know variable names! */+/* do "if I'm here, I can also be there" etc without branches */+#define	FWD(dst, src, n)	((dst) |= ((unsigned long)(src)&(here)) << (n))+#define	BACK(dst, src, n)	((dst) |= ((unsigned long)(src)&(here)) >> (n))+#define	ISSETBACK(v, n)	(((v) & ((unsigned long)here >> (n))) != 0)+/* function names */+#define SNAMES			/* engine.c looks after details */++#include "engine.c"++/* now undo things */+#undef	states+#undef	CLEAR+#undef	SET0+#undef	SET1+#undef	ISSET+#undef	ASSIGN+#undef	EQ+#undef	STATEVARS+#undef	STATESETUP+#undef	STATETEARDOWN+#undef	SETUP+#undef	onestate+#undef	INIT+#undef	INC+#undef	ISSTATEIN+#undef	FWD+#undef	BACK+#undef	ISSETBACK+#undef	SNAMES++/* macros for manipulating states, large version */+#define	states	char *+#define	CLEAR(v)	memset(v, 0, m->g->nstates)+#define	SET0(v, n)	((v)[n] = 0)+#define	SET1(v, n)	((v)[n] = 1)+#define	ISSET(v, n)	((v)[n])+#define	ASSIGN(d, s)	memcpy(d, s, m->g->nstates)+#define	EQ(a, b)	(memcmp(a, b, m->g->nstates) == 0)+#define	STATEVARS	long vn; char *space+#define	STATESETUP(m, nv)	{ (m)->space = malloc((nv)*(m)->g->nstates); \+				if ((m)->space == NULL) return(REG_ESPACE); \+				(m)->vn = 0; }+#define	STATETEARDOWN(m)	{ free((m)->space); }+#define	SETUP(v)	((v) = &m->space[m->vn++ * m->g->nstates])+#define	onestate	long+#define	INIT(o, n)	((o) = (n))+#define	INC(o)	((o)++)+#define	ISSTATEIN(v, o)	((v)[o])+/* some abbreviations; note that some of these know variable names! */+/* do "if I'm here, I can also be there" etc without branches */+#define	FWD(dst, src, n)	((dst)[here+(n)] |= (src)[here])+#define	BACK(dst, src, n)	((dst)[here-(n)] |= (src)[here])+#define	ISSETBACK(v, n)	((v)[here - (n)])+/* function names */+#define	LNAMES			/* flag */++#include "engine.c"++/*+ - regexec - interface for matching+ = extern int regexec(const regex_t *, const char *, size_t, \+ =					regmatch_t [], int);+ = #define	REG_NOTBOL	00001+ = #define	REG_NOTEOL	00002+ = #define	REG_STARTEND	00004+ = #define	REG_TRACE	00400	// tracing of execution+ = #define	REG_LARGE	01000	// force large representation+ = #define	REG_BACKR	02000	// force use of backref code+ *+ * We put this here so we can exploit knowledge of the state representation+ * when choosing which matcher to call.  Also, by this point the matchers+ * have been prototyped.+ */+int				/* 0 success, REG_NOMATCH failure */+regexec(preg, string, nmatch, pmatch, eflags)+const regex_t *preg;+const char *string;+size_t nmatch;+regmatch_t pmatch[];+int eflags;+{+	register struct re_guts *g = preg->re_g;+#ifdef REDEBUG+#	define	GOODFLAGS(f)	(f)+#else+#	define	GOODFLAGS(f)	((f)&(REG_NOTBOL|REG_NOTEOL|REG_STARTEND))+#endif++	if (preg->re_magic != MAGIC1 || g->magic != MAGIC2)+		return(REG_BADPAT);+	assert(!(g->iflags&BAD));+	if (g->iflags&BAD)		/* backstop for no-debug case */+		return(REG_BADPAT);+	eflags = GOODFLAGS(eflags);++	if (g->nstates <= CHAR_BIT*sizeof(states1) && !(eflags&REG_LARGE))+		return(smatcher(g, (char *)string, nmatch, pmatch, eflags));+	else+		return(lmatcher(g, (char *)string, nmatch, pmatch, eflags));+}
+ cbits/regfree.c view
@@ -0,0 +1,87 @@+/*-+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.+ * Copyright (c) 1992, 1993, 1994+ *	The Regents of the University of California.  All rights reserved.+ *+ * This code is derived from software contributed to Berkeley by+ * Henry Spencer.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. 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.+ * 3. All advertising materials mentioning features or use of this software+ *    must display the following acknowledgement:+ *	This product includes software developed by the University of+ *	California, Berkeley and its contributors.+ * 4. Neither the name of the University nor the names of its contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS OR CONTRIBUTORS 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.+ *+ *	@(#)regfree.c	8.3 (Berkeley) 3/20/94+ *+ * $FreeBSD: src/lib/libc/regex/regfree.c,v 1.1.1.1.14.1 2000/07/31 06:30:37 dcs Exp $+ */++#if defined(LIBC_SCCS) && !defined(lint)+static char sccsid[] = "@(#)regfree.c	8.3 (Berkeley) 3/20/94";+#endif /* LIBC_SCCS and not lint */++#include <sys/types.h>+#include <stdio.h>+#include <stdlib.h>+#include <limits.h>+#include "regex.h"++#include "utils.h"+#include "regex2.h"++/*+ - regfree - free everything+ = extern void regfree(regex_t *);+ */+void+regfree(preg)+regex_t *preg;+{+	register struct re_guts *g;++	if (preg->re_magic != MAGIC1)	/* oops */+		return;			/* nice to complain, but hard */++	g = preg->re_g;+	if (g == NULL || g->magic != MAGIC2)	/* oops again */+		return;+	preg->re_magic = 0;		/* mark it invalid */+	g->magic = 0;			/* mark it invalid */++	if (g->strip != NULL)+		free((char *)g->strip);+	if (g->sets != NULL)+		free((char *)g->sets);+	if (g->setbits != NULL)+		free((char *)g->setbits);+	if (g->must != NULL)+		free(g->must);+	if (g->charjump != NULL)+		free(&g->charjump[CHAR_MIN]);+	if (g->matchjump != NULL)+		free(g->matchjump);+	free((char *)g);+}
+ cbits/utils.h view
@@ -0,0 +1,62 @@+/*-+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.+ * Copyright (c) 1992, 1993, 1994+ *	The Regents of the University of California.  All rights reserved.+ *+ * This code is derived from software contributed to Berkeley by+ * Henry Spencer.+ *+ * Redistribution and use in source and binary forms, with or without+ * modification, are permitted provided that the following conditions+ * are met:+ * 1. Redistributions of source code must retain the above copyright+ *    notice, this list of conditions and the following disclaimer.+ * 2. 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.+ * 3. All advertising materials mentioning features or use of this software+ *    must display the following acknowledgement:+ *	This product includes software developed by the University of+ *	California, Berkeley and its contributors.+ * 4. Neither the name of the University nor the names of its contributors+ *    may be used to endorse or promote products derived from this software+ *    without specific prior written permission.+ *+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 THE REGENTS OR CONTRIBUTORS 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.+ *+ *	@(#)utils.h	8.3 (Berkeley) 3/20/94+ */++/* Added by SDM 15/2/2002: apparently mingw doesn't define this constant */+#ifndef _POSIX2_RE_DUP_MAX+#define _POSIX2_RE_DUP_MAX 255+#endif++/* utility definitions */+#define	DUPMAX		_POSIX2_RE_DUP_MAX	/* xxx is this right? */+#define	INFINITY	(DUPMAX + 1)+#define	NC		(CHAR_MAX - CHAR_MIN + 1)+typedef unsigned char uch;++/* switch off assertions (if not already off) if no REDEBUG */+#ifndef REDEBUG+#ifndef NDEBUG+#define	NDEBUG	/* no assertions please */+#endif+#endif+#include <assert.h>++/* for old systems with bcopy() but no memmove() */+#ifdef USEBCOPY+#define	memmove(d, s, c)	bcopy(s, d, c)+#endif
regex-posix.cabal view
@@ -1,49 +1,69 @@ Name:                   regex-posix--- Keep the Version below in sync with ./Text/Regex/Posix.hs value getVersion_Text_Regex_Posix :: Version-Version:                0.94.2+-- Keep the Version below in sync with ./Text/Regex/Posix.hs value+-- getVersion_Text_Regex_Posix :: Version+Version:                0.94.4 Cabal-Version:          >=1.2 Build-Type:             Custom License:                BSD3 License-File:           LICENSE-Copyright:              Copyright (c) 2007, Christopher Kuklewicz+Copyright:              Copyright (c) 2007-2010, Christopher Kuklewicz Author:                 Christopher Kuklewicz Maintainer:             TextRegexLazy@personal.mightyreason.com Stability:              Seems to work, passes a few tests Homepage:               http://sourceforge.net/projects/lazy-regex-Package-URL:            http://darcs.haskell.org/packages/regex-unstable/regex-posix/+Package-URL:            http://code.haskell.org/regex-posix/ Synopsis:               Replaces/Enhances Text.Regex Description:            The posix regex backend for regex-base Category:               Text Tested-With:            GHC Build-Type:             Simple+Extra-Source-Files:     cbits/engine.c cbits/cclass.h cbits/cname.h+                        cbits/regex2.h cbits/regex.h cbits/utils.h+ flag newBase   description: Choose base >= 4   default: True+ flag splitBase   description: Choose the new smaller, split-up base package.   default: True-library++Library   if flag(newBase)       Build-Depends: regex-base >= 0.93, base >= 4 && < 5, array, containers, bytestring       -- Need the next symbol for using CPP to get Data.ByteString.Base|Unsafe in       --  ./Text/Regex/Posix/ByteString.hs and  ./Text/Regex/Posix/ByteString/Lazy.hs       CPP-Options: "-DSPLIT_BASE=1"-      Extensions:         MultiParamTypeClasses, FunctionalDependencies, CPP, ForeignFunctionInterface, GeneralizedNewtypeDeriving, FlexibleContexts, TypeSynonymInstances, FlexibleInstances+      Extensions:         MultiParamTypeClasses, FunctionalDependencies, CPP,+                          ForeignFunctionInterface, GeneralizedNewtypeDeriving,+                          FlexibleContexts, TypeSynonymInstances,+                          FlexibleInstances    else     if flag(splitBase)-      Build-Depends:      regex-base >= 0.93, base >= 3.0, array, containers, bytestring-      -- Need the next symbol for using CPP to get Data.ByteString.Base|Unsafe in-      --  ./Text/Regex/Posix/ByteString.hs and  ./Text/Regex/Posix/ByteString/Lazy.hs+      Build-Depends:      regex-base >= 0.93, base >= 3.0, array, containers,+                          bytestring+      -- Need the next symbol for using CPP to get Data.ByteString.Base|Unsafe+      -- in ./Text/Regex/Posix/ByteString.hs and+      -- ./Text/Regex/Posix/ByteString/Lazy.hs       CPP-Options: "-DSPLIT_BASE=1"-      Extensions:         MultiParamTypeClasses, FunctionalDependencies, CPP, ForeignFunctionInterface, GeneralizedNewtypeDeriving, FlexibleContexts, TypeSynonymInstances, FlexibleInstances+      Extensions:         MultiParamTypeClasses, FunctionalDependencies, CPP,+                          ForeignFunctionInterface, GeneralizedNewtypeDeriving,+                          FlexibleContexts, TypeSynonymInstances,+                          FlexibleInstances      else       Build-Depends:      regex-base >= 0.93, base < 3.0       Extensions:         MultiParamTypeClasses, FunctionalDependencies, CPP +  if !os(windows)+    CC-Options:           -DHAVE_REGEX_H+  else+    C-Sources:            cbits/reallocf.c cbits/regcomp.c cbits/regerror.c+                          cbits/regexec.c cbits/regfree.c+    Include-Dirs:         cbits+   -- Data-Files:-  -- Extra-Source-Files:   -- Extra-Tmp-Files:   -- This is the library   Exposed-Modules:        Text.Regex.Posix@@ -60,13 +80,12 @@   GHC-Options:            -Wall -O2   -- GHC-Options:            -Wall -Werror -O2   -- GHC-Options:            -Wall -ddump-minimal-imports-  -- GHC-Prof-Options: +  -- GHC-Prof-Options:   -- Hugs-Options:   -- NHC-Options:   -- C-Sources:   -- LD-Options:   -- Frameworks:-  CC-Options:             -DHAVE_REGEX_H   -- Includes:   -- Include-Dirs:           include   -- Extra-Libraries: