Index: fusl/src/regex/regexec.c |
diff --git a/fusl/src/regex/regexec.c b/fusl/src/regex/regexec.c |
index 16c5d0ac5c7b5ae6f4a7aaa9313d474682ef6a85..db6b36ae00105a85182aa0d32525612fbdd5bf9e 100644 |
--- a/fusl/src/regex/regexec.c |
+++ b/fusl/src/regex/regexec.c |
@@ -41,99 +41,96 @@ |
#include <assert.h> |
-static void |
-tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags, |
- const tre_tnfa_t *tnfa, int *tags, int match_eo); |
+static void tre_fill_pmatch(size_t nmatch, |
+ regmatch_t pmatch[], |
+ int cflags, |
+ const tre_tnfa_t* tnfa, |
+ int* tags, |
+ int match_eo); |
/*********************************************************************** |
from tre-match-utils.h |
***********************************************************************/ |
-#define GET_NEXT_WCHAR() do { \ |
- prev_c = next_c; pos += pos_add_next; \ |
- if ((pos_add_next = mbtowc(&next_c, str_byte, MB_LEN_MAX)) <= 0) { \ |
- if (pos_add_next < 0) { ret = REG_NOMATCH; goto error_exit; } \ |
- else pos_add_next++; \ |
- } \ |
- str_byte += pos_add_next; \ |
+#define GET_NEXT_WCHAR() \ |
+ do { \ |
+ prev_c = next_c; \ |
+ pos += pos_add_next; \ |
+ if ((pos_add_next = mbtowc(&next_c, str_byte, MB_LEN_MAX)) <= 0) { \ |
+ if (pos_add_next < 0) { \ |
+ ret = REG_NOMATCH; \ |
+ goto error_exit; \ |
+ } else \ |
+ pos_add_next++; \ |
+ } \ |
+ str_byte += pos_add_next; \ |
} while (0) |
-#define IS_WORD_CHAR(c) ((c) == L'_' || tre_isalnum(c)) |
- |
-#define CHECK_ASSERTIONS(assertions) \ |
- (((assertions & ASSERT_AT_BOL) \ |
- && (pos > 0 || reg_notbol) \ |
- && (prev_c != L'\n' || !reg_newline)) \ |
- || ((assertions & ASSERT_AT_EOL) \ |
- && (next_c != L'\0' || reg_noteol) \ |
- && (next_c != L'\n' || !reg_newline)) \ |
- || ((assertions & ASSERT_AT_BOW) \ |
- && (IS_WORD_CHAR(prev_c) || !IS_WORD_CHAR(next_c))) \ |
- || ((assertions & ASSERT_AT_EOW) \ |
- && (!IS_WORD_CHAR(prev_c) || IS_WORD_CHAR(next_c))) \ |
- || ((assertions & ASSERT_AT_WB) \ |
- && (pos != 0 && next_c != L'\0' \ |
- && IS_WORD_CHAR(prev_c) == IS_WORD_CHAR(next_c))) \ |
- || ((assertions & ASSERT_AT_WB_NEG) \ |
- && (pos == 0 || next_c == L'\0' \ |
- || IS_WORD_CHAR(prev_c) != IS_WORD_CHAR(next_c)))) |
- |
-#define CHECK_CHAR_CLASSES(trans_i, tnfa, eflags) \ |
- (((trans_i->assertions & ASSERT_CHAR_CLASS) \ |
- && !(tnfa->cflags & REG_ICASE) \ |
- && !tre_isctype((tre_cint_t)prev_c, trans_i->u.class)) \ |
- || ((trans_i->assertions & ASSERT_CHAR_CLASS) \ |
- && (tnfa->cflags & REG_ICASE) \ |
- && !tre_isctype(tre_tolower((tre_cint_t)prev_c),trans_i->u.class) \ |
- && !tre_isctype(tre_toupper((tre_cint_t)prev_c),trans_i->u.class)) \ |
- || ((trans_i->assertions & ASSERT_CHAR_CLASS_NEG) \ |
- && tre_neg_char_classes_match(trans_i->neg_classes,(tre_cint_t)prev_c,\ |
- tnfa->cflags & REG_ICASE))) |
- |
- |
- |
+#define IS_WORD_CHAR(c) ((c) == L'_' || tre_isalnum(c)) |
+ |
+#define CHECK_ASSERTIONS(assertions) \ |
+ (((assertions & ASSERT_AT_BOL) && (pos > 0 || reg_notbol) && \ |
+ (prev_c != L'\n' || !reg_newline)) || \ |
+ ((assertions & ASSERT_AT_EOL) && (next_c != L'\0' || reg_noteol) && \ |
+ (next_c != L'\n' || !reg_newline)) || \ |
+ ((assertions & ASSERT_AT_BOW) && \ |
+ (IS_WORD_CHAR(prev_c) || !IS_WORD_CHAR(next_c))) || \ |
+ ((assertions & ASSERT_AT_EOW) && \ |
+ (!IS_WORD_CHAR(prev_c) || IS_WORD_CHAR(next_c))) || \ |
+ ((assertions & ASSERT_AT_WB) && \ |
+ (pos != 0 && next_c != L'\0' && \ |
+ IS_WORD_CHAR(prev_c) == IS_WORD_CHAR(next_c))) || \ |
+ ((assertions & ASSERT_AT_WB_NEG) && \ |
+ (pos == 0 || next_c == L'\0' || \ |
+ IS_WORD_CHAR(prev_c) != IS_WORD_CHAR(next_c)))) |
+ |
+#define CHECK_CHAR_CLASSES(trans_i, tnfa, eflags) \ |
+ (((trans_i->assertions & ASSERT_CHAR_CLASS) && \ |
+ !(tnfa->cflags & REG_ICASE) && \ |
+ !tre_isctype((tre_cint_t)prev_c, trans_i->u.class)) || \ |
+ ((trans_i->assertions & ASSERT_CHAR_CLASS) && (tnfa->cflags & REG_ICASE) && \ |
+ !tre_isctype(tre_tolower((tre_cint_t)prev_c), trans_i->u.class) && \ |
+ !tre_isctype(tre_toupper((tre_cint_t)prev_c), trans_i->u.class)) || \ |
+ ((trans_i->assertions & ASSERT_CHAR_CLASS_NEG) && \ |
+ tre_neg_char_classes_match(trans_i->neg_classes, (tre_cint_t)prev_c, \ |
+ tnfa->cflags & REG_ICASE))) |
/* Returns 1 if `t1' wins `t2', 0 otherwise. */ |
-static int |
-tre_tag_order(int num_tags, tre_tag_direction_t *tag_directions, |
- int *t1, int *t2) |
-{ |
+static int tre_tag_order(int num_tags, |
+ tre_tag_direction_t* tag_directions, |
+ int* t1, |
+ int* t2) { |
int i; |
- for (i = 0; i < num_tags; i++) |
- { |
- if (tag_directions[i] == TRE_TAG_MINIMIZE) |
- { |
- if (t1[i] < t2[i]) |
- return 1; |
- if (t1[i] > t2[i]) |
- return 0; |
- } |
- else |
- { |
- if (t1[i] > t2[i]) |
- return 1; |
- if (t1[i] < t2[i]) |
- return 0; |
- } |
+ for (i = 0; i < num_tags; i++) { |
+ if (tag_directions[i] == TRE_TAG_MINIMIZE) { |
+ if (t1[i] < t2[i]) |
+ return 1; |
+ if (t1[i] > t2[i]) |
+ return 0; |
+ } else { |
+ if (t1[i] > t2[i]) |
+ return 1; |
+ if (t1[i] < t2[i]) |
+ return 0; |
} |
+ } |
/* assert(0);*/ |
return 0; |
} |
-static int |
-tre_neg_char_classes_match(tre_ctype_t *classes, tre_cint_t wc, int icase) |
-{ |
+static int tre_neg_char_classes_match(tre_ctype_t* classes, |
+ tre_cint_t wc, |
+ int icase) { |
while (*classes != (tre_ctype_t)0) |
- if ((!icase && tre_isctype(wc, *classes)) |
- || (icase && (tre_isctype(tre_toupper(wc), *classes) |
- || tre_isctype(tre_tolower(wc), *classes)))) |
+ if ((!icase && tre_isctype(wc, *classes)) || |
+ (icase && (tre_isctype(tre_toupper(wc), *classes) || |
+ tre_isctype(tre_tolower(wc), *classes)))) |
return 1; /* Match. */ |
else |
classes++; |
return 0; /* No match. */ |
} |
- |
/*********************************************************************** |
from tre-match-parallel.c |
***********************************************************************/ |
@@ -155,24 +152,23 @@ tre_neg_char_classes_match(tre_ctype_t *classes, tre_cint_t wc, int icase) |
*/ |
typedef struct { |
- tre_tnfa_transition_t *state; |
- int *tags; |
+ tre_tnfa_transition_t* state; |
+ int* tags; |
} tre_tnfa_reach_t; |
typedef struct { |
int pos; |
- int **tags; |
+ int** tags; |
} tre_reach_pos_t; |
- |
-static reg_errcode_t |
-tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, |
- int *match_tags, int eflags, |
- int *match_end_ofs) |
-{ |
+static reg_errcode_t tre_tnfa_run_parallel(const tre_tnfa_t* tnfa, |
+ const void* string, |
+ int* match_tags, |
+ int eflags, |
+ int* match_end_ofs) { |
/* State variables required by GET_NEXT_WCHAR. */ |
tre_char_t prev_c = 0, next_c = 0; |
- const char *str_byte = string; |
+ const char* str_byte = string; |
int pos = -1; |
int pos_add_next = 1; |
#ifdef TRE_MBSTATE |
@@ -183,17 +179,17 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, |
int reg_newline = tnfa->cflags & REG_NEWLINE; |
reg_errcode_t ret; |
- char *buf; |
- tre_tnfa_transition_t *trans_i; |
+ char* buf; |
+ tre_tnfa_transition_t* trans_i; |
tre_tnfa_reach_t *reach, *reach_next, *reach_i, *reach_next_i; |
- tre_reach_pos_t *reach_pos; |
- int *tag_i; |
+ tre_reach_pos_t* reach_pos; |
+ int* tag_i; |
int num_tags, i; |
- int match_eo = -1; /* end offset of match (-1 if no match found yet) */ |
+ int match_eo = -1; /* end offset of match (-1 if no match found yet) */ |
int new_match = 0; |
- int *tmp_tags = NULL; |
- int *tmp_iptr; |
+ int* tmp_tags = NULL; |
+ int* tmp_iptr; |
#ifdef TRE_MBSTATE |
memset(&mbstate, '\0', sizeof(mbstate)); |
@@ -210,15 +206,14 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, |
or with malloc() if alloca is unavailable. */ |
{ |
int tbytes, rbytes, pbytes, xbytes, total_bytes; |
- char *tmp_buf; |
+ char* tmp_buf; |
/* Compute the length of the block we need. */ |
tbytes = sizeof(*tmp_tags) * num_tags; |
rbytes = sizeof(*reach_next) * (tnfa->num_states + 1); |
pbytes = sizeof(*reach_pos) * tnfa->num_states; |
xbytes = sizeof(int) * num_tags; |
- total_bytes = |
- (sizeof(long) - 1) * 4 /* for alignment paddings */ |
- + (rbytes + xbytes * tnfa->num_states) * 2 + tbytes + pbytes; |
+ total_bytes = (sizeof(long) - 1) * 4 /* for alignment paddings */ |
+ + (rbytes + xbytes * tnfa->num_states) * 2 + tbytes + pbytes; |
/* Allocate the memory. */ |
buf = xmalloc((unsigned)total_bytes); |
@@ -227,25 +222,24 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, |
memset(buf, 0, (size_t)total_bytes); |
/* Get the various pointers within tmp_buf (properly aligned). */ |
- tmp_tags = (void *)buf; |
+ tmp_tags = (void*)buf; |
tmp_buf = buf + tbytes; |
tmp_buf += ALIGN(tmp_buf, long); |
- reach_next = (void *)tmp_buf; |
+ reach_next = (void*)tmp_buf; |
tmp_buf += rbytes; |
tmp_buf += ALIGN(tmp_buf, long); |
- reach = (void *)tmp_buf; |
+ reach = (void*)tmp_buf; |
tmp_buf += rbytes; |
tmp_buf += ALIGN(tmp_buf, long); |
- reach_pos = (void *)tmp_buf; |
+ reach_pos = (void*)tmp_buf; |
tmp_buf += pbytes; |
tmp_buf += ALIGN(tmp_buf, long); |
- for (i = 0; i < tnfa->num_states; i++) |
- { |
- reach[i].tags = (void *)tmp_buf; |
- tmp_buf += xbytes; |
- reach_next[i].tags = (void *)tmp_buf; |
- tmp_buf += xbytes; |
- } |
+ for (i = 0; i < tnfa->num_states; i++) { |
+ reach[i].tags = (void*)tmp_buf; |
+ tmp_buf += xbytes; |
+ reach_next[i].tags = (void*)tmp_buf; |
+ tmp_buf += xbytes; |
+ } |
} |
for (i = 0; i < tnfa->num_states; i++) |
@@ -255,190 +249,161 @@ tre_tnfa_run_parallel(const tre_tnfa_t *tnfa, const void *string, |
pos = 0; |
reach_next_i = reach_next; |
- while (1) |
- { |
- /* If no match found yet, add the initial states to `reach_next'. */ |
- if (match_eo < 0) |
- { |
- trans_i = tnfa->initial; |
- while (trans_i->state != NULL) |
- { |
- if (reach_pos[trans_i->state_id].pos < pos) |
- { |
- if (trans_i->assertions |
- && CHECK_ASSERTIONS(trans_i->assertions)) |
- { |
- trans_i++; |
- continue; |
- } |
- |
- reach_next_i->state = trans_i->state; |
- for (i = 0; i < num_tags; i++) |
- reach_next_i->tags[i] = -1; |
- tag_i = trans_i->tags; |
- if (tag_i) |
- while (*tag_i >= 0) |
- { |
- if (*tag_i < num_tags) |
- reach_next_i->tags[*tag_i] = pos; |
- tag_i++; |
- } |
- if (reach_next_i->state == tnfa->final) |
- { |
- match_eo = pos; |
- new_match = 1; |
- for (i = 0; i < num_tags; i++) |
- match_tags[i] = reach_next_i->tags[i]; |
- } |
- reach_pos[trans_i->state_id].pos = pos; |
- reach_pos[trans_i->state_id].tags = &reach_next_i->tags; |
- reach_next_i++; |
- } |
- trans_i++; |
- } |
- reach_next_i->state = NULL; |
- } |
- else |
- { |
- if (num_tags == 0 || reach_next_i == reach_next) |
- /* We have found a match. */ |
- break; |
- } |
+ while (1) { |
+ /* If no match found yet, add the initial states to `reach_next'. */ |
+ if (match_eo < 0) { |
+ trans_i = tnfa->initial; |
+ while (trans_i->state != NULL) { |
+ if (reach_pos[trans_i->state_id].pos < pos) { |
+ if (trans_i->assertions && CHECK_ASSERTIONS(trans_i->assertions)) { |
+ trans_i++; |
+ continue; |
+ } |
+ |
+ reach_next_i->state = trans_i->state; |
+ for (i = 0; i < num_tags; i++) |
+ reach_next_i->tags[i] = -1; |
+ tag_i = trans_i->tags; |
+ if (tag_i) |
+ while (*tag_i >= 0) { |
+ if (*tag_i < num_tags) |
+ reach_next_i->tags[*tag_i] = pos; |
+ tag_i++; |
+ } |
+ if (reach_next_i->state == tnfa->final) { |
+ match_eo = pos; |
+ new_match = 1; |
+ for (i = 0; i < num_tags; i++) |
+ match_tags[i] = reach_next_i->tags[i]; |
+ } |
+ reach_pos[trans_i->state_id].pos = pos; |
+ reach_pos[trans_i->state_id].tags = &reach_next_i->tags; |
+ reach_next_i++; |
+ } |
+ trans_i++; |
+ } |
+ reach_next_i->state = NULL; |
+ } else { |
+ if (num_tags == 0 || reach_next_i == reach_next) |
+ /* We have found a match. */ |
+ break; |
+ } |
- /* Check for end of string. */ |
- if (!next_c) break; |
+ /* Check for end of string. */ |
+ if (!next_c) |
+ break; |
- GET_NEXT_WCHAR(); |
+ GET_NEXT_WCHAR(); |
+ |
+ /* Swap `reach' and `reach_next'. */ |
+ reach_i = reach; |
+ reach = reach_next; |
+ reach_next = reach_i; |
+ |
+ /* For each state in `reach', weed out states that don't fulfill the |
+ minimal matching conditions. */ |
+ if (tnfa->num_minimals && new_match) { |
+ new_match = 0; |
+ reach_next_i = reach_next; |
+ for (reach_i = reach; reach_i->state; reach_i++) { |
+ int skip = 0; |
+ for (i = 0; tnfa->minimal_tags[i] >= 0; i += 2) { |
+ int end = tnfa->minimal_tags[i]; |
+ int start = tnfa->minimal_tags[i + 1]; |
+ if (end >= num_tags) { |
+ skip = 1; |
+ break; |
+ } else if (reach_i->tags[start] == match_tags[start] && |
+ reach_i->tags[end] < match_tags[end]) { |
+ skip = 1; |
+ break; |
+ } |
+ } |
+ if (!skip) { |
+ reach_next_i->state = reach_i->state; |
+ tmp_iptr = reach_next_i->tags; |
+ reach_next_i->tags = reach_i->tags; |
+ reach_i->tags = tmp_iptr; |
+ reach_next_i++; |
+ } |
+ } |
+ reach_next_i->state = NULL; |
/* Swap `reach' and `reach_next'. */ |
reach_i = reach; |
reach = reach_next; |
reach_next = reach_i; |
+ } |
- /* For each state in `reach', weed out states that don't fulfill the |
- minimal matching conditions. */ |
- if (tnfa->num_minimals && new_match) |
- { |
- new_match = 0; |
- reach_next_i = reach_next; |
- for (reach_i = reach; reach_i->state; reach_i++) |
- { |
- int skip = 0; |
- for (i = 0; tnfa->minimal_tags[i] >= 0; i += 2) |
- { |
- int end = tnfa->minimal_tags[i]; |
- int start = tnfa->minimal_tags[i + 1]; |
- if (end >= num_tags) |
- { |
- skip = 1; |
- break; |
- } |
- else if (reach_i->tags[start] == match_tags[start] |
- && reach_i->tags[end] < match_tags[end]) |
- { |
- skip = 1; |
- break; |
- } |
- } |
- if (!skip) |
- { |
- reach_next_i->state = reach_i->state; |
- tmp_iptr = reach_next_i->tags; |
- reach_next_i->tags = reach_i->tags; |
- reach_i->tags = tmp_iptr; |
- reach_next_i++; |
- } |
- } |
- reach_next_i->state = NULL; |
- |
- /* Swap `reach' and `reach_next'. */ |
- reach_i = reach; |
- reach = reach_next; |
- reach_next = reach_i; |
- } |
- |
- /* For each state in `reach' see if there is a transition leaving with |
- the current input symbol to a state not yet in `reach_next', and |
- add the destination states to `reach_next'. */ |
- reach_next_i = reach_next; |
- for (reach_i = reach; reach_i->state; reach_i++) |
- { |
- for (trans_i = reach_i->state; trans_i->state; trans_i++) |
- { |
- /* Does this transition match the input symbol? */ |
- if (trans_i->code_min <= (tre_cint_t)prev_c && |
- trans_i->code_max >= (tre_cint_t)prev_c) |
- { |
- if (trans_i->assertions |
- && (CHECK_ASSERTIONS(trans_i->assertions) |
- || CHECK_CHAR_CLASSES(trans_i, tnfa, eflags))) |
- { |
- continue; |
- } |
- |
- /* Compute the tags after this transition. */ |
- for (i = 0; i < num_tags; i++) |
- tmp_tags[i] = reach_i->tags[i]; |
- tag_i = trans_i->tags; |
- if (tag_i != NULL) |
- while (*tag_i >= 0) |
- { |
- if (*tag_i < num_tags) |
- tmp_tags[*tag_i] = pos; |
- tag_i++; |
- } |
- |
- if (reach_pos[trans_i->state_id].pos < pos) |
- { |
- /* Found an unvisited node. */ |
- reach_next_i->state = trans_i->state; |
- tmp_iptr = reach_next_i->tags; |
- reach_next_i->tags = tmp_tags; |
- tmp_tags = tmp_iptr; |
- reach_pos[trans_i->state_id].pos = pos; |
- reach_pos[trans_i->state_id].tags = &reach_next_i->tags; |
- |
- if (reach_next_i->state == tnfa->final |
- && (match_eo == -1 |
- || (num_tags > 0 |
- && reach_next_i->tags[0] <= match_tags[0]))) |
- { |
- match_eo = pos; |
- new_match = 1; |
- for (i = 0; i < num_tags; i++) |
- match_tags[i] = reach_next_i->tags[i]; |
- } |
- reach_next_i++; |
- |
- } |
- else |
- { |
- assert(reach_pos[trans_i->state_id].pos == pos); |
- /* Another path has also reached this state. We choose |
- the winner by examining the tag values for both |
- paths. */ |
- if (tre_tag_order(num_tags, tnfa->tag_directions, |
- tmp_tags, |
- *reach_pos[trans_i->state_id].tags)) |
- { |
- /* The new path wins. */ |
- tmp_iptr = *reach_pos[trans_i->state_id].tags; |
- *reach_pos[trans_i->state_id].tags = tmp_tags; |
- if (trans_i->state == tnfa->final) |
- { |
- match_eo = pos; |
- new_match = 1; |
- for (i = 0; i < num_tags; i++) |
- match_tags[i] = tmp_tags[i]; |
- } |
- tmp_tags = tmp_iptr; |
- } |
- } |
- } |
- } |
- } |
- reach_next_i->state = NULL; |
+ /* For each state in `reach' see if there is a transition leaving with |
+ the current input symbol to a state not yet in `reach_next', and |
+ add the destination states to `reach_next'. */ |
+ reach_next_i = reach_next; |
+ for (reach_i = reach; reach_i->state; reach_i++) { |
+ for (trans_i = reach_i->state; trans_i->state; trans_i++) { |
+ /* Does this transition match the input symbol? */ |
+ if (trans_i->code_min <= (tre_cint_t)prev_c && |
+ trans_i->code_max >= (tre_cint_t)prev_c) { |
+ if (trans_i->assertions && |
+ (CHECK_ASSERTIONS(trans_i->assertions) || |
+ CHECK_CHAR_CLASSES(trans_i, tnfa, eflags))) { |
+ continue; |
+ } |
+ |
+ /* Compute the tags after this transition. */ |
+ for (i = 0; i < num_tags; i++) |
+ tmp_tags[i] = reach_i->tags[i]; |
+ tag_i = trans_i->tags; |
+ if (tag_i != NULL) |
+ while (*tag_i >= 0) { |
+ if (*tag_i < num_tags) |
+ tmp_tags[*tag_i] = pos; |
+ tag_i++; |
+ } |
+ |
+ if (reach_pos[trans_i->state_id].pos < pos) { |
+ /* Found an unvisited node. */ |
+ reach_next_i->state = trans_i->state; |
+ tmp_iptr = reach_next_i->tags; |
+ reach_next_i->tags = tmp_tags; |
+ tmp_tags = tmp_iptr; |
+ reach_pos[trans_i->state_id].pos = pos; |
+ reach_pos[trans_i->state_id].tags = &reach_next_i->tags; |
+ |
+ if (reach_next_i->state == tnfa->final && |
+ (match_eo == -1 || |
+ (num_tags > 0 && reach_next_i->tags[0] <= match_tags[0]))) { |
+ match_eo = pos; |
+ new_match = 1; |
+ for (i = 0; i < num_tags; i++) |
+ match_tags[i] = reach_next_i->tags[i]; |
+ } |
+ reach_next_i++; |
+ |
+ } else { |
+ assert(reach_pos[trans_i->state_id].pos == pos); |
+ /* Another path has also reached this state. We choose |
+ the winner by examining the tag values for both |
+ paths. */ |
+ if (tre_tag_order(num_tags, tnfa->tag_directions, tmp_tags, |
+ *reach_pos[trans_i->state_id].tags)) { |
+ /* The new path wins. */ |
+ tmp_iptr = *reach_pos[trans_i->state_id].tags; |
+ *reach_pos[trans_i->state_id].tags = tmp_tags; |
+ if (trans_i->state == tnfa->final) { |
+ match_eo = pos; |
+ new_match = 1; |
+ for (i = 0; i < num_tags; i++) |
+ match_tags[i] = tmp_tags[i]; |
+ } |
+ tmp_tags = tmp_iptr; |
+ } |
+ } |
+ } |
+ } |
} |
+ reach_next_i->state = NULL; |
+ } |
*match_end_ofs = match_eo; |
ret = match_eo >= 0 ? REG_OK : REG_NOMATCH; |
@@ -447,8 +412,6 @@ error_exit: |
return ret; |
} |
- |
- |
/*********************************************************************** |
from tre-match-backtrack.c |
***********************************************************************/ |
@@ -478,11 +441,11 @@ error_exit: |
typedef struct { |
int pos; |
- const char *str_byte; |
- tre_tnfa_transition_t *state; |
+ const char* str_byte; |
+ tre_tnfa_transition_t* state; |
int state_id; |
int next_c; |
- int *tags; |
+ int* tags; |
#ifdef TRE_MBSTATE |
mbstate_t mbstate; |
#endif /* TRE_MBSTATE */ |
@@ -490,99 +453,91 @@ typedef struct { |
typedef struct tre_backtrack_struct { |
tre_backtrack_item_t item; |
- struct tre_backtrack_struct *prev; |
- struct tre_backtrack_struct *next; |
-} *tre_backtrack_t; |
+ struct tre_backtrack_struct* prev; |
+ struct tre_backtrack_struct* next; |
+} * tre_backtrack_t; |
#ifdef TRE_MBSTATE |
-#define BT_STACK_MBSTATE_IN stack->item.mbstate = (mbstate) |
+#define BT_STACK_MBSTATE_IN stack->item.mbstate = (mbstate) |
#define BT_STACK_MBSTATE_OUT (mbstate) = stack->item.mbstate |
#else /* !TRE_MBSTATE */ |
#define BT_STACK_MBSTATE_IN |
#define BT_STACK_MBSTATE_OUT |
#endif /* !TRE_MBSTATE */ |
-#define tre_bt_mem_new tre_mem_new |
-#define tre_bt_mem_alloc tre_mem_alloc |
-#define tre_bt_mem_destroy tre_mem_destroy |
- |
- |
-#define BT_STACK_PUSH(_pos, _str_byte, _str_wide, _state, _state_id, _next_c, _tags, _mbstate) \ |
- do \ |
- { \ |
- int i; \ |
- if (!stack->next) \ |
- { \ |
- tre_backtrack_t s; \ |
- s = tre_bt_mem_alloc(mem, sizeof(*s)); \ |
- if (!s) \ |
- { \ |
- tre_bt_mem_destroy(mem); \ |
- if (tags) \ |
- xfree(tags); \ |
- if (pmatch) \ |
- xfree(pmatch); \ |
- if (states_seen) \ |
- xfree(states_seen); \ |
- return REG_ESPACE; \ |
- } \ |
- s->prev = stack; \ |
- s->next = NULL; \ |
- s->item.tags = tre_bt_mem_alloc(mem, \ |
- sizeof(*tags) * tnfa->num_tags); \ |
- if (!s->item.tags) \ |
- { \ |
- tre_bt_mem_destroy(mem); \ |
- if (tags) \ |
- xfree(tags); \ |
- if (pmatch) \ |
- xfree(pmatch); \ |
- if (states_seen) \ |
- xfree(states_seen); \ |
- return REG_ESPACE; \ |
- } \ |
- stack->next = s; \ |
- stack = s; \ |
- } \ |
- else \ |
- stack = stack->next; \ |
- stack->item.pos = (_pos); \ |
- stack->item.str_byte = (_str_byte); \ |
- stack->item.state = (_state); \ |
- stack->item.state_id = (_state_id); \ |
- stack->item.next_c = (_next_c); \ |
- for (i = 0; i < tnfa->num_tags; i++) \ |
- stack->item.tags[i] = (_tags)[i]; \ |
- BT_STACK_MBSTATE_IN; \ |
- } \ |
- while (0) |
- |
-#define BT_STACK_POP() \ |
- do \ |
- { \ |
- int i; \ |
- assert(stack->prev); \ |
- pos = stack->item.pos; \ |
- str_byte = stack->item.str_byte; \ |
- state = stack->item.state; \ |
- next_c = stack->item.next_c; \ |
- for (i = 0; i < tnfa->num_tags; i++) \ |
- tags[i] = stack->item.tags[i]; \ |
- BT_STACK_MBSTATE_OUT; \ |
- stack = stack->prev; \ |
- } \ |
- while (0) |
+#define tre_bt_mem_new tre_mem_new |
+#define tre_bt_mem_alloc tre_mem_alloc |
+#define tre_bt_mem_destroy tre_mem_destroy |
+ |
+#define BT_STACK_PUSH(_pos, _str_byte, _str_wide, _state, _state_id, _next_c, \ |
+ _tags, _mbstate) \ |
+ do { \ |
+ int i; \ |
+ if (!stack->next) { \ |
+ tre_backtrack_t s; \ |
+ s = tre_bt_mem_alloc(mem, sizeof(*s)); \ |
+ if (!s) { \ |
+ tre_bt_mem_destroy(mem); \ |
+ if (tags) \ |
+ xfree(tags); \ |
+ if (pmatch) \ |
+ xfree(pmatch); \ |
+ if (states_seen) \ |
+ xfree(states_seen); \ |
+ return REG_ESPACE; \ |
+ } \ |
+ s->prev = stack; \ |
+ s->next = NULL; \ |
+ s->item.tags = tre_bt_mem_alloc(mem, sizeof(*tags) * tnfa->num_tags); \ |
+ if (!s->item.tags) { \ |
+ tre_bt_mem_destroy(mem); \ |
+ if (tags) \ |
+ xfree(tags); \ |
+ if (pmatch) \ |
+ xfree(pmatch); \ |
+ if (states_seen) \ |
+ xfree(states_seen); \ |
+ return REG_ESPACE; \ |
+ } \ |
+ stack->next = s; \ |
+ stack = s; \ |
+ } else \ |
+ stack = stack->next; \ |
+ stack->item.pos = (_pos); \ |
+ stack->item.str_byte = (_str_byte); \ |
+ stack->item.state = (_state); \ |
+ stack->item.state_id = (_state_id); \ |
+ stack->item.next_c = (_next_c); \ |
+ for (i = 0; i < tnfa->num_tags; i++) \ |
+ stack->item.tags[i] = (_tags)[i]; \ |
+ BT_STACK_MBSTATE_IN; \ |
+ } while (0) |
+ |
+#define BT_STACK_POP() \ |
+ do { \ |
+ int i; \ |
+ assert(stack->prev); \ |
+ pos = stack->item.pos; \ |
+ str_byte = stack->item.str_byte; \ |
+ state = stack->item.state; \ |
+ next_c = stack->item.next_c; \ |
+ for (i = 0; i < tnfa->num_tags; i++) \ |
+ tags[i] = stack->item.tags[i]; \ |
+ BT_STACK_MBSTATE_OUT; \ |
+ stack = stack->prev; \ |
+ } while (0) |
#undef MIN |
#define MIN(a, b) ((a) <= (b) ? (a) : (b)) |
-static reg_errcode_t |
-tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, |
- int *match_tags, int eflags, int *match_end_ofs) |
-{ |
+static reg_errcode_t tre_tnfa_run_backtrack(const tre_tnfa_t* tnfa, |
+ const void* string, |
+ int* match_tags, |
+ int eflags, |
+ int* match_end_ofs) { |
/* State variables required by GET_NEXT_WCHAR. */ |
tre_char_t prev_c = 0, next_c = 0; |
- const char *str_byte = string; |
+ const char* str_byte = string; |
int pos = 0; |
int pos_add_next = 1; |
#ifdef TRE_MBSTATE |
@@ -596,7 +551,7 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, |
variables to return to the position where the current search |
started from. */ |
int next_c_start; |
- const char *str_byte_start; |
+ const char* str_byte_start; |
int pos_start = -1; |
#ifdef TRE_MBSTATE |
mbstate_t mbstate_start; |
@@ -607,8 +562,8 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, |
/* Tag arrays. */ |
int *next_tags, *tags = NULL; |
/* Current TNFA state. */ |
- tre_tnfa_transition_t *state; |
- int *states_seen = NULL; |
+ tre_tnfa_transition_t* state; |
+ int* states_seen = NULL; |
/* Memory allocator to for allocating the backtracking stack. */ |
tre_mem_t mem = tre_bt_mem_new(); |
@@ -616,8 +571,8 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, |
/* The backtracking stack. */ |
tre_backtrack_t stack; |
- tre_tnfa_transition_t *trans_i; |
- regmatch_t *pmatch = NULL; |
+ tre_tnfa_transition_t* trans_i; |
+ regmatch_t* pmatch = NULL; |
int ret; |
#ifdef TRE_MBSTATE |
@@ -627,54 +582,45 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, |
if (!mem) |
return REG_ESPACE; |
stack = tre_bt_mem_alloc(mem, sizeof(*stack)); |
- if (!stack) |
- { |
- ret = REG_ESPACE; |
- goto error_exit; |
- } |
+ if (!stack) { |
+ ret = REG_ESPACE; |
+ goto error_exit; |
+ } |
stack->prev = NULL; |
stack->next = NULL; |
- if (tnfa->num_tags) |
- { |
- tags = xmalloc(sizeof(*tags) * tnfa->num_tags); |
- if (!tags) |
- { |
- ret = REG_ESPACE; |
- goto error_exit; |
- } |
+ if (tnfa->num_tags) { |
+ tags = xmalloc(sizeof(*tags) * tnfa->num_tags); |
+ if (!tags) { |
+ ret = REG_ESPACE; |
+ goto error_exit; |
} |
- if (tnfa->num_submatches) |
- { |
- pmatch = xmalloc(sizeof(*pmatch) * tnfa->num_submatches); |
- if (!pmatch) |
- { |
- ret = REG_ESPACE; |
- goto error_exit; |
- } |
+ } |
+ if (tnfa->num_submatches) { |
+ pmatch = xmalloc(sizeof(*pmatch) * tnfa->num_submatches); |
+ if (!pmatch) { |
+ ret = REG_ESPACE; |
+ goto error_exit; |
} |
- if (tnfa->num_states) |
- { |
- states_seen = xmalloc(sizeof(*states_seen) * tnfa->num_states); |
- if (!states_seen) |
- { |
- ret = REG_ESPACE; |
- goto error_exit; |
- } |
+ } |
+ if (tnfa->num_states) { |
+ states_seen = xmalloc(sizeof(*states_seen) * tnfa->num_states); |
+ if (!states_seen) { |
+ ret = REG_ESPACE; |
+ goto error_exit; |
} |
+ } |
- retry: |
- { |
- int i; |
- for (i = 0; i < tnfa->num_tags; i++) |
- { |
- tags[i] = -1; |
- if (match_tags) |
- match_tags[i] = -1; |
- } |
- for (i = 0; i < tnfa->num_states; i++) |
- states_seen[i] = 0; |
+retry : { |
+ int i; |
+ for (i = 0; i < tnfa->num_tags; i++) { |
+ tags[i] = -1; |
+ if (match_tags) |
+ match_tags[i] = -1; |
} |
+ for (i = 0; i < tnfa->num_states; i++) |
+ states_seen[i] = 0; |
+} |
state = NULL; |
pos = pos_start; |
@@ -688,210 +634,175 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, |
/* Handle initial states. */ |
next_tags = NULL; |
- for (trans_i = tnfa->initial; trans_i->state; trans_i++) |
- { |
- if (trans_i->assertions && CHECK_ASSERTIONS(trans_i->assertions)) |
- { |
- continue; |
- } |
- if (state == NULL) |
- { |
- /* Start from this state. */ |
- state = trans_i->state; |
- next_tags = trans_i->tags; |
- } |
- else |
- { |
- /* Backtrack to this state. */ |
- BT_STACK_PUSH(pos, str_byte, 0, trans_i->state, |
- trans_i->state_id, next_c, tags, mbstate); |
- { |
- int *tmp = trans_i->tags; |
- if (tmp) |
- while (*tmp >= 0) |
- stack->item.tags[*tmp++] = pos; |
- } |
- } |
+ for (trans_i = tnfa->initial; trans_i->state; trans_i++) { |
+ if (trans_i->assertions && CHECK_ASSERTIONS(trans_i->assertions)) { |
+ continue; |
+ } |
+ if (state == NULL) { |
+ /* Start from this state. */ |
+ state = trans_i->state; |
+ next_tags = trans_i->tags; |
+ } else { |
+ /* Backtrack to this state. */ |
+ BT_STACK_PUSH(pos, str_byte, 0, trans_i->state, trans_i->state_id, next_c, |
+ tags, mbstate); |
+ { |
+ int* tmp = trans_i->tags; |
+ if (tmp) |
+ while (*tmp >= 0) |
+ stack->item.tags[*tmp++] = pos; |
+ } |
} |
+ } |
if (next_tags) |
for (; *next_tags >= 0; next_tags++) |
tags[*next_tags] = pos; |
- |
if (state == NULL) |
goto backtrack; |
- while (1) |
- { |
- tre_tnfa_transition_t *next_state; |
- int empty_br_match; |
- |
- if (state == tnfa->final) |
- { |
- if (match_eo < pos |
- || (match_eo == pos |
- && match_tags |
- && tre_tag_order(tnfa->num_tags, tnfa->tag_directions, |
- tags, match_tags))) |
- { |
- int i; |
- /* This match wins the previous match. */ |
- match_eo = pos; |
- if (match_tags) |
- for (i = 0; i < tnfa->num_tags; i++) |
- match_tags[i] = tags[i]; |
- } |
- /* Our TNFAs never have transitions leaving from the final state, |
- so we jump right to backtracking. */ |
- goto backtrack; |
- } |
- |
- /* Go to the next character in the input string. */ |
- empty_br_match = 0; |
- trans_i = state; |
- if (trans_i->state && trans_i->assertions & ASSERT_BACKREF) |
- { |
- /* This is a back reference state. All transitions leaving from |
- this state have the same back reference "assertion". Instead |
- of reading the next character, we match the back reference. */ |
- int so, eo, bt = trans_i->u.backref; |
- int bt_len; |
- int result; |
- |
- /* Get the substring we need to match against. Remember to |
- turn off REG_NOSUB temporarily. */ |
- tre_fill_pmatch(bt + 1, pmatch, tnfa->cflags & ~REG_NOSUB, |
- tnfa, tags, pos); |
- so = pmatch[bt].rm_so; |
- eo = pmatch[bt].rm_eo; |
- bt_len = eo - so; |
- |
- result = strncmp((const char*)string + so, str_byte - 1, |
- (size_t)bt_len); |
- |
- if (result == 0) |
- { |
- /* Back reference matched. Check for infinite loop. */ |
- if (bt_len == 0) |
- empty_br_match = 1; |
- if (empty_br_match && states_seen[trans_i->state_id]) |
- { |
- goto backtrack; |
- } |
- |
- states_seen[trans_i->state_id] = empty_br_match; |
- |
- /* Advance in input string and resync `prev_c', `next_c' |
- and pos. */ |
- str_byte += bt_len - 1; |
- pos += bt_len - 1; |
- GET_NEXT_WCHAR(); |
- } |
- else |
- { |
- goto backtrack; |
- } |
- } |
- else |
- { |
- /* Check for end of string. */ |
- if (next_c == L'\0') |
- goto backtrack; |
- |
- /* Read the next character. */ |
- GET_NEXT_WCHAR(); |
- } |
- |
- next_state = NULL; |
- for (trans_i = state; trans_i->state; trans_i++) |
- { |
- if (trans_i->code_min <= (tre_cint_t)prev_c |
- && trans_i->code_max >= (tre_cint_t)prev_c) |
- { |
- if (trans_i->assertions |
- && (CHECK_ASSERTIONS(trans_i->assertions) |
- || CHECK_CHAR_CLASSES(trans_i, tnfa, eflags))) |
- { |
- continue; |
- } |
- |
- if (next_state == NULL) |
- { |
- /* First matching transition. */ |
- next_state = trans_i->state; |
- next_tags = trans_i->tags; |
- } |
- else |
- { |
- /* Second matching transition. We may need to backtrack here |
- to take this transition instead of the first one, so we |
- push this transition in the backtracking stack so we can |
- jump back here if needed. */ |
- BT_STACK_PUSH(pos, str_byte, 0, trans_i->state, |
- trans_i->state_id, next_c, tags, mbstate); |
- { |
- int *tmp; |
- for (tmp = trans_i->tags; tmp && *tmp >= 0; tmp++) |
- stack->item.tags[*tmp] = pos; |
- } |
-#if 0 /* XXX - it's important not to look at all transitions here to keep |
- the stack small! */ |
+ while (1) { |
+ tre_tnfa_transition_t* next_state; |
+ int empty_br_match; |
+ |
+ if (state == tnfa->final) { |
+ if (match_eo < pos || (match_eo == pos && match_tags && |
+ tre_tag_order(tnfa->num_tags, tnfa->tag_directions, |
+ tags, match_tags))) { |
+ int i; |
+ /* This match wins the previous match. */ |
+ match_eo = pos; |
+ if (match_tags) |
+ for (i = 0; i < tnfa->num_tags; i++) |
+ match_tags[i] = tags[i]; |
+ } |
+ /* Our TNFAs never have transitions leaving from the final state, |
+ so we jump right to backtracking. */ |
+ goto backtrack; |
+ } |
+ |
+ /* Go to the next character in the input string. */ |
+ empty_br_match = 0; |
+ trans_i = state; |
+ if (trans_i->state && trans_i->assertions & ASSERT_BACKREF) { |
+ /* This is a back reference state. All transitions leaving from |
+ this state have the same back reference "assertion". Instead |
+ of reading the next character, we match the back reference. */ |
+ int so, eo, bt = trans_i->u.backref; |
+ int bt_len; |
+ int result; |
+ |
+ /* Get the substring we need to match against. Remember to |
+ turn off REG_NOSUB temporarily. */ |
+ tre_fill_pmatch(bt + 1, pmatch, tnfa->cflags & ~REG_NOSUB, tnfa, tags, |
+ pos); |
+ so = pmatch[bt].rm_so; |
+ eo = pmatch[bt].rm_eo; |
+ bt_len = eo - so; |
+ |
+ result = strncmp((const char*)string + so, str_byte - 1, (size_t)bt_len); |
+ |
+ if (result == 0) { |
+ /* Back reference matched. Check for infinite loop. */ |
+ if (bt_len == 0) |
+ empty_br_match = 1; |
+ if (empty_br_match && states_seen[trans_i->state_id]) { |
+ goto backtrack; |
+ } |
+ |
+ states_seen[trans_i->state_id] = empty_br_match; |
+ |
+ /* Advance in input string and resync `prev_c', `next_c' |
+ and pos. */ |
+ str_byte += bt_len - 1; |
+ pos += bt_len - 1; |
+ GET_NEXT_WCHAR(); |
+ } else { |
+ goto backtrack; |
+ } |
+ } else { |
+ /* Check for end of string. */ |
+ if (next_c == L'\0') |
+ goto backtrack; |
+ |
+ /* Read the next character. */ |
+ GET_NEXT_WCHAR(); |
+ } |
+ |
+ next_state = NULL; |
+ for (trans_i = state; trans_i->state; trans_i++) { |
+ if (trans_i->code_min <= (tre_cint_t)prev_c && |
+ trans_i->code_max >= (tre_cint_t)prev_c) { |
+ if (trans_i->assertions && |
+ (CHECK_ASSERTIONS(trans_i->assertions) || |
+ CHECK_CHAR_CLASSES(trans_i, tnfa, eflags))) { |
+ continue; |
+ } |
+ |
+ if (next_state == NULL) { |
+ /* First matching transition. */ |
+ next_state = trans_i->state; |
+ next_tags = trans_i->tags; |
+ } else { |
+ /* Second matching transition. We may need to backtrack here |
+ to take this transition instead of the first one, so we |
+ push this transition in the backtracking stack so we can |
+ jump back here if needed. */ |
+ BT_STACK_PUSH(pos, str_byte, 0, trans_i->state, trans_i->state_id, |
+ next_c, tags, mbstate); |
+ { |
+ int* tmp; |
+ for (tmp = trans_i->tags; tmp && *tmp >= 0; tmp++) |
+ stack->item.tags[*tmp] = pos; |
+ } |
+#if 0 /* XXX - it's important not to look at all transitions here to keep \ |
+ the stack small! */ |
break; |
#endif |
- } |
- } |
- } |
- |
- if (next_state != NULL) |
- { |
- /* Matching transitions were found. Take the first one. */ |
- state = next_state; |
- |
- /* Update the tag values. */ |
- if (next_tags) |
- while (*next_tags >= 0) |
- tags[*next_tags++] = pos; |
- } |
- else |
- { |
- backtrack: |
- /* A matching transition was not found. Try to backtrack. */ |
- if (stack->prev) |
- { |
- if (stack->item.state->assertions & ASSERT_BACKREF) |
- { |
- states_seen[stack->item.state_id] = 0; |
- } |
- |
- BT_STACK_POP(); |
- } |
- else if (match_eo < 0) |
- { |
- /* Try starting from a later position in the input string. */ |
- /* Check for end of string. */ |
- if (next_c == L'\0') |
- { |
- break; |
- } |
- next_c = next_c_start; |
+ } |
+ } |
+ } |
+ |
+ if (next_state != NULL) { |
+ /* Matching transitions were found. Take the first one. */ |
+ state = next_state; |
+ |
+ /* Update the tag values. */ |
+ if (next_tags) |
+ while (*next_tags >= 0) |
+ tags[*next_tags++] = pos; |
+ } else { |
+ backtrack: |
+ /* A matching transition was not found. Try to backtrack. */ |
+ if (stack->prev) { |
+ if (stack->item.state->assertions & ASSERT_BACKREF) { |
+ states_seen[stack->item.state_id] = 0; |
+ } |
+ |
+ BT_STACK_POP(); |
+ } else if (match_eo < 0) { |
+ /* Try starting from a later position in the input string. */ |
+ /* Check for end of string. */ |
+ if (next_c == L'\0') { |
+ break; |
+ } |
+ next_c = next_c_start; |
#ifdef TRE_MBSTATE |
- mbstate = mbstate_start; |
+ mbstate = mbstate_start; |
#endif /* TRE_MBSTATE */ |
- str_byte = str_byte_start; |
- goto retry; |
- } |
- else |
- { |
- break; |
- } |
- } |
+ str_byte = str_byte_start; |
+ goto retry; |
+ } else { |
+ break; |
+ } |
} |
+ } |
ret = match_eo >= 0 ? REG_OK : REG_NOMATCH; |
*match_end_ofs = match_eo; |
- error_exit: |
+error_exit: |
tre_bt_mem_destroy(mem); |
#ifndef TRE_USE_ALLOCA |
if (tags) |
@@ -911,98 +822,92 @@ tre_tnfa_run_backtrack(const tre_tnfa_t *tnfa, const void *string, |
/* Fills the POSIX.2 regmatch_t array according to the TNFA tag and match |
endpoint values. */ |
-static void |
-tre_fill_pmatch(size_t nmatch, regmatch_t pmatch[], int cflags, |
- const tre_tnfa_t *tnfa, int *tags, int match_eo) |
-{ |
- tre_submatch_data_t *submatch_data; |
+static void tre_fill_pmatch(size_t nmatch, |
+ regmatch_t pmatch[], |
+ int cflags, |
+ const tre_tnfa_t* tnfa, |
+ int* tags, |
+ int match_eo) { |
+ tre_submatch_data_t* submatch_data; |
unsigned int i, j; |
- int *parents; |
+ int* parents; |
i = 0; |
- if (match_eo >= 0 && !(cflags & REG_NOSUB)) |
- { |
- /* Construct submatch offsets from the tags. */ |
- submatch_data = tnfa->submatch_data; |
- while (i < tnfa->num_submatches && i < nmatch) |
- { |
- if (submatch_data[i].so_tag == tnfa->end_tag) |
- pmatch[i].rm_so = match_eo; |
- else |
- pmatch[i].rm_so = tags[submatch_data[i].so_tag]; |
- |
- if (submatch_data[i].eo_tag == tnfa->end_tag) |
- pmatch[i].rm_eo = match_eo; |
- else |
- pmatch[i].rm_eo = tags[submatch_data[i].eo_tag]; |
- |
- /* If either of the endpoints were not used, this submatch |
- was not part of the match. */ |
- if (pmatch[i].rm_so == -1 || pmatch[i].rm_eo == -1) |
- pmatch[i].rm_so = pmatch[i].rm_eo = -1; |
- |
- i++; |
- } |
- /* Reset all submatches that are not within all of their parent |
- submatches. */ |
- i = 0; |
- while (i < tnfa->num_submatches && i < nmatch) |
- { |
- if (pmatch[i].rm_eo == -1) |
- assert(pmatch[i].rm_so == -1); |
- assert(pmatch[i].rm_so <= pmatch[i].rm_eo); |
- |
- parents = submatch_data[i].parents; |
- if (parents != NULL) |
- for (j = 0; parents[j] >= 0; j++) |
- { |
- if (pmatch[i].rm_so < pmatch[parents[j]].rm_so |
- || pmatch[i].rm_eo > pmatch[parents[j]].rm_eo) |
- pmatch[i].rm_so = pmatch[i].rm_eo = -1; |
- } |
- i++; |
- } |
- } |
+ if (match_eo >= 0 && !(cflags & REG_NOSUB)) { |
+ /* Construct submatch offsets from the tags. */ |
+ submatch_data = tnfa->submatch_data; |
+ while (i < tnfa->num_submatches && i < nmatch) { |
+ if (submatch_data[i].so_tag == tnfa->end_tag) |
+ pmatch[i].rm_so = match_eo; |
+ else |
+ pmatch[i].rm_so = tags[submatch_data[i].so_tag]; |
+ |
+ if (submatch_data[i].eo_tag == tnfa->end_tag) |
+ pmatch[i].rm_eo = match_eo; |
+ else |
+ pmatch[i].rm_eo = tags[submatch_data[i].eo_tag]; |
+ |
+ /* If either of the endpoints were not used, this submatch |
+ was not part of the match. */ |
+ if (pmatch[i].rm_so == -1 || pmatch[i].rm_eo == -1) |
+ pmatch[i].rm_so = pmatch[i].rm_eo = -1; |
- while (i < nmatch) |
- { |
- pmatch[i].rm_so = -1; |
- pmatch[i].rm_eo = -1; |
i++; |
} |
-} |
+ /* Reset all submatches that are not within all of their parent |
+ submatches. */ |
+ i = 0; |
+ while (i < tnfa->num_submatches && i < nmatch) { |
+ if (pmatch[i].rm_eo == -1) |
+ assert(pmatch[i].rm_so == -1); |
+ assert(pmatch[i].rm_so <= pmatch[i].rm_eo); |
+ |
+ parents = submatch_data[i].parents; |
+ if (parents != NULL) |
+ for (j = 0; parents[j] >= 0; j++) { |
+ if (pmatch[i].rm_so < pmatch[parents[j]].rm_so || |
+ pmatch[i].rm_eo > pmatch[parents[j]].rm_eo) |
+ pmatch[i].rm_so = pmatch[i].rm_eo = -1; |
+ } |
+ i++; |
+ } |
+ } |
+ while (i < nmatch) { |
+ pmatch[i].rm_so = -1; |
+ pmatch[i].rm_eo = -1; |
+ i++; |
+ } |
+} |
/* |
Wrapper functions for POSIX compatible regexp matching. |
*/ |
-int |
-regexec(const regex_t *restrict preg, const char *restrict string, |
- size_t nmatch, regmatch_t pmatch[restrict], int eflags) |
-{ |
- tre_tnfa_t *tnfa = (void *)preg->TRE_REGEX_T_FIELD; |
+int regexec(const regex_t* restrict preg, |
+ const char* restrict string, |
+ size_t nmatch, |
+ regmatch_t pmatch[restrict], |
+ int eflags) { |
+ tre_tnfa_t* tnfa = (void*)preg->TRE_REGEX_T_FIELD; |
reg_errcode_t status; |
int *tags = NULL, eo; |
- if (tnfa->cflags & REG_NOSUB) nmatch = 0; |
- if (tnfa->num_tags > 0 && nmatch > 0) |
- { |
- tags = xmalloc(sizeof(*tags) * tnfa->num_tags); |
- if (tags == NULL) |
- return REG_ESPACE; |
- } |
+ if (tnfa->cflags & REG_NOSUB) |
+ nmatch = 0; |
+ if (tnfa->num_tags > 0 && nmatch > 0) { |
+ tags = xmalloc(sizeof(*tags) * tnfa->num_tags); |
+ if (tags == NULL) |
+ return REG_ESPACE; |
+ } |
/* Dispatch to the appropriate matcher. */ |
- if (tnfa->have_backrefs) |
- { |
- /* The regex has back references, use the backtracking matcher. */ |
- status = tre_tnfa_run_backtrack(tnfa, string, tags, eflags, &eo); |
- } |
- else |
- { |
- /* Exact matching, no back references, use the parallel matcher. */ |
- status = tre_tnfa_run_parallel(tnfa, string, tags, eflags, &eo); |
- } |
+ if (tnfa->have_backrefs) { |
+ /* The regex has back references, use the backtracking matcher. */ |
+ status = tre_tnfa_run_backtrack(tnfa, string, tags, eflags, &eo); |
+ } else { |
+ /* Exact matching, no back references, use the parallel matcher. */ |
+ status = tre_tnfa_run_parallel(tnfa, string, tags, eflags, &eo); |
+ } |
if (status == REG_OK) |
/* A match was found, so fill the submatch registers. */ |