|
|
@@ -48,6 +48,15 @@ typedef struct { |
|
|
|
int to; |
|
|
|
} offshoot_t; |
|
|
|
|
|
|
|
typedef struct { |
|
|
|
bool * do_catch; |
|
|
|
bool * is_negative; |
|
|
|
int * state; |
|
|
|
int * width; |
|
|
|
char * whitelist; |
|
|
|
regex_t * regex; |
|
|
|
} compiler_state; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------- |
|
|
@@ -317,19 +326,24 @@ static bool catch_(const regex_t * const regex, |
|
|
|
|
|
|
|
#define HALT_AND_CATCH_FIRE -1 |
|
|
|
|
|
|
|
#define HOOK_ALL(from, str, to) do { \ |
|
|
|
int hook_to = (is_negative) ? -1 : state + to; \ |
|
|
|
for (char * s = str; *s != '\0'; s++) { \ |
|
|
|
vector_push(®ex->delta_table, \ |
|
|
|
&(delta_t){state + from, *s, hook_to, width} \ |
|
|
|
); \ |
|
|
|
} \ |
|
|
|
if (do_catch || is_negative) { \ |
|
|
|
vector_push(®ex->catch_table, \ |
|
|
|
&(offshoot_t){state + from, hook_to} \ |
|
|
|
); \ |
|
|
|
} \ |
|
|
|
} while (0) |
|
|
|
void HOOK_ALL( int from, |
|
|
|
const char * const str, |
|
|
|
int to, |
|
|
|
compiler_state * cs) { |
|
|
|
|
|
|
|
int hook_to = (*cs->is_negative) ? HALT_AND_CATCH_FIRE : *cs->state + to; |
|
|
|
|
|
|
|
for (const char * s = str; *s != '\0'; s++) { |
|
|
|
vector_push(&cs->regex->delta_table, |
|
|
|
&(delta_t){*cs->state + from, *s, hook_to, *cs->width} |
|
|
|
); |
|
|
|
} |
|
|
|
if (cs->do_catch || cs->is_negative) { |
|
|
|
vector_push(&cs->regex->catch_table, |
|
|
|
&(offshoot_t){*cs->state + from, hook_to} |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
#define EAT(n) do { \ |
|
|
|
s += n; \ |
|
|
@@ -343,10 +357,20 @@ regex_t * regex_compile(const char * const pattern) { |
|
|
|
|
|
|
|
int state = 0; |
|
|
|
|
|
|
|
char whitelist[64]; |
|
|
|
bool do_catch; |
|
|
|
bool is_negative; |
|
|
|
int width; |
|
|
|
char whitelist[64]; |
|
|
|
|
|
|
|
compiler_state cs = { |
|
|
|
.do_catch = &do_catch, |
|
|
|
.is_negative = &is_negative, |
|
|
|
.state = &state, |
|
|
|
.width = &width, |
|
|
|
.whitelist = whitelist, |
|
|
|
.regex = regex, |
|
|
|
}; |
|
|
|
|
|
|
|
for (const char * s = pattern; *s != '\00';) { |
|
|
|
// Get token |
|
|
|
assert(!is_quantifier(*pattern) && "Pattern starts with quantifier."); |
|
|
@@ -385,21 +409,21 @@ regex_t * regex_compile(const char * const pattern) { |
|
|
|
switch (*s) { |
|
|
|
case '=': |
|
|
|
case '?': { |
|
|
|
HOOK_ALL(0, whitelist, +1); |
|
|
|
HOOK_ALL(0, whitelist, +1, &cs); |
|
|
|
EAT(1); |
|
|
|
} break; |
|
|
|
case '*': { |
|
|
|
HOOK_ALL(0, whitelist, 0); |
|
|
|
HOOK_ALL(0, whitelist, 0, &cs); |
|
|
|
EAT(1); |
|
|
|
} break; |
|
|
|
case '+': { |
|
|
|
HOOK_ALL(0, whitelist, +1); |
|
|
|
HOOK_ALL(0, whitelist, +1, &cs); |
|
|
|
state += 1; |
|
|
|
HOOK_ALL(0, whitelist, 0); |
|
|
|
HOOK_ALL(0, whitelist, 0, &cs); |
|
|
|
EAT(1); |
|
|
|
} break; |
|
|
|
default: { // Literal |
|
|
|
HOOK_ALL(0, whitelist, +1); |
|
|
|
HOOK_ALL(0, whitelist, +1, &cs); |
|
|
|
state += 1; |
|
|
|
} break; |
|
|
|
} |
|
|
|