Main Page | Class List | Directories | File List | Class Members | File Members

regexec.c File Reference

Go to the source code of this file.

Defines

#define NUMBER_OF_STATE   1
#define STATE_NODE_CONTAINS(state, node)   ((state) != NULL && re_node_set_contains (&(state)->nodes, node))

Functions

static reg_errcode_t match_ctx_init _RE_ARGS ((re_match_context_t *cache, int eflags, re_string_t *input, int n))
int regexec (regex_t *__restrict preg, const char *__restrict string, size_t nmatch, pmatch, int eflags) const
int re_match (struct re_pattern_buffer *bufp, const char *string, int length, int start, struct re_registers *regs)
int re_search (struct re_pattern_buffer *bufp, const char *string, int length, int start, int range, struct re_registers *regs)
int re_match_2 (struct re_pattern_buffer *bufp, const char *string1, int length1, const char *string2, int length2, int start, struct re_registers *regs, int stop)
int re_search_2 (struct re_pattern_buffer *bufp, const char *string1, int length1, const char *string2, int length2, int start, int range, struct re_registers *regs, int stop)
static int re_search_2_stub (struct re_pattern_buffer *bufp, const char *string1, int length1, const char *string2, int length2, int start, int range, struct re_registers *regs, int stop, int ret_len)
static int re_search_stub (struct re_pattern_buffer *bufp, const char *string, int length, int start, int range, int stop, struct re_registers *regs, int ret_len)
static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch, int nregs, int regs_allocated)
void re_set_registers (struct re_pattern_buffer *bufp, struct re_registers *regs, unsigned num_regs, regoff_t *starts, regoff_t *ends)
static reg_errcode_t re_search_internal (regex_t *preg, const char *string, int length, int start, int range, int stop, size_t nmatch, pmatch, int eflags) const
static reg_errcode_t prune_impossible_nodes (regex_t *preg, re_match_context_t *mctx) const
static re_dfastate_tacquire_init_state_context (reg_errcode_t *err, const regex_t *preg, const re_match_context_t *mctx, int idx)
static int check_matching (regex_t *preg, re_match_context_t *mctx, int fl_search, int fl_longest_match) const
static int check_halt_node_context (re_dfa_t *dfa, int node, unsigned int context) const
static int check_halt_state_context (regex_t *preg, const re_dfastate_t *state, const re_match_context_t *mctx, int idx) const
static int proceed_next_node (regex_t *preg, int nregs, regmatch_t *regs, const re_match_context_t *mctx, int *pidx, int node, re_node_set *eps_via_nodes, struct re_fail_stack_t *fs) const
static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs, int str_idx, int *dests, int nregs, regmatch_t *regs, re_node_set *eps_via_nodes)
static int pop_fail_stack (struct re_fail_stack_t *fs, int *pidx, int nregs, regmatch_t *regs, re_node_set *eps_via_nodes)
static reg_errcode_t set_regs (regex_t *preg, const re_match_context_t *mctx, size_t nmatch, regmatch_t *pmatch, int fl_backtrack) const
static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs)
static void update_regs (re_dfa_t *dfa, regmatch_t *pmatch, int cur_node, int cur_idx, int nmatch)
static reg_errcode_t sift_states_backward (regex_t *preg, re_match_context_t *mctx, re_sift_context_t *sctx) const
static reg_errcode_t clean_state_log_if_need (re_match_context_t *mctx, int next_state_log_idx)
static reg_errcode_t merge_state_array (re_dfa_t *dfa, re_dfastate_t **dst, re_dfastate_t **src, int num)
static reg_errcode_t update_cur_sifted_state (regex_t *preg, re_match_context_t *mctx, re_sift_context_t *sctx, int str_idx, re_node_set *dest_nodes) const
static reg_errcode_t add_epsilon_src_nodes (re_dfa_t *dfa, re_node_set *dest_nodes, const re_node_set *candidates)
static reg_errcode_t sub_epsilon_src_nodes (re_dfa_t *dfa, int node, re_node_set *dest_nodes, const re_node_set *candidates)
static int check_dst_limits (re_dfa_t *dfa, re_node_set *limits, re_match_context_t *mctx, int dst_node, int dst_idx, int src_node, int src_idx)
static int check_dst_limits_calc_pos (re_dfa_t *dfa, re_match_context_t *mctx, int limit, re_node_set *eclosures, int subexp_idx, int node, int str_idx)
static reg_errcode_t check_subexp_limits (re_dfa_t *dfa, re_node_set *dest_nodes, const re_node_set *candidates, re_node_set *limits, struct re_backref_cache_entry *bkref_ents, int str_idx)
static reg_errcode_t sift_states_bkref (regex_t *preg, re_match_context_t *mctx, re_sift_context_t *sctx, int str_idx, re_node_set *dest_nodes) const
static re_dfastate_ttransit_state (reg_errcode_t *err, const regex_t *preg, re_match_context_t *mctx, re_dfastate_t *state, int fl_search)
static reg_errcode_t check_subexp_matching_top (re_dfa_t *dfa, re_match_context_t *mctx, re_node_set *cur_nodes, int str_idx)
static re_dfastate_ttransit_state_sb (reg_errcode_t *err, const regex_t *preg, re_dfastate_t *state, int fl_search, re_match_context_t *mctx)
static reg_errcode_t transit_state_bkref (regex_t *preg, re_node_set *nodes, re_match_context_t *mctx) const
static reg_errcode_t get_subexp (regex_t *preg, re_match_context_t *mctx, int bkref_node, int bkref_str_idx) const
static reg_errcode_t get_subexp_sub (regex_t *preg, re_match_context_t *mctx, re_sub_match_top_t *sub_top, re_sub_match_last_t *sub_last, int bkref_node, int bkref_str) const
static int find_subexp_node (re_dfa_t *dfa, re_node_set *nodes, int subexp_idx, int fl_open)
static reg_errcode_t check_arrival (regex_t *preg, re_match_context_t *mctx, state_array_t *path, int top_node, int top_str, int last_node, int last_str, int fl_open) const
static reg_errcode_t check_arrival_add_next_nodes (regex_t *preg, re_dfa_t *dfa, re_match_context_t *mctx, int str_idx, re_node_set *cur_nodes, re_node_set *next_nodes) const
static reg_errcode_t check_arrival_expand_ecl (re_dfa_t *dfa, re_node_set *cur_nodes, int ex_subexp, int fl_open)
static reg_errcode_t check_arrival_expand_ecl_sub (re_dfa_t *dfa, re_node_set *dst_nodes, int target, int ex_subexp, int fl_open)
static reg_errcode_t expand_bkref_cache (regex_t *preg, re_match_context_t *mctx, re_node_set *cur_nodes, int cur_str, int last_str, int subexp_num, int fl_open) const
static re_dfastate_t ** build_trtable (regex_t *preg, const re_dfastate_t *state, int fl_search) const
static int group_nodes_into_DFAstates (regex_t *preg, const re_dfastate_t *state, re_node_set *dests_node, bitset *dests_ch) const
static int check_node_accept (regex_t *preg, const re_token_t *node, const re_match_context_t *mctx, int idx) const
static reg_errcode_t extend_buffers (re_match_context_t *mctx)
static reg_errcode_t match_ctx_init (re_match_context_t *mctx, int eflags, re_string_t *input, int n)
static void match_ctx_clean (re_match_context_t *mctx)
static void match_ctx_free (re_match_context_t *mctx)
static void match_ctx_free_subtops (re_match_context_t *mctx)
static reg_errcode_t match_ctx_add_entry (re_match_context_t *mctx, int node, int str_idx, int from, int to)
static int search_cur_bkref_entry (re_match_context_t *mctx, int str_idx)
static void match_ctx_clear_flag (re_match_context_t *mctx)
static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx)
static re_sub_match_last_tmatch_ctx_add_sublast (re_sub_match_top_t *subtop, int node, int str_idx)
static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts, re_dfastate_t **limited_sts, int last_node, int last_str_idx, int check_subexp)

Variables

static re_node_set empty_set


Define Documentation

#define NUMBER_OF_STATE   1
 

Definition at line 1381 of file regexec.c.

#define STATE_NODE_CONTAINS state,
node   )     ((state) != NULL && re_node_set_contains (&(state)->nodes, node))
 

Definition at line 1403 of file regexec.c.

Referenced by sift_states_backward(), and sift_states_bkref().


Function Documentation

static reg_errcode_t match_ctx_init _RE_ARGS (re_match_context_t *cache, int eflags, re_string_t *input, int n  )  [static]
 

static re_dfastate_t* acquire_init_state_context reg_errcode_t err,
const regex_t preg,
const re_match_context_t mctx,
int  idx
[inline, static]
 

Definition at line 914 of file regexec.c.

References re_pattern_buffer::buffer, re_match_context_t::eflags, re_dfastate_t::entrance_nodes, re_dfastate_t::has_constraint, re_dfa_t::init_state, re_dfa_t::init_state_begbuf, re_dfa_t::init_state_nl, re_dfa_t::init_state_word, re_match_context_t::input, IS_BEGBUF_CONTEXT, IS_NEWLINE_CONTEXT, IS_ORDINARY_CONTEXT, IS_WORD_CONTEXT, re_pattern_buffer::newline_anchor, re_acquire_state_context(), re_string_context_at(), and REG_NOERROR.

Referenced by check_matching().

00919 {
00920   re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
00921 
00922   *err = REG_NOERROR;
00923   if (dfa->init_state->has_constraint)
00924     {
00925       unsigned int context;
00926       context =  re_string_context_at (mctx->input, idx - 1, mctx->eflags,
00927                                        preg->newline_anchor);
00928       if (IS_WORD_CONTEXT (context))
00929         return dfa->init_state_word;
00930       else if (IS_ORDINARY_CONTEXT (context))
00931         return dfa->init_state;
00932       else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context))
00933         return dfa->init_state_begbuf;
00934       else if (IS_NEWLINE_CONTEXT (context))
00935         return dfa->init_state_nl;
00936       else if (IS_BEGBUF_CONTEXT (context))
00937         {
00938           /* It is relatively rare case, then calculate on demand.  */
00939           return  re_acquire_state_context (err, dfa,
00940                                             dfa->init_state->entrance_nodes,
00941                                             context);
00942         }
00943       else
00944         /* Must not happen?  */
00945         return dfa->init_state;
00946     }
00947   else
00948     return dfa->init_state;
00949 }

static reg_errcode_t add_epsilon_src_nodes re_dfa_t dfa,
re_node_set dest_nodes,
const re_node_set candidates
[static]
 

Definition at line 1620 of file regexec.c.

References BE, re_node_set::elems, err(), re_node_set::nelem, re_node_set_add_intersect(), re_node_set_free, re_node_set_init_copy(), and REG_NOERROR.

Referenced by update_cur_sifted_state().

01624 {
01625   reg_errcode_t err;
01626   int src_idx;
01627   re_node_set src_copy;
01628 
01629   err = re_node_set_init_copy (&src_copy, dest_nodes);
01630   if (BE (err != REG_NOERROR, 0))
01631     return err;
01632   for (src_idx = 0; src_idx < src_copy.nelem; ++src_idx)
01633     {
01634       err = re_node_set_add_intersect (dest_nodes, candidates,
01635                                        dfa->inveclosures
01636                                        + src_copy.elems[src_idx]);
01637       if (BE (err != REG_NOERROR, 0))
01638         {
01639           re_node_set_free (&src_copy);
01640           return err;
01641         }
01642     }
01643   re_node_set_free (&src_copy);
01644   return REG_NOERROR;
01645 }

static re_dfastate_t** build_trtable regex_t preg,
const re_dfastate_t state,
int  fl_search
const [static]
 

Definition at line 3083 of file regexec.c.

References alloca, BE, bitset_contain, bitset_empty, BITSET_UINTS, CHARACTER, CONTEXT_NEWLINE, CONTEXT_WORD, re_dfa_t::eclosures, re_node_set::elems, re_dfastate_t::entrance_nodes, free(), group_nodes_into_DFAstates(), re_dfa_t::init_state, IS_WORD_CHAR, malloc(), re_node_set::nelem, NEWLINE_CHAR, re_dfa_t::nexts, re_dfa_t::nodes, NULL, re_acquire_state_context(), re_node_set_alloc(), re_node_set_empty, re_node_set_free, re_node_set_merge(), REG_NOERROR, SBC_MAX, and UINT_BITS.

Referenced by transit_state().

03087 {
03088   reg_errcode_t err;
03089   re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
03090   int i, j, k, ch;
03091   int dests_node_malloced = 0, dest_states_malloced = 0;
03092   int ndests; /* Number of the destination states from `state'.  */
03093   re_dfastate_t **trtable;
03094   re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl;
03095   re_node_set follows, *dests_node;
03096   bitset *dests_ch;
03097   bitset acceptable;
03098 
03099   /* We build DFA states which corresponds to the destination nodes
03100      from `state'.  `dests_node[i]' represents the nodes which i-th
03101      destination state contains, and `dests_ch[i]' represents the
03102      characters which i-th destination state accepts.  */
03103 #ifdef _LIBC
03104   if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX))
03105     dests_node = (re_node_set *)
03106                  alloca ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX);
03107   else
03108 #endif
03109     {
03110       dests_node = (re_node_set *)
03111                    malloc ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX);
03112       if (BE (dests_node == NULL, 0))
03113         return NULL;
03114       dests_node_malloced = 1;
03115     }
03116   dests_ch = (bitset *) (dests_node + SBC_MAX);
03117 
03118   /* Initialize transiton table.  */
03119   trtable = (re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX);
03120   if (BE (trtable == NULL, 0))
03121     {
03122       if (dests_node_malloced)
03123         free (dests_node);
03124       return NULL;
03125     }
03126 
03127   /* At first, group all nodes belonging to `state' into several
03128      destinations.  */
03129   ndests = group_nodes_into_DFAstates (preg, state, dests_node, dests_ch);
03130   if (BE (ndests <= 0, 0))
03131     {
03132       if (dests_node_malloced)
03133         free (dests_node);
03134       /* Return NULL in case of an error, trtable otherwise.  */
03135       if (ndests == 0)
03136         return trtable;
03137       free (trtable);
03138       return NULL;
03139     }
03140 
03141   err = re_node_set_alloc (&follows, ndests + 1);
03142   if (BE (err != REG_NOERROR, 0))
03143     goto out_free;
03144 
03145 #ifdef _LIBC
03146   if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset)) * SBC_MAX
03147                          + ndests * 3 * sizeof (re_dfastate_t *)))
03148     dest_states = (re_dfastate_t **)
03149                   alloca (ndests * 3 * sizeof (re_dfastate_t *));
03150   else
03151 #endif
03152     {
03153       dest_states = (re_dfastate_t **)
03154                     malloc (ndests * 3 * sizeof (re_dfastate_t *));
03155       if (BE (dest_states == NULL, 0))
03156         {
03157 out_free:
03158           if (dest_states_malloced)
03159             free (dest_states);
03160           re_node_set_free (&follows);
03161           for (i = 0; i < ndests; ++i)
03162             re_node_set_free (dests_node + i);
03163           free (trtable);
03164           if (dests_node_malloced)
03165             free (dests_node);
03166           return NULL;
03167         }
03168       dest_states_malloced = 1;
03169     }
03170   dest_states_word = dest_states + ndests;
03171   dest_states_nl = dest_states_word + ndests;
03172   bitset_empty (acceptable);
03173 
03174   /* Then build the states for all destinations.  */
03175   for (i = 0; i < ndests; ++i)
03176     {
03177       int next_node;
03178       re_node_set_empty (&follows);
03179       /* Merge the follows of this destination states.  */
03180       for (j = 0; j < dests_node[i].nelem; ++j)
03181         {
03182           next_node = dfa->nexts[dests_node[i].elems[j]];
03183           if (next_node != -1)
03184             {
03185               err = re_node_set_merge (&follows, dfa->eclosures + next_node);
03186               if (BE (err != REG_NOERROR, 0))
03187                 goto out_free;
03188             }
03189         }
03190       /* If search flag is set, merge the initial state.  */
03191       if (fl_search)
03192         {
03193 #ifdef RE_ENABLE_I18N
03194           int not_initial = 0;
03195           for (j = 0; j < follows.nelem; ++j)
03196             if (dfa->nodes[follows.elems[j]].type == CHARACTER)
03197               {
03198                 not_initial = dfa->nodes[follows.elems[j]].mb_partial;
03199                 break;
03200               }
03201           if (!not_initial)
03202 #endif
03203             {
03204               err = re_node_set_merge (&follows,
03205                                        dfa->init_state->entrance_nodes);
03206               if (BE (err != REG_NOERROR, 0))
03207                 goto out_free;
03208             }
03209         }
03210       dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0);
03211       if (BE (dest_states[i] == NULL && err != REG_NOERROR, 0))
03212         goto out_free;
03213       /* If the new state has context constraint,
03214          build appropriate states for these contexts.  */
03215       if (dest_states[i]->has_constraint)
03216         {
03217           dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows,
03218                                                           CONTEXT_WORD);
03219           if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0))
03220             goto out_free;
03221           dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows,
03222                                                         CONTEXT_NEWLINE);
03223           if (BE (dest_states_nl[i] == NULL && err != REG_NOERROR, 0))
03224             goto out_free;
03225         }
03226       else
03227         {
03228           dest_states_word[i] = dest_states[i];
03229           dest_states_nl[i] = dest_states[i];
03230         }
03231       bitset_merge (acceptable, dests_ch[i]);
03232     }
03233 
03234   /* Update the transition table.  */
03235   /* For all characters ch...:  */
03236   for (i = 0, ch = 0; i < BITSET_UINTS; ++i)
03237     for (j = 0; j < UINT_BITS; ++j, ++ch)
03238       if ((acceptable[i] >> j) & 1)
03239         {
03240           /* The current state accepts the character ch.  */
03241           if (IS_WORD_CHAR (ch))
03242             {
03243               for (k = 0; k < ndests; ++k)
03244                 if ((dests_ch[k][i] >> j) & 1)
03245                   {
03246                     /* k-th destination accepts the word character ch.  */
03247                     trtable[ch] = dest_states_word[k];
03248                     /* There must be only one destination which accepts
03249                        character ch.  See group_nodes_into_DFAstates.  */
03250                     break;
03251                   }
03252             }
03253           else /* not WORD_CHAR */
03254             {
03255               for (k = 0; k < ndests; ++k)
03256                 if ((dests_ch[k][i] >> j) & 1)
03257                   {
03258                     /* k-th destination accepts the non-word character ch.  */
03259                     trtable[ch] = dest_states[k];
03260                     /* There must be only one destination which accepts
03261                        character ch.  See group_nodes_into_DFAstates.  */
03262                     break;
03263                   }
03264             }
03265         }
03266   /* new line */
03267   if (bitset_contain (acceptable, NEWLINE_CHAR))
03268     {
03269       /* The current state accepts newline character.  */
03270       for (k = 0; k < ndests; ++k)
03271         if (bitset_contain (dests_ch[k], NEWLINE_CHAR))
03272           {
03273             /* k-th destination accepts newline character.  */
03274             trtable[NEWLINE_CHAR] = dest_states_nl[k];
03275             /* There must be only one destination which accepts
03276                newline.  See group_nodes_into_DFAstates.  */
03277             break;
03278           }
03279     }
03280 
03281   if (dest_states_malloced)
03282     free (dest_states);
03283 
03284   re_node_set_free (&follows);
03285   for (i = 0; i < ndests; ++i)
03286     re_node_set_free (dests_node + i);
03287 
03288   if (dests_node_malloced)
03289     free (dests_node);
03290 
03291   return trtable;
03292 }

static reg_errcode_t check_arrival regex_t preg,
re_match_context_t mctx,
state_array_t path,
int  top_node,
int  top_str,
int  last_node,
int  last_str,
int  fl_open
const [static]
 

Definition at line 2638 of file regexec.c.

References state_array_t::alloc, state_array_t::array, BE, check_arrival_add_next_nodes(), check_arrival_expand_ecl(), re_string_t::cur_idx, re_match_context_t::eflags, expand_bkref_cache(), re_dfastate_t::has_backref, re_match_context_t::input, re_match_context_t::max_mb_elem_len, memset(), re_node_set::nelem, state_array_t::next_idx, re_dfastate_t::nodes, re_dfa_t::nodes, NULL, re_token_t::opr, re_acquire_state_context(), re_node_set_contains(), re_node_set_empty, re_node_set_free, re_node_set_init_1(), re_node_set_init_copy(), re_node_set_init_empty, re_node_set_merge(), re_realloc, re_string_context_at(), REG_ESPACE, REG_NOERROR, REG_NOMATCH, and re_match_context_t::state_log.

Referenced by get_subexp(), and get_subexp_sub().

02644 {
02645   re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
02646   reg_errcode_t err;
02647   int subexp_num, backup_cur_idx, str_idx, null_cnt;
02648   re_dfastate_t *cur_state = NULL;
02649   re_node_set *cur_nodes, next_nodes;
02650   re_dfastate_t **backup_state_log;
02651   unsigned int context;
02652 
02653   subexp_num = dfa->nodes[top_node].opr.idx;
02654   /* Extend the buffer if we need.  */
02655   if (path->alloc < last_str + mctx->max_mb_elem_len + 1)
02656     {
02657       re_dfastate_t **new_array;
02658       int old_alloc = path->alloc;
02659       path->alloc += last_str + mctx->max_mb_elem_len + 1;
02660       new_array = re_realloc (path->array, re_dfastate_t *, path->alloc);
02661       if (new_array == NULL)
02662         return REG_ESPACE;
02663       path->array = new_array;
02664       memset (new_array + old_alloc, '\0',
02665               sizeof (re_dfastate_t *) * (path->alloc - old_alloc));
02666     }
02667 
02668   str_idx = path->next_idx == 0 ? top_str : path->next_idx;
02669 
02670   /* Temporary modify MCTX.  */
02671   backup_state_log = mctx->state_log;
02672   backup_cur_idx = mctx->input->cur_idx;
02673   mctx->state_log = path->array;
02674   mctx->input->cur_idx = str_idx;
02675 
02676   /* Setup initial node set.  */
02677   context = re_string_context_at (mctx->input, str_idx - 1, mctx->eflags,
02678                                   preg->newline_anchor);
02679   if (str_idx == top_str)
02680     {
02681       err = re_node_set_init_1 (&next_nodes, top_node);
02682       if (BE (err != REG_NOERROR, 0))
02683         return err;
02684       err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, fl_open);
02685       if (BE (err != REG_NOERROR, 0))
02686         {
02687           re_node_set_free (&next_nodes);
02688           return err;
02689         }
02690     }
02691   else
02692     {
02693       cur_state = mctx->state_log[str_idx];
02694       if (cur_state && cur_state->has_backref)
02695         {
02696           err = re_node_set_init_copy (&next_nodes, &cur_state->nodes);
02697           if (BE ( err != REG_NOERROR, 0))
02698             return err;
02699         }
02700       else
02701         re_node_set_init_empty (&next_nodes);
02702     }
02703   if (str_idx == top_str || (cur_state && cur_state->has_backref))
02704     {
02705       if (next_nodes.nelem)
02706         {
02707           err = expand_bkref_cache (preg, mctx, &next_nodes, str_idx, last_str,
02708                                     subexp_num, fl_open);
02709           if (BE ( err != REG_NOERROR, 0))
02710             {
02711               re_node_set_free (&next_nodes);
02712               return err;
02713             }
02714         }
02715       cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context);
02716       if (BE (cur_state == NULL && err != REG_NOERROR, 0))
02717         {
02718           re_node_set_free (&next_nodes);
02719           return err;
02720         }
02721       mctx->state_log[str_idx] = cur_state;
02722     }
02723 
02724   for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;)
02725     {
02726       re_node_set_empty (&next_nodes);
02727       if (mctx->state_log[str_idx + 1])
02728         {
02729           err = re_node_set_merge (&next_nodes,
02730                                    &mctx->state_log[str_idx + 1]->nodes);
02731           if (BE (err != REG_NOERROR, 0))
02732             {
02733               re_node_set_free (&next_nodes);
02734               return err;
02735             }
02736         }
02737       if (cur_state)
02738         {
02739           err = check_arrival_add_next_nodes(preg, dfa, mctx, str_idx,
02740                                              &cur_state->nodes, &next_nodes);
02741           if (BE (err != REG_NOERROR, 0))
02742             {
02743               re_node_set_free (&next_nodes);
02744               return err;
02745             }
02746         }
02747       ++str_idx;
02748       if (next_nodes.nelem)
02749         {
02750           err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num,
02751                                           fl_open);
02752           if (BE (err != REG_NOERROR, 0))
02753             {
02754               re_node_set_free (&next_nodes);
02755               return err;
02756             }
02757           err = expand_bkref_cache (preg, mctx, &next_nodes, str_idx, last_str,
02758                                     subexp_num, fl_open);
02759           if (BE ( err != REG_NOERROR, 0))
02760             {
02761               re_node_set_free (&next_nodes);
02762               return err;
02763             }
02764         }
02765       context = re_string_context_at (mctx->input, str_idx - 1, mctx->eflags,
02766                                       preg->newline_anchor);
02767       cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context);
02768       if (BE (cur_state == NULL && err != REG_NOERROR, 0))
02769         {
02770           re_node_set_free (&next_nodes);
02771           return err;
02772         }
02773       mctx->state_log[str_idx] = cur_state;
02774       null_cnt = cur_state == NULL ? null_cnt + 1 : 0;
02775     }
02776   re_node_set_free (&next_nodes);
02777   cur_nodes = (mctx->state_log[last_str] == NULL ? NULL
02778                : &mctx->state_log[last_str]->nodes);
02779   path->next_idx = str_idx;
02780 
02781   /* Fix MCTX.  */
02782   mctx->state_log = backup_state_log;
02783   mctx->input->cur_idx = backup_cur_idx;
02784 
02785   if (cur_nodes == NULL)
02786     return REG_NOMATCH;
02787   /* Then check the current node set has the node LAST_NODE.  */
02788   return (re_node_set_contains (cur_nodes, last_node)
02789           || re_node_set_contains (cur_nodes, last_node) ? REG_NOERROR
02790           : REG_NOMATCH);
02791 }

static reg_errcode_t check_arrival_add_next_nodes regex_t preg,
re_dfa_t dfa,
re_match_context_t mctx,
int  str_idx,
re_node_set cur_nodes,
re_node_set next_nodes
const [static]
 

Definition at line 2802 of file regexec.c.

References ACCEPT_MB_NODE, BE, check_node_accept(), re_node_set::elems, re_match_context_t::input, IS_EPSILON_NODE, re_dfa_t::nexts, re_dfastate_t::nodes, re_dfa_t::nodes, NULL, re_acquire_state(), re_node_set_empty, re_node_set_free, re_node_set_init_empty, re_node_set_insert(), re_node_set_merge(), REG_ESPACE, REG_NOERROR, re_match_context_t::state_log, and re_token_t::type.

Referenced by check_arrival().

02808 {
02809   int cur_idx;
02810   reg_errcode_t err;
02811   re_node_set union_set;
02812   re_node_set_init_empty (&union_set);
02813   for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx)
02814     {
02815       int naccepted = 0;
02816       int cur_node = cur_nodes->elems[cur_idx];
02817       re_token_type_t type = dfa->nodes[cur_node].type;
02818       if (IS_EPSILON_NODE(type))
02819         continue;
02820 #ifdef RE_ENABLE_I18N
02821       /* If the node may accept `multi byte'.  */
02822       if (ACCEPT_MB_NODE (type))
02823         {
02824           naccepted = check_node_accept_bytes (preg, cur_node, mctx->input,
02825                                                str_idx);
02826           if (naccepted > 1)
02827             {
02828               re_dfastate_t *dest_state;
02829               int next_node = dfa->nexts[cur_node];
02830               int next_idx = str_idx + naccepted;
02831               dest_state = mctx->state_log[next_idx];
02832               re_node_set_empty (&union_set);
02833               if (dest_state)
02834                 {
02835                   err = re_node_set_merge (&union_set, &dest_state->nodes);
02836                   if (BE (err != REG_NOERROR, 0))
02837                     {
02838                       re_node_set_free (&union_set);
02839                       return err;
02840                     }
02841                   err = re_node_set_insert (&union_set, next_node);
02842                   if (BE (err < 0, 0))
02843                     {
02844                       re_node_set_free (&union_set);
02845                       return REG_ESPACE;
02846                     }
02847                 }
02848               else
02849                 {
02850                   err = re_node_set_insert (&union_set, next_node);
02851                   if (BE (err < 0, 0))
02852                     {
02853                       re_node_set_free (&union_set);
02854                       return REG_ESPACE;
02855                     }
02856                 }
02857               mctx->state_log[next_idx] = re_acquire_state (&err, dfa,
02858                                                             &union_set);
02859               if (BE (mctx->state_log[next_idx] == NULL
02860                       && err != REG_NOERROR, 0))
02861                 {
02862                   re_node_set_free (&union_set);
02863                   return err;
02864                 }
02865             }
02866         }
02867 #endif /* RE_ENABLE_I18N */
02868       if (naccepted
02869           || check_node_accept (preg, dfa->nodes + cur_node, mctx,
02870                                 str_idx))
02871         {
02872           err = re_node_set_insert (next_nodes, dfa->nexts[cur_node]);
02873           if (BE (err < 0, 0))
02874             {
02875               re_node_set_free (&union_set);
02876               return REG_ESPACE;
02877             }
02878         }
02879     }
02880   re_node_set_free (&union_set);
02881   return REG_NOERROR;
02882 }

static reg_errcode_t check_arrival_expand_ecl re_dfa_t dfa,
re_node_set cur_nodes,
int  ex_subexp,
int  fl_open
[static]
 

Definition at line 2891 of file regexec.c.

References BE, check_arrival_expand_ecl_sub(), re_node_set::elems, find_subexp_node(), re_node_set::nelem, re_node_set_alloc(), re_node_set_free, re_node_set_merge(), and REG_NOERROR.

Referenced by check_arrival(), and expand_bkref_cache().

02895 {
02896   reg_errcode_t err;
02897   int idx, outside_node;
02898   re_node_set new_nodes;
02899 #ifdef DEBUG
02900   assert (cur_nodes->nelem);
02901 #endif
02902   err = re_node_set_alloc (&new_nodes, cur_nodes->nelem);
02903   if (BE (err != REG_NOERROR, 0))
02904     return err;
02905   /* Create a new node set NEW_NODES with the nodes which are epsilon
02906      closures of the node in CUR_NODES.  */
02907 
02908   for (idx = 0; idx < cur_nodes->nelem; ++idx)
02909     {
02910       int cur_node = cur_nodes->elems[idx];
02911       re_node_set *eclosure = dfa->eclosures + cur_node;
02912       outside_node = find_subexp_node (dfa, eclosure, ex_subexp, fl_open);
02913       if (outside_node == -1)
02914         {
02915           /* There are no problematic nodes, just merge them.  */
02916           err = re_node_set_merge (&new_nodes, eclosure);
02917           if (BE (err != REG_NOERROR, 0))
02918             {
02919               re_node_set_free (&new_nodes);
02920               return err;
02921             }
02922         }
02923       else
02924         {
02925           /* There are problematic nodes, re-calculate incrementally.  */
02926           err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node,
02927                                               ex_subexp, fl_open);
02928           if (BE (err != REG_NOERROR, 0))
02929             {
02930               re_node_set_free (&new_nodes);
02931               return err;
02932             }
02933         }
02934     }
02935   re_node_set_free (cur_nodes);
02936   *cur_nodes = new_nodes;
02937   return REG_NOERROR;
02938 }

static reg_errcode_t check_arrival_expand_ecl_sub re_dfa_t dfa,
re_node_set dst_nodes,
int  target,
int  ex_subexp,
int  fl_open
[static]
 

Definition at line 2945 of file regexec.c.

References BE, re_dfa_t::nodes, OP_CLOSE_SUBEXP, OP_OPEN_SUBEXP, re_node_set_contains(), re_node_set_insert(), REG_ESPACE, REG_NOERROR, and re_token_t::type.

Referenced by check_arrival_expand_ecl().

02949 {
02950   int cur_node, type;
02951   for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);)
02952     {
02953       int err;
02954       type = dfa->nodes[cur_node].type;
02955 
02956       if (((type == OP_OPEN_SUBEXP && fl_open)
02957            || (type == OP_CLOSE_SUBEXP && !fl_open))
02958           && dfa->nodes[cur_node].opr.idx == ex_subexp)
02959         {
02960           if (!fl_open)
02961             {
02962               err = re_node_set_insert (dst_nodes, cur_node);
02963               if (BE (err == -1, 0))
02964                 return REG_ESPACE;
02965             }
02966           break;
02967         }
02968       err = re_node_set_insert (dst_nodes, cur_node);
02969       if (BE (err == -1, 0))
02970         return REG_ESPACE;
02971       if (dfa->edests[cur_node].nelem == 0)
02972         break;
02973       if (dfa->edests[cur_node].nelem == 2)
02974         {
02975           err = check_arrival_expand_ecl_sub (dfa, dst_nodes,
02976                                               dfa->edests[cur_node].elems[1],
02977                                               ex_subexp, fl_open);
02978           if (BE (err != REG_NOERROR, 0))
02979             return err;
02980         }
02981       cur_node = dfa->edests[cur_node].elems[0];
02982     }
02983   return REG_NOERROR;
02984 }

static int check_dst_limits re_dfa_t dfa,
re_node_set limits,
re_match_context_t mctx,
int  dst_node,
int  dst_idx,
int  src_node,
int  src_idx
[static]
 

Definition at line 1699 of file regexec.c.

References re_match_context_t::bkref_ents, check_dst_limits_calc_pos(), re_node_set::elems, and re_backref_cache_entry::node.

Referenced by sift_states_backward(), and sift_states_bkref().

01704 {
01705   int lim_idx, src_pos, dst_pos;
01706 
01707   for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
01708     {
01709       int subexp_idx;
01710       struct re_backref_cache_entry *ent;
01711       ent = mctx->bkref_ents + limits->elems[lim_idx];
01712       subexp_idx = dfa->nodes[ent->node].opr.idx - 1;
01713 
01714       dst_pos = check_dst_limits_calc_pos (dfa, mctx, limits->elems[lim_idx],
01715                                            dfa->eclosures + dst_node,
01716                                            subexp_idx, dst_node, dst_idx);
01717       src_pos = check_dst_limits_calc_pos (dfa, mctx, limits->elems[lim_idx],
01718                                            dfa->eclosures + src_node,
01719                                            subexp_idx, src_node, src_idx);
01720 
01721       /* In case of:
01722          <src> <dst> ( <subexp> )
01723          ( <subexp> ) <src> <dst>
01724          ( <subexp1> <src> <subexp2> <dst> <subexp3> )  */
01725       if (src_pos == dst_pos)
01726         continue; /* This is unrelated limitation.  */
01727       else
01728         return 1;
01729     }
01730   return 0;
01731 }

static int check_dst_limits_calc_pos re_dfa_t dfa,
re_match_context_t mctx,
int  limit,
re_node_set eclosures,
int  subexp_idx,
int  node,
int  str_idx
[static]
 

Definition at line 1734 of file regexec.c.

References re_match_context_t::bkref_ents, re_node_set::elems, re_node_set::nelem, re_backref_cache_entry::node, OP_BACK_REF, OP_CLOSE_SUBEXP, OP_OPEN_SUBEXP, search_cur_bkref_entry(), re_backref_cache_entry::str_idx, re_backref_cache_entry::subexp_from, and re_backref_cache_entry::subexp_to.

Referenced by check_dst_limits().

01740 {
01741