/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1985-2010 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* David Korn <dgk@research.att.com> *
* Phong Vo <kpv@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* posix regex executor
* single sized-record interface
*/
#include "reglib.h"
#if _AST_REGEX_DEBUG
#define DEBUG_INIT() do { char* t; if (!debug) { debug = 0x80000000; if (t = getenv("_AST_regex_exec_debug")) debug |= strtoul(t, NiL, 0); } } while (0)
static unsigned long debug;
static unsigned long debug_flag;
static const char* rexnames[] =
{
"REX_NULL",
"REX_ALT",
"REX_ALT_CATCH",
"REX_BACK",
"REX_BEG",
"REX_BEG_STR",
"REX_BM",
"REX_CAT",
"REX_CLASS",
"REX_COLL_CLASS",
"REX_CONJ",
"REX_CONJ_LEFT",
"REX_CONJ_RIGHT",
"REX_DONE",
"REX_DOT",
"REX_END",
"REX_END_STR",
"REX_EXEC",
"REX_FIN_STR",
"REX_GROUP",
"REX_GROUP_CATCH",
"REX_GROUP_AHEAD",
"REX_GROUP_AHEAD_CATCH",
"REX_GROUP_AHEAD_NOT",
"REX_GROUP_BEHIND",
"REX_GROUP_BEHIND_CATCH",
"REX_GROUP_BEHIND_NOT",
"REX_GROUP_BEHIND_NOT_CATCH",
"REX_GROUP_COND",
"REX_GROUP_COND_CATCH",
"REX_GROUP_CUT",
"REX_GROUP_CUT_CATCH",
"REX_KMP",
"REX_NEG",
"REX_NEG_CATCH",
"REX_NEST",
"REX_ONECHAR",
"REX_REP",
"REX_REP_CATCH",
"REX_STRING",
"REX_TRIE",
"REX_WBEG",
"REX_WEND",
"REX_WORD",
"REX_WORD_NOT"
};
{
if (!rex)
return "NIL";
return "ERROR";
}
#else
#define DEBUG_INIT()
#define DEBUG_TEST(f,y,n) (n)
#define DEBUG_CODE(f,y,n) do {n} while(0)
#endif
/*
* returns from parse()
*/
/*
* REG_SHELL_DOT test
*/
/*
* Pos_t is for comparing parses. An entry is made in the
* array at the beginning and at the end of each Group_t,
* each iteration in a Group_t, and each Binary_t.
*/
typedef struct
{
unsigned char* p; /* where in string */
} Pos_t;
/* ===== begin library support ===== */
static Vector_t*
{
Vector_t* v;
if (inc <= 0)
inc = 16;
return 0;
{
return 0;
}
v->cur = 0;
return v;
}
static void*
{
Vector_t* v = *p;
{
return 0;
*p = v;
}
}
static void
{
if (v)
}
typedef struct
{
} Stk_frame_t;
static void*
{
Stk_frame_t* f;
Stk_pos_t p;
return 0;
f->pos = p;
return f->data;
}
/* ===== end library support ===== */
/*
* Match_frame_t is for saving and restoring match records
* around alternate attempts, so that fossils will not be
* left in the match array. These are the only entries in
* the match array that are not otherwise guaranteed to
* have current data in them when they get used.
*/
typedef struct
{
#define matchcopy(e,x) ((x)->re.group.number?memcpy(matchframe->match,matchframe->save,matchframe->size):(void*)0)
#define matchpop(e,x) ((x)->re.group.number?memcpy(matchframe->match,matchframe->save,matchframe->size),stkpop(stkstd):(void*)0)
/*
* allocate a frame and push a match onto the stack
*/
static int
{
Match_frame_t* f;
regmatch_t* m;
regmatch_t* e;
regmatch_t* s;
int num;
num = 0;
{
return 1;
}
e = m + num;
s = f->save;
while (m < e)
{
*s++ = *m;
}
return 0;
}
/*
* allocate a frame and push a pos onto the stack
*/
static int
{
{
return 1;
}
pos->p = p;
return 0;
}
/*
* two matches are known to have the same length
* os is start of old pos array, ns is start of new,
* oend and nend are end+1 pointers to ends of arrays.
* oe and ne are ends (not end+1) of subarrays.
* returns 1 if new is better, -1 if old, else 0.
*/
static int
{
int k;
int n;
return -1;
for (;;)
{
DEBUG_CODE(0x0080,{sfprintf(sfstdout, " %-*.*sold ", (level + 3) * 4, (level + 3) * 4, "");for (oe = os; oe < oend; oe++)sfprintf(sfstdout, "<%d,%d,%d>", oe->p - env->beg, oe->serial, oe->be);sfprintf(sfstdout, "\n %-*.*snew ", (level + 3) * 4, (level + 3) * 4, "");for (oe = ns; oe < nend; oe++)sfprintf(sfstdout, "<%d,%d,%d>", oe->p - env->beg, oe->serial, oe->be);sfprintf(sfstdout, "\n");},{0;});
return -1;
{
return -1;
}
return 1;
return -1;
k = 0;
for (;;)
{
k++;
else if (k-- <= 0)
break;
}
k = 0;
for (;;)
{
k++;
else if (k-- <= 0)
break;
}
return 1;
return -1;
return k;
}
}
#if _AST_REGEX_DEBUG
static void
{
if (p->rm_so < 0)
else
if (p->rm_eo < 0)
else
}
static int
{
int i;
DEBUG_CODE(0x0040,{sfprintf(sfstdout, "AHA better old ");for (i = 0; i <= env->nsub; i++)showmatch(&env->best[i]);sfprintf(sfstdout, "\n new ");for (i = 0; i <= env->nsub; i++)showmatch(&env->match[i]);sfprintf(sfstdout, "\n");},{0;});
return i;
}
#endif
static int
{
int i;
int r = NONE;
DEBUG_TEST(0x0010,(sfprintf(sfstdout, "AHA#%04d 0x%04x parserep %s %d %d %d %d `%-.*s'\n", __LINE__, debug_flag, rexname(rex->re.group.expr.rex), rex->re.group.number, rex->lo, n, rex->hi, env->end - s, s)),(0));
{
return BAD;
switch (i)
{
case BAD:
return BAD;
case CUT:
return CUT;
case BEST:
case GOOD:
return BEST;
}
}
{
if (n == 0)
{
return BAD;
return BAD;
DEBUG_TEST(0x0004,(sfprintf(sfstdout,"AHA#%04d 0x%04x PUSH %d (%d,%d)(%d,%d)(%d,%d) (%d,%d)(%d,%d)(%d,%d)\n", __LINE__, debug_flag, rex->re.group.number, env->best[0].rm_so, env->best[0].rm_eo, env->best[1].rm_so, env->best[1].rm_eo, env->best[2].rm_so, env->best[2].rm_eo, env->match[0].rm_so, env->match[0].rm_eo, env->match[1].rm_so, env->match[1].rm_eo, env->match[2].rm_so, env->match[2].rm_eo)),(0));
}
DEBUG_TEST(0x0010,(sfprintf(sfstdout, "AHA#%04d 0x%04x parserep parse %d %d `%-.*s'\n", __LINE__, debug_flag, rex->re.group.number, r, env->end - s, s)),(0));
{
DEBUG_TEST(0x0004,(sfprintf(sfstdout,"AHA#%04d 0x%04x POP %d %d (%d,%d)(%d,%d)(%d,%d) (%d,%d)(%d,%d)(%d,%d)\n", __LINE__, debug_flag, rex->re.group.number, r, env->best[0].rm_so, env->best[0].rm_eo, env->best[1].rm_so, env->best[1].rm_eo, env->best[2].rm_so, env->best[2].rm_eo, env->match[0].rm_so, env->match[0].rm_eo, env->match[1].rm_so, env->match[1].rm_eo, env->match[2].rm_so, env->match[2].rm_eo)),(0));
}
switch (r)
{
case BAD:
return BAD;
case BEST:
return BEST;
case CUT:
r = NONE;
break;
case GOOD:
return BEST;
r = GOOD;
break;
}
}
return r;
{
return BAD;
switch (i)
{
case BAD:
r = BAD;
break;
case CUT:
r = CUT;
break;
case BEST:
r = BEST;
break;
case GOOD:
break;
}
}
return r;
}
static int
{
unsigned char* p;
int r;
{
for (;;)
{
return NONE;
while (x->c != p[*s])
if (!(x = x->sib))
return NONE;
if (x->end)
break;
x = x->son;
s++;
}
}
else
{
for (;;)
{
return NONE;
while (x->c != *s)
if (!(x = x->sib))
return NONE;
if (x->end)
break;
x = x->son;
s++;
}
}
s++;
{
case BAD:
return BAD;
case CUT:
return CUT;
case BEST:
case GOOD:
return BEST;
}
if (x->son)
{
case BAD:
return BAD;
case CUT:
return CUT;
case BEST:
return BEST;
case GOOD:
return BEST;
r = GOOD;
break;
default:
r = NONE;
break;
}
else
r = NONE;
{
case BAD:
return BAD;
case CUT:
return CUT;
case BEST:
return BEST;
case GOOD:
return GOOD;
}
return r;
}
static int
{
for (;; ce++)
{
{
case COLL_call:
return 1;
continue;
case COLL_char:
return 1;
continue;
case COLL_range:
return 1;
continue;
case COLL_range_lc:
if (strcmp((char*)ce->beg, (char*)elt) <= ce->min && strcmp((char*)elt, (char*)ce->end) <= ce->max && (iswlower(c) || !iswupper(c)))
return 1;
continue;
case COLL_range_uc:
if (strcmp((char*)ce->beg, (char*)elt) <= ce->min && strcmp((char*)elt, (char*)ce->end) <= ce->max && (iswupper(c) || !iswlower(c)))
return 1;
continue;
}
break;
}
return 0;
}
static int
{
if (!x)
{
return 1;
if (iswlower(c))
c = towupper(c);
else if (iswupper(c))
c = towlower(c);
else
return 0;
key[x] = 0;
}
while (*nxt)
{
return 1;
else
return 0;
nxt++;
}
}
static int
{
unsigned char* t;
wchar_t c;
int w;
int r;
int x;
int ic;
if ((w = MBSIZE(s)) > 1)
{
key[w] = 0;
t = s;
c = mbchar(t);
#if !_lib_wctype
c &= 0xff;
#endif
x = 0;
}
else
{
c = s[0];
c = tolower(c);
key[0] = c;
key[1] = 0;
if (isalpha(c))
{
x = e - s;
if (x > COLL_KEY_MAX)
x = COLL_KEY_MAX;
while (w < x)
{
c = s[w];
if (!isalpha(c))
break;
c = tolower(c);
key[w] = c;
key[w + 1] = 0;
break;
w++;
}
}
key[w] = 0;
c = key[0];
x = w - 1;
}
r = 1;
for (;;)
{
if (ic ? collic(rex->re.collate.elements, (char*)key, (char*)key, c, x) : collelt(rex->re.collate.elements, (char*)key, c, x))
break;
if (!x)
{
r = 0;
break;
}
w = x--;
key[w] = 0;
}
*p = s + w;
}
static unsigned char*
nestmatch(register unsigned char* s, register unsigned char* e, const unsigned short* type, register int co)
{
register int c;
register int cc;
unsigned int n;
int oc;
{
while (s < e)
{
c = *s++;
if (c == co)
return s;
else if (type[c] & n)
{
if (s >= e || (type[c] & REX_NEST_terminator))
break;
s++;
}
}
}
else
{
n = 1;
while (s < e)
{
c = *s++;
switch (type[c] & (REX_NEST_escape|REX_NEST_open|REX_NEST_close|REX_NEST_delimiter|REX_NEST_separator|REX_NEST_terminator))
{
case REX_NEST_delimiter:
case REX_NEST_terminator:
return oc ? 0 : s;
case REX_NEST_separator:
if (!oc)
return s;
break;
case REX_NEST_escape:
if (s >= e)
return 0;
s++;
break;
case REX_NEST_open|REX_NEST_close:
if (c == cc)
{
if (!--n)
return s;
}
/*FALLTHROUGH*/
case REX_NEST_open:
if (c == co)
{
if (!++n)
return 0;
}
return 0;
break;
case REX_NEST_close:
if (c != cc)
return 0;
if (!--n)
return s;
break;
}
}
}
return 0;
}
static int
{
int c;
int d;
int i;
int m;
int n;
int r;
int* f;
unsigned char* p;
unsigned char* t;
unsigned char* b;
unsigned char* e;
char* u;
regmatch_t* o;
Trie_node_t* x;
Rex_t* q;
for (;;)
{
DEBUG_TEST(0x0008,(sfprintf(sfstdout, "AHA#%04d 0x%04x parse %s `%-.*s'\n", __LINE__, debug_flag, rexname(rex), env->end - s, s)),(0));
{
case REX_ALT:
{
return BAD;
return BAD;
{
((Pos_t*)env->pos->vec + env->pos->cur - 1)->serial = catcher.serial = rex->re.group.expr.binary.serial;
if (n != NONE)
r = n;
}
}
else
{
if (r == GOOD)
r = BEST;
}
return r;
case REX_ALT_CATCH:
return BAD;
return r;
case REX_BACK:
if (o->rm_so < 0)
return NONE;
e = s + i;
return NONE;
{
while (s < e)
if (*s++ != *t++)
return NONE;
}
else if (!mbwide())
{
while (s < e)
if (p[*s++] != p[*t++])
return NONE;
}
else
{
while (s < e)
{
c = mbchar(s);
d = mbchar(t);
return NONE;
}
}
break;
case REX_BEG:
if ((!(rex->flags & REG_NEWLINE) || s <= env->beg || *(s - 1) != '\n') && ((env->flags & REG_NOTBOL) || s != env->beg))
return NONE;
break;
case REX_CLASS:
return NONE;
if (m > n)
return NONE;
r = NONE;
{
for (i = 0; i < n; i++)
{
n = i;
break;
}
for (s += n; n-- >= m; s--)
{
case BAD:
return BAD;
case CUT:
return CUT;
case BEST:
return BEST;
case GOOD:
r = GOOD;
break;
}
}
else
{
for (e = s + m; s < e; s++)
return r;
e += n - m;
for (;;)
{
{
case BAD:
return BAD;
case CUT:
return CUT;
case BEST:
case GOOD:
return BEST;
}
break;
s++;
}
}
return r;
case REX_COLL_CLASS:
return NONE;
if (m > n)
return NONE;
r = NONE;
{
{
return BAD;
}
{
b[i] = t - s;
s = t;
}
{
case BAD:
return BAD;
case CUT:
return CUT;
case BEST:
return BEST;
case GOOD:
r = GOOD;
break;
}
}
else
{
for (i = 0; i < m && s < e; i++, s = t)
return r;
while (i++ <= n)
{
{
case BAD:
return BAD;
case CUT:
return CUT;
case BEST:
case GOOD:
return BEST;
}
break;
}
}
return r;
case REX_CONJ:
case REX_CONJ_LEFT:
continue;
case REX_CONJ_RIGHT:
return NONE;
break;
case REX_DONE:
return BEST;
DEBUG_TEST(0x0100,(sfprintf(sfstdout,"AHA#%04d 0x%04x %s (%d,%d)(%d,%d)(%d,%d)(%d,%d) (%d,%d)(%d,%d)\n", __LINE__, debug_flag, rexname(rex), env->best[0].rm_so, env->best[0].rm_eo, env->best[1].rm_so, env->best[1].rm_eo, env->best[2].rm_so, env->best[2].rm_eo, env->best[3].rm_so, env->best[3].rm_eo, env->match[0].rm_so, env->match[0].rm_eo, env->match[1].rm_so, env->match[1].rm_eo)),(0));
{
{
if (n > i)
return GOOD;
}
else
{
if (n < i)
return GOOD;
}
0) <= 0)
return GOOD;
}
{
return BAD;
}
DEBUG_TEST(0x0100,(sfprintf(sfstdout,"AHA#%04d 0x%04x %s (%d,%d)(%d,%d)(%d,%d)(%d,%d) (%d,%d)(%d,%d)\n", __LINE__, debug_flag, rexname(rex), env->best[0].rm_so, env->best[0].rm_eo, env->best[1].rm_so, env->best[1].rm_eo, env->best[2].rm_so, env->best[2].rm_eo, env->best[3].rm_so, env->best[3].rm_eo, env->match[0].rm_so, env->match[0].rm_eo, env->match[1].rm_so, env->match[1].rm_eo)),(0));
return GOOD;
case REX_DOT:
return NONE;
if (m > n)
return NONE;
for (i = 0; i < n; i++)
if (s[i] == c)
{
n = i;
break;
}
r = NONE;
{
if (!mbwide())
{
for (s += n; n-- >= m; s--)
{
case BAD:
return BAD;
case CUT:
return CUT;
case BEST:
return BEST;
case GOOD:
r = GOOD;
break;
}
}
else
{
{
return BAD;
}
for (i = 0; s < e && i < n && *s != c; i++)
s += b[i] = MBSIZE(s);
for (; i-- >= m; s -= b[i])
{
case BAD:
return BAD;
case CUT:
return CUT;
case BEST:
return BEST;
case GOOD:
r = GOOD;
break;
}
}
}
else
{
if (!mbwide())
{
e = s + n;
for (s += m; s <= e; s++)
{
case BAD:
return BAD;
case CUT:
return CUT;
case BEST:
case GOOD:
return BEST;
}
}
else
{
for (i = 0; s < e && i < m && *s != c; i++)
s += MBSIZE(s);
if (i >= m)
for (; s <= e && i <= n; s += MBSIZE(s), i++)
{
case BAD:
return BAD;
case CUT:
return CUT;
case BEST:
case GOOD:
return BEST;
}
}
}
return r;
case REX_END:
return NONE;
break;
case REX_GROUP:
DEBUG_TEST(0x0200,(sfprintf(sfstdout,"AHA#%04d 0x%04x parse %s `%-.*s'\n", __LINE__, debug_flag, rexname(rex), env->end - s, s)),(0));
{
return BAD;
catcher.re.group_catch.eo = rex->re.group.number ? &env->match[rex->re.group.number].rm_eo : (regoff_t*)0;
}
{
}
return r;
case REX_GROUP_CATCH:
DEBUG_TEST(0x0200,(sfprintf(sfstdout,"AHA#%04d 0x%04x parse %s=>%s `%-.*s'\n", __LINE__, debug_flag, rexname(rex), rexname(rex->re.group_catch.cont), env->end - s, s)),(0));
{
return BAD;
}
{
}
return r;
case REX_GROUP_AHEAD:
case REX_GROUP_AHEAD_CATCH:
case REX_GROUP_AHEAD_NOT:
if (r == NONE)
else if (r != BAD)
r = NONE;
return r;
case REX_GROUP_BEHIND:
return NONE;
{
if (r != NONE)
return r;
}
return NONE;
case REX_GROUP_BEHIND_CATCH:
return NONE;
case REX_GROUP_BEHIND_NOT:
r = NONE;
else
{
{
if (r != NONE)
break;
}
}
if (r == NONE)
else if (r != BAD)
r = NONE;
return r;
case REX_GROUP_COND:
{
}
else
{
return r;
}
else if (!rex->re.group.size || rex->re.group.size > 0 && env->match[rex->re.group.size].rm_so >= 0)
r = GOOD;
else
r = NONE;
{
}
case REX_GROUP_COND_CATCH:
case REX_CAT:
case REX_GROUP_CUT:
case REX_GROUP_CUT_CATCH:
{
case GOOD:
r = BEST;
break;
case NONE:
r = CUT;
break;
}
return r;
case REX_KMP:
t = s;
{
while (t + n <= e)
{
for (i = -1; t < e; t++)
{
while (i >= 0 && b[i+1] != p[*t])
i = f[i];
if (b[i+1] == p[*t])
i++;
if (i + 1 == n)
{
t++;
{
case BAD:
return BAD;
case CUT:
return CUT;
case BEST:
case GOOD:
return BEST;
}
t -= n - 1;
break;
}
}
}
}
else
{
while (t + n <= e)
{
for (i = -1; t < e; t++)
{
while (i >= 0 && b[i+1] != *t)
i = f[i];
if (b[i+1] == *t)
i++;
if (i + 1 == n)
{
t++;
{
case BAD:
return BAD;
case CUT:
return CUT;
case BEST:
case GOOD:
return BEST;
}
t -= n - 1;
break;
}
}
}
}
return NONE;
case REX_NEG:
return NONE;
n = ((i + 7) >> 3) + 1;
return BAD;
r = BAD;
else
{
r = NONE;
for (; i >= 0; i--)
if (!bittst(p, i))
{
{
case BAD:
r = BAD;
break;
case BEST:
r = BEST;
break;
case CUT:
r = CUT;
break;
case GOOD:
r = GOOD;
/*FALLTHROUGH*/
default:
continue;
}
break;
}
}
return r;
case REX_NEG_CATCH:
return NONE;
case REX_NEST:
return NONE;
do
{
{
return NONE;
break;
}
return NONE;
break;
return NONE;
} while (s < env->end && !(rex->re.nest.type[*(s-1)] & (REX_NEST_delimiter|REX_NEST_separator|REX_NEST_terminator)));
break;
case REX_NULL:
break;
case REX_ONECHAR:
if (m > n)
return NONE;
r = NONE;
{
if (!mbwide())
{
{
for (i = 0; i < n; i++, s++)
if (p[*s] != c)
break;
}
else
{
for (i = 0; i < n; i++, s++)
if (*s != c)
break;
}
for (; i-- >= m; s--)
{
case BAD:
return BAD;
case BEST:
return BEST;
case CUT:
return CUT;
case GOOD:
r = GOOD;
break;
}
}
else
{
{
return BAD;
}
{
for (i = 0; s < e && i < n; i++, s = t)
{
t = s;
if (mbchar(t) != c)
break;
b[i] = t - s;
}
}
else
{
for (i = 0; s < e && i < n; i++, s = t)
{
t = s;
break;
b[i] = t - s;
}
}
for (; i-- >= m; s -= b[i])
{
case BAD:
return BAD;
case BEST:
return BEST;
case CUT:
return CUT;
case GOOD:
r = GOOD;
break;
}
}
}
else
{
if (!mbwide())
{
e = s + m;
{
for (; s < e; s++)
if (p[*s] != c)
return r;
e += n - m;
for (;;)
{
{
case BAD:
return BAD;
case CUT:
return CUT;
case BEST:
case GOOD:
return BEST;
}
if (s >= e || p[*s++] != c)
break;
}
}
else
{
for (; s < e; s++)
if (*s != c)
return r;
e += n - m;
for (;;)
{
{
case BAD:
return BAD;
case CUT:
return CUT;
case BEST:
case GOOD:
return BEST;
}
if (s >= e || *s++ != c)
break;
}
}
}
else
{
{
for (i = 0; i < m && s < e; i++, s = t)
{
t = s;
if (mbchar(t) != c)
return r;
}
while (i++ <= n)
{
{
case BAD:
return BAD;
case CUT:
return CUT;
case BEST:
case GOOD:
return BEST;
}
if (s >= e || mbchar(s) != c)
break;
}
}
else
{
for (i = 0; i < m && s < e; i++, s = t)
{
t = s;
return r;
}
while (i++ <= n)
{
{
case BAD:
return BAD;
case CUT:
return CUT;
case BEST:
case GOOD:
return BEST;
}
break;
}
}
}
}
return r;
case REX_REP:
return BAD;
return r;
case REX_REP_CATCH:
DEBUG_TEST(0x0020,(sfprintf(sfstdout, "AHA#%04d 0x%04x %s n %d len %d s `%-.*s'\n", __LINE__, debug_flag, rexname(rex), rex->re.rep_catch.n, s - rex->re.rep_catch.beg, env->end - s, s)),(0));
return BAD;
{
/*
* optional empty iteration
*/
DEBUG_TEST(0x0002,(sfprintf(sfstdout, "AHA#%04d %p re.group.back=%d re.group.expr.rex=%s\n", __LINE__, rex->re.rep_catch.ref->re.group.expr.rex, rex->re.rep_catch.ref->re.group.expr.rex->re.group.back, rexname(rex->re.rep_catch.ref->re.group.expr.rex))),(0));
if (!env->stack || s != rex->re.rep_catch.ref->re.rep_catch.beg && !rex->re.rep_catch.ref->re.group.expr.rex->re.group.back)
r = NONE;
r = BAD;
else
{
}
}
else
return r;
case REX_STRING:
DEBUG_TEST(0x0200,(sfprintf(sfstdout,"AHA#%04d 0x%04x parse %s \"%-.*s\" `%-.*s'\n", __LINE__, debug_flag, rexname(rex), rex->re.string.size, rex->re.string.base, env->end - s, s)),(0));
return NONE;
{
while (t < e)
if (*s++ != *t++)
return NONE;
}
else if (!mbwide())
{
while (t < e)
if (p[*s++] != *t++)
return NONE;
}
else
{
while (t < e)
{
c = mbchar(s);
d = mbchar(t);
if (towupper(c) != d)
return NONE;
}
}
break;
case REX_TRIE:
return NONE;
case REX_EXEC:
u = 0;
r = (*env->disc->re_execf)(env->regex, rex->re.exec.data, rex->re.exec.text, rex->re.exec.size, (const char*)s, env->end - s, &u, env->disc);
e = (unsigned char*)u;
s = e;
switch (r)
{
case 0:
break;
case REG_NOMATCH:
return NONE;
default:
return BAD;
}
break;
case REX_WBEG:
return NONE;
break;
case REX_WEND:
return NONE;
break;
case REX_WORD:
return NONE;
break;
case REX_WORD_NOT:
return NONE;
break;
case REX_BEG_STR:
return NONE;
break;
case REX_END_STR:
return NONE;
break;
case REX_FIN_STR:
return NONE;
break;
}
{
break;
cont = 0;
}
}
return GOOD;
}
#if _AST_REGEX_DEBUG
static void
{
int i;
if (e)
{
do
{
for (i = 0; i < level; i++)
switch (e->type)
{
case REX_ALT:
case REX_CONJ:
break;
case REX_GROUP:
case REX_GROUP_AHEAD:
case REX_GROUP_AHEAD_NOT:
case REX_GROUP_BEHIND:
case REX_GROUP_BEHIND_NOT:
case REX_GROUP_CUT:
case REX_NEG:
case REX_REP:
break;
}
} while (e = e->next);
}
}
static int
{
if (rex)
return 0;
}
#endif
/*
* returning REG_BADPAT or REG_ESPACE is not explicitly
* countenanced by the standard
*/
int
regnexec(const regex_t* p, const char* s, size_t len, size_t nmatch, regmatch_t* match, regflags_t flags)
{
register int n;
register int i;
int j;
int k;
int m;
int advance;
Rex_t* e;
DEBUG_INIT();
DEBUG_TEST(0x0001,(sfprintf(sfstdout, "AHA#%04d 0x%04x regnexec %d 0x%08x `%-.*s'\n", __LINE__, debug_flag, nmatch, flags, len, s)),(0));
return REG_BADPAT;
if (!s)
{
DEBUG_TEST(0x0080,(sfprintf(sfstdout, "AHA#%04d REG_NOMATCH %d %d\n", __LINE__, len, env->min)),(0));
return REG_NOMATCH;
}
advance = 0;
{
{
k = REG_ESPACE;
goto done;
}
for (i = 0; i <= n; i++)
if (flags & REG_ADVANCE)
advance = 1;
}
k = REG_NOMATCH;
{
{
DEBUG_TEST(0x0080,(sfprintf(sfstdout, "AHA#%04d REG_NOMATCH %d %d\n", __LINE__, len, e->re.bm.right)),(0));
goto done;
}
{
register unsigned char* buf = (unsigned char*)s;
Bm_mask_t m;
size_t x;
DEBUG_TEST(0x0080,(sfprintf(sfstdout, "AHA#%04d REX_BM len=%d right=%d left=%d size=%d %d %d\n", __LINE__, len, e->re.bm.right, e->re.bm.left, e->re.bm.size, index, mid)),(0));
for (;;)
{
{
goto done;
}
do
{
if (!n--)
{
goto possible;
if (advance)
{
s += i;
goto possible;
}
x = index;
index = 0;
else
while (index <= x)
{
{
goto hit;
}
index++;
}
break;
}
goto done;
}
}
e = e->next;
}
while ((i = parse(env, e, &env->done, (unsigned char*)s)) == NONE || advance && !env->best[0].rm_eo && !(advance = 0))
{
if (j)
goto done;
i = MBSIZE(s);
s += i;
goto done;
}
goto done;
hit:
goto done;
if (i == CUT)
{
goto done;
}
{
for (i = j = m = 0; j < nmatch; i++)
if (!i || !k || (i & 1))
{
if (i > n)
else
j++;
}
if (k)
{
m--;
}
}
k = 0;
done:
if (k > REG_NOMATCH)
return k;
}
void
{
{
#if _REG_subcomp
{
regsubfree(p);
p->re_sub = 0;
}
#endif
p->env = 0;
{
}
}
}