regcomp.c revision 7c2fbfb345896881c631598ee3852ce9ce33fb07
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* Copyright (c) 1985-2008 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* David Korn <dgk@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Phong Vo <kpv@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * posix regex compiler
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define serialize re_serialize /* hp.ia64 <unistd.h>! */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DEBUG_TEST(f,y,n) ((debug&(debug_flag=f))?(y):(n))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DEBUG_CODE(f,y,n) do if(debug&(f)){y}else{n} while(0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DEBUG_INIT() do { char* t; if (!debug) { debug = 0x80000000; if (t = getenv("_AST_regex_comp_debug")) debug |= strtoul(t, NiL, 0); } } while (0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic unsigned long debug;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic unsigned long debug_flag;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DEBUG_TEST(f,y,n) (n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define DEBUG_CODE(f,y,n) do {n} while(0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct Cchr_s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#define eat(p) do{if ((p)->token.push)(p)->token.push=0;else (p)->cursor+=(p)->token.len;}while (0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * determine whether greedy matching will work, i.e. produce
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * the best match first. such expressions are "easy", and
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * need no backtracking once a complete match is found.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if an expression has backreferences or alts it's hard
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * else if it has only one closure it's easy
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * else if all closures are simple (i.e. one-character) it's easy
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * else it's hard.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct Stats_s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long l; /* min length to left of x */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long k; /* min length to left of y */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long m; /* min length */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long n; /* max length */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned short a; /* number of alternations */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned short b; /* number of backrefs */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned short c; /* number of closures */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned short i; /* number of negations */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned short p; /* number of named subexpressions */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned short s; /* number of simple closures */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned short t; /* number of tries */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned short u; /* number of unnamed subexpressions */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct Token_s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long min;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long max;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct Cenv_s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* paren[i]!=0 if \i defined */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * allocate a new Rex_t node
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinnode(Cenv_t* env, int type, int lo, int hi, size_t extra)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Rex_t* e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (e = (Rex_t*)alloc(env->disc, 0, sizeof(Rex_t) + extra))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * free a Trie_node_t node
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * free a Rex_t node
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (e->type)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; i <= UCHAR_MAX; i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } while (e = x);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * mark e and descendants minimal
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (e && !e->marked)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (e->type)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } while (e = e->next);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * assign subexpression numbers by a preorder tree walk
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (e->type)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } while (e = e->next);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * catenate e and f into a sequence, collapsing them if possible
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (n <= RE_DUP_MAX)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * collect re statistics
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned long n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned long m;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long cm;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long nm;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long cn;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long nn;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long l;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long k;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char b;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (e->type)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (e->re.group.expr.binary.right && stats(env, e->re.group.expr.binary.right))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (e->re.group.number && ++env->stats.p <= 0 || !e->re.group.number && ++env->stats.u <= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (e->type)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (e->re.group.expr.binary.left && stats(env, e->re.group.expr.binary.left))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (q->re.group.expr.binary.left && stats(env, q->re.group.expr.binary.left))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (q->re.group.expr.binary.right && stats(env, q->re.group.expr.binary.right))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (env->stats.m == 1 && b == env->stats.b && c == env->stats.c && ++env->stats.s <= 0)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (!env->stats.x || env->stats.x->re.string.size < e->re.string.size)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!env->stats.y || env->stats.y->re.trie.min < e->re.trie.min)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } while (e = e->next);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinmagic(register Cenv_t* env, register int c, int escaped)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char* sp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int o = c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (n > RE_DUP_MAX)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\\':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (*sp++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (env->type == SRE || c == T_BACK && !(env->flags & REG_LENIENT))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (escaped == 1 && (env->flags & REG_LENIENT) && (c = mp[env->type+escaped+2]) >= T_META)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c < T_OPEN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (env->type == KRE && *(env->cursor + env->token.len) == '-' && *(env->cursor + env->token.len + 1) == '(')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (env->type == KRE && *(env->cursor + env->token.len) == '(')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == T_STAR)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == T_QUES)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c > T_BACK)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = (c > env->parno || !env->paren[c]) ? o : T_BACK + c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (env->type == KRE && !env->parnest && (env->flags & REG_SHELL_GROUP))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == T_BAR)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == T_OPEN)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (env->type >= SRE && !(env->flags & REG_SHELL_ESCAPED) || (env->flags & REG_ESCAPE) && (c == '[' || c == '-' || c == ']' || env->delimiter && c == env->delimiter))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (escaped && !(env->flags & REG_LENIENT) && c != ']')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (*sp++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (*sp++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == 0 || c == env->delimiter || c == env->terminator)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '#')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } while (c != '\n');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!isspace(c))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '\n' && (env->flags & REG_MULTIPLE) && !env->delimiter)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '*')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '\\')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return '\\';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return '\n';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == ')' && env->type == BRE && env->parnest <= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == '$')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (env->type == BRE && (*(env->cursor + 1) == 0 || *(env->cursor + 1) == env->delimiter || *(env->cursor + 1) == env->terminator || *(env->cursor + 1) == '\\' && *(env->cursor + 2) == ')') || (env->flags & REG_MULTIPLE) && *(env->cursor + 1) == '\n')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == '^')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (env->type == BRE && (env->cursor == env->pattern || posixkludge))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == ')')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == '/' && env->explicit == env->mappedslash)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chincol(Celt_t* ce, int ic, unsigned char* bp, int bw, int bc, unsigned char* ep, int ew, int ec)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin register char* s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* k;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register unsigned char* e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int cc;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin s = (char*)bp;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin k += wctomb((char*)k, c);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin for (e = k + bw; k < e; *k++ = *s++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (iswlower(c))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin s = (char*)ep;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin k += wctomb((char*)k, c);
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin for (e = k + ew; k < e; *k++ = *s++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (iswlower(c))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char* first;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char* start;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char* begin;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char* s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*env->cursor == '^' || env->type >= SRE && *env->cursor == '!')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*env->cursor == 0 || *(env->cursor + 1) == 0 || *env->cursor == env->terminator || *(env->cursor + 1) == env->terminator || (env->flags & REG_ESCAPE) && (*env->cursor == env->delimiter || *env->cursor != '\\' && *(env->cursor + 1) == env->delimiter))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * inrange: 0=no, 1=possibly, 2=definitely
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(c = *env->cursor) || c == env->terminator || (env->flags & REG_ESCAPE) && c == env->delimiter)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '\\')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (env->type < SRE || !(env->flags & REG_SHELL_ESCAPED))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (c = 0; c <= UCHAR_MAX; c++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((*f)(c))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (env->type < SRE && !(env->flags & REG_LENIENT) && !mbwide())
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == ']')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == '-')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!inrange && env->cursor != begin && *env->cursor != ']')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == '[')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(f = regclass((char*)env->cursor, (char**)&env->cursor)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (*++s && *s != ':');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (c = 0; c <= UCHAR_MAX; c++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((*f)(c))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((c = regcollate((char*)env->cursor, (char**)&env->cursor, (char*)buf, sizeof(buf))) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c > 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((c = regcollate((char*)env->cursor, (char**)&env->cursor, (char*)buf, sizeof(buf))) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c > 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*env->cursor == env->terminator || *env->cursor == env->delimiter && (env->flags & REG_ESCAPE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (w > 1)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = last; i <= c; i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin inrange = env->type >= SRE || (env->flags & REG_LENIENT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char* rp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char* pp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin static const char primary[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((cc = newof(0, Cchr_t, elementsof(primary), 0)) && (dt = dtopen(&disc, Dttree)))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (!(e = node(env, REX_COLL_CLASS, 1, 1, (elements + 2) * sizeof(Celt_t))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((c = *env->cursor) == 0 || c == env->terminator || (env->flags & REG_ESCAPE) && c == env->delimiter)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '\\')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (env->type < SRE || !(env->flags & REG_SHELL_ESCAPED))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == ']')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == '-')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!inrange && env->cursor != begin && *env->cursor != ']')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == '[')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(f = regclass((char*)env->cursor, (char**)&env->cursor)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (env->cursor == start && (c = *(env->cursor + 1)) && *(env->cursor + 2) == ':' && *(env->cursor + 3) == ']' && *(env->cursor + 4) == ']')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if ((rw = regcollate((char*)env->cursor, (char**)&env->cursor, (char*)pp, COLL_KEY_MAX)) < 0)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (!(cc = (Cchr_t*)dtsearch(dt, &key)) && !(cc = (Cchr_t*)dtprev(dt, &key)))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin xc = (tc = (Cchr_t*)dtprev(dt, cc)) && !strcasecmp((char*)tc->nam, (char*)cc->nam) ? tc : cc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!strcasecmp((char*)xc->nam, (char*)cc->nam) && (tc = (Cchr_t*)dtnext(dt, cc)))
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (c == 'u')
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if ((w = regcollate((char*)env->cursor, (char**)&env->cursor, (char*)pp, COLL_KEY_MAX)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*env->cursor == env->terminator || *env->cursor == env->delimiter && (env->flags & REG_ESCAPE))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin inrange = env->type >= SRE || (env->flags & REG_LENIENT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; i <= UCHAR_MAX; i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (islower(i))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; i < elementsof(e->re.charclass->bits); i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; i <= UCHAR_MAX; i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((*f)(i))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(e = node(env, REX_COLL_CLASS, 1, 1, 2 * sizeof(Celt_t))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long m = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long n = RE_DUP_INF;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (e->type)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (m <= n && n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (; e && e->type >= REX_GROUP && e->type <= REX_GROUP_CUT; e = e->re.group.expr.rex);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (e->type)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (t = (Trie_node_t*)alloc(env->disc, 0, sizeof(Trie_node_t)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char* s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char* e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (f->type)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e = s + 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(t = g->re.trie.root[*s]) && !(t = g->re.trie.root[*s] = trienode(env, *s)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (t->c == *s)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (++s >= e)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * trie() tries to combine nontrivial e and f into a REX_TRIE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * unless 0 is returned, e and f are deleted as far as possible
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * also called by regcomb
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (e->next || f->next || !isstring(e) || e->flags != f->flags)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(g = node(env, REX_TRIE, 0, 0, (UCHAR_MAX + 1) * sizeof(Trie_node_t*))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (g != f)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char* p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '\\')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return c ? c : '\\';
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = chresc((char*)env->cursor - 1, (char**)&env->cursor);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * open the perly gates
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char* p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env->explicit = (env->flags & (REG_NEWLINE|REG_SPAN)) == REG_NEWLINE ? env->mappednewline : -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env->explicit = (env->flags & (REG_NEWLINE|REG_SPAN)) == REG_NEWLINE ? env->mappednewline : -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env->flags |= REG_AUGMENTED|REG_SHELL|REG_LEFT|REG_RIGHT;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* used by caller to disable glob(3) GLOB_BRACE */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* used by caller to disable glob(3) GLOB_NOCHECK */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /* used by caller to disable glob(3) GLOB_STARSTAR */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env->flags &= ~(REG_AUGMENTED|REG_EXTENDED|REG_LITERAL|REG_SHELL|REG_LEFT|REG_RIGHT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e = node(env, REX_NEST, 0, 0, (UCHAR_MAX + 1) * sizeof(unsigned short));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e->re.nest.primary = isalnum(*env->cursor) ? -1 : *env->cursor;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e->re.nest.type[i] = x|REX_NEST_open|REX_NEST_close|(i<<REX_NEST_SHIFT);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!esc && !--n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (isalnum(i) || (e->re.nest.type[i] & (REX_NEST_close|REX_NEST_escape|REX_NEST_literal|REX_NEST_quote|REX_NEST_delimiter|REX_NEST_separator|REX_NEST_terminator)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((x = chr(env, &esc)) < 0 || (e->re.nest.type[x] & (REX_NEST_close|REX_NEST_escape|REX_NEST_delimiter|REX_NEST_separator|REX_NEST_terminator)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (x == ')' && !--n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (x == '(')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (n = 0; n < 2; n++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(e->re.group.expr.binary.right = alt(env, parno, 1)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == '{')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == '}' && !--n)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c != '}')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e->re.exec.data = (*env->disc->re_compf)(env->regex, e->re.exec.text, e->re.exec.size, env->disc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if (c != T_CLOSE && (!(env->flags & REG_LITERAL) || c != ')'))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (x == REX_GROUP_BEHIND || x == REX_GROUP_BEHIND_NOT)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (x)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char* s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char* p;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char* t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char* u;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while ((c = token(env)) < T_META && s < &buf[sizeof(buf) - env->token.len])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c >= 0)
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if ((n = wctomb((char*)s, c)) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (t = p, u = s + n; s < u; *s++ = *t++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((s -= n) == buf)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy((char*)(e->re.string.base = (unsigned char*)e->re.data), (char*)buf, i);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (x >= 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f->re.onechar = (env->flags & REG_ICASE) ? toupper(x) : x;
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin memcpy((char*)(f->re.string.base = (unsigned char*)f->re.data), (char*)p, n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(f = rep(env, f, 0, 0)) || !(f = cat(env, f, seq(env))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy((char*)(e->re.string.base = (unsigned char*)e->re.data), (char*)buf, c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c > T_BACK)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((e = node(env, REX_BEG, 0, 0, 0)) && (env->flags & REG_EXTENDED))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (e->type == REX_NULL && env->type == ERE && !(env->flags & REG_NULL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env->error = (*env->cursor == 0 || *env->cursor == env->delimiter || *env->cursor == env->terminator) ? REG_EPAREN : REG_ENULL;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (e && *env->cursor != 0 && *env->cursor != env->delimiter && *env->cursor != env->terminator)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(e = seq(env)) || !(env->flags & REG_AUGMENTED) || token(env) != T_AND)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((e->type == REX_NULL || f->type == REX_NULL) && !(env->flags & REG_NULL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * add v to REX_BM tables
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic void
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinbmstr(Cenv_t* env, register Rex_t* a, unsigned char* v, int n, Bm_mask_t b)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (m = 0; m < n; m++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(z = n - m - 1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (z == HIT || !a->re.bm.skip[c] || a->re.bm.skip[c] > z && a->re.bm.skip[c] < HIT)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (islower(c))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (z == HIT || !a->re.bm.skip[c] || a->re.bm.skip[c] > z && a->re.bm.skip[c] < HIT)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * set up BM table from trie
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinbmtrie(Cenv_t* env, Rex_t* a, unsigned char* v, Trie_node_t* x, int n, int m, Bm_mask_t b)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin v[m] = x->c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (m >= (n - 1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(b <<= 1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (x->son)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (x->son)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } while (x = x->sib);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * rewrite the expression tree for some special cases
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * 1. it is a null expression - illegal
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * 2. max length fixed string found -- use BM algorithm
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * 3. it begins with an unanchored string - use KMP algorithm
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * 0 returned on success
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char* s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (x && t)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char* v;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned long l;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(q = (size_t*)alloc(env->disc, 0, (n + 1) * sizeof(size_t))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(a = node(env, REX_BM, 0, 0, n * (sizeof(Bm_mask_t*) + (UCHAR_MAX + 1) * sizeof(Bm_mask_t)) + (UCHAR_MAX + n + 2) * sizeof(size_t))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin a->re.bm.back = (y == e || y == e->re.group.expr.rex) ? (m - n) : -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin a->re.bm.complete = (y != e && (e->type != REX_GROUP || y != e->re.group.expr.rex) || e->next || ((a->re.bm.left + a->re.bm.right) >= 0)) ? 0 : n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (m = 0; m <= UCHAR_MAX; m++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin a->re.bm.skip[0] = a->re.bm.skip[env->mappednewline] = (y->next && y->next->type == REX_END) ? HIT : (n + a->re.bm.left);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 1; i <= n; i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (m = 0; m < n; m++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin v = (unsigned char*)q;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; i <= UCHAR_MAX; i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memset(q, 0, n * sizeof(*q));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (k = (j = n) + 1; j > 0; j--, k--)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin DEBUG_TEST(0x0010,(sfprintf(sfstderr, "BM#0: k=%d j=%d\n", k, j)),(0));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (q[j] = k; k <= n; k = q[k])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (m = 0; m <= UCHAR_MAX; m++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin DEBUG_TEST(0x0010,sfprintf(sfstderr, "CUT1: mask[%d][%c]=mask[%d][%c]\n", k, m, j, m), (0));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin DEBUG_TEST(0x0010,sfprintf(sfstderr, "BM#2: fail[%d]=%d => %d\n", k, a->re.bm.fail[k], (a->re.bm.fail[k] > n - j) ? (n - j) : a->re.bm.fail[k]), (0));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 1; i <= n; i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin DEBUG_TEST(0x0010,sfprintf(sfstderr, "BM#4: fail[%d]=%d => %d\n", i, a->re.bm.fail[i], n + k - i), (0));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr, "STAT: complete=%d n=%d k=%d l=%d r=%d y=%d:%d e=%d:%d\n", a->re.bm.complete, n, k, a->re.bm.left, a->re.bm.right, y->type, y->next ? y->next->type : 0, e->type, e->next ? e->next->type : 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (m = 0; m < n; m++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr, "MASK: [%d]['%c'] = %032..2u\n", m, i, a->re.bm.mask[m][i]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstderr, "SKIP: ['%c'] = %3d\n", i, a->re.bm.skip[i]);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (j = 31; j >= 0; j--)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (m = 0; m < n; m++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (i >= 0177)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (j > 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (m = 1; m <= n; m++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (e->type)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*FALLTHROUGH*/
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin if ((env->flags & (REG_LEFT|REG_LITERAL|REG_RIGHT)) || e->map)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(a = node(env, REX_KMP, 0, 0, n * (sizeof(int*) + 1))))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin memcpy((char*)(a->re.string.base = (unsigned char*)&f[n]), (char*)s, n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin f[0] = m = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (k = 1; k < n; k++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (m >= 0 && s[m+1] != s[k])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (s[m+1] == s[k])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinregcomp(regex_t* p, const char* pattern, regflags_t flags)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin unsigned char* fold;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin state.magic[state.escape[i].key] = state.escape[i].val;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(fold = (unsigned char*)LCINFO(AST_LC_CTYPE)->data))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; i <= UCHAR_MAX; i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (disc->re_version >= REG_VERSION_MAP && disc->re_map)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 0; i <= UCHAR_MAX; i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env.type = (env.flags & REG_AUGMENTED) ? ARE : (env.flags & REG_EXTENDED) ? ERE : BRE;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if ((env.flags & (REG_NEWLINE|REG_SPAN)) == REG_NEWLINE)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->env->leading = (env.flags & REG_SHELL_DOT) ? env.mappeddot : -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env.posixkludge = !(env.flags & (REG_EXTENDED|REG_SHELL));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\\':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\n':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '\r':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin env.literal = env.pattern = env.cursor = (unsigned char*)pattern;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin p->env->stats.re_flags = env.flags & (REG_EXTENDED|REG_AUGMENTED|REG_SHELL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!(env.flags & REG_FIRST) && (env.stats.a || env.stats.c > 1 && env.stats.c != env.stats.s || env.stats.t && (env.stats.t > 1 || env.stats.a || env.stats.c)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (env.type >= SRE && env.error != REG_ESPACE && !(flags & REG_LITERAL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * regcomp() on sized pattern
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * the lazy way around adding and checking env.end
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinregncomp(regex_t* p, const char* pattern, size_t size, regflags_t flags)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return fatal((flags & REG_DISCIPLINE) ? p->re_disc : &state.disc, REG_ESPACE, pattern);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * combine two compiled regular expressions if possible,
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * replacing first with the combination and freeing second.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * return 0 on success.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * the only combinations handled are building a Trie
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * from String|Kmp|Trie and String|Kmp
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!e || !f)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (e->next && e->next->type == REX_END && f->next && f->next->type == REX_END)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return fatal(p->env->disc, env.error ? env.error : REG_ECOUNT, NiL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return fatal(p->env->disc, env.error ? env.error : REG_ESPACE, NiL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * copy a reference of p into q
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * p and q may then have separate regsubcomp() instantiations
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!p || !q)