Blame deps/regex/regexec.c

Packit Service 20376f
/* Extended regular expression matching and search library.
Packit Service 20376f
   Copyright (C) 2002-2005, 2007, 2009, 2010 Free Software Foundation, Inc.
Packit Service 20376f
   This file is part of the GNU C Library.
Packit Service 20376f
   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
Packit Service 20376f
Packit Service 20376f
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 20376f
   modify it under the terms of the GNU Lesser General Public
Packit Service 20376f
   License as published by the Free Software Foundation; either
Packit Service 20376f
   version 2.1 of the License, or (at your option) any later version.
Packit Service 20376f
Packit Service 20376f
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 20376f
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 20376f
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 20376f
   Lesser General Public License for more details.
Packit Service 20376f
Packit Service 20376f
   You should have received a copy of the GNU Lesser General Public
Packit Service 20376f
   License along with the GNU C Library; if not, write to the Free
Packit Service 20376f
   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
Packit Service 20376f
   02110-1301 USA.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags,
Packit Service 20376f
				     int n) internal_function;
Packit Service 20376f
static void match_ctx_clean (re_match_context_t *mctx) internal_function;
Packit Service 20376f
static void match_ctx_free (re_match_context_t *cache) internal_function;
Packit Service 20376f
static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, int node,
Packit Service 20376f
					  int str_idx, int from, int to)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static int search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, int node,
Packit Service 20376f
					   int str_idx) internal_function;
Packit Service 20376f
static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop,
Packit Service 20376f
						   int node, int str_idx)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts,
Packit Service 20376f
			   re_dfastate_t **limited_sts, int last_node,
Packit Service 20376f
			   int last_str_idx)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static reg_errcode_t re_search_internal (const regex_t *preg,
Packit Service 20376f
					 const char *string, int length,
Packit Service 20376f
					 int start, int range, int stop,
Packit Service 20376f
					 size_t nmatch, regmatch_t pmatch[],
Packit Service 20376f
					 int eflags);
Packit Service 20376f
static int re_search_2_stub (struct re_pattern_buffer *bufp,
Packit Service 20376f
			     const char *string1, int length1,
Packit Service 20376f
			     const char *string2, int length2,
Packit Service 20376f
			     int start, int range, struct re_registers *regs,
Packit Service 20376f
			     int stop, int ret_len);
Packit Service 20376f
static int re_search_stub (struct re_pattern_buffer *bufp,
Packit Service 20376f
			   const char *string, int length, int start,
Packit Service 20376f
			   int range, int stop, struct re_registers *regs,
Packit Service 20376f
			   int ret_len);
Packit Service 20376f
static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch,
Packit Service 20376f
			      unsigned int nregs, int regs_allocated);
Packit Service 20376f
static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx);
Packit Service 20376f
static int check_matching (re_match_context_t *mctx, int fl_longest_match,
Packit Service 20376f
			   int *p_match_first) internal_function;
Packit Service 20376f
static int check_halt_state_context (const re_match_context_t *mctx,
Packit Service 20376f
				     const re_dfastate_t *state, int idx)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
Packit Service 20376f
			 regmatch_t *prev_idx_match, int cur_node,
Packit Service 20376f
			 int cur_idx, int nmatch) internal_function;
Packit Service 20376f
static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs,
Packit Service 20376f
				      int str_idx, int dest_node, int nregs,
Packit Service 20376f
				      regmatch_t *regs,
Packit Service 20376f
				      re_node_set *eps_via_nodes)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static reg_errcode_t set_regs (const regex_t *preg,
Packit Service 20376f
			       const re_match_context_t *mctx,
Packit Service 20376f
			       size_t nmatch, regmatch_t *pmatch,
Packit Service 20376f
			       int fl_backtrack) internal_function;
Packit Service 20376f
static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs)
Packit Service 20376f
     internal_function;
Packit Service 20376f
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
static int sift_states_iter_mb (const re_match_context_t *mctx,
Packit Service 20376f
				re_sift_context_t *sctx,
Packit Service 20376f
				int node_idx, int str_idx, int max_str_idx)
Packit Service 20376f
     internal_function;
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
static reg_errcode_t sift_states_backward (const re_match_context_t *mctx,
Packit Service 20376f
					   re_sift_context_t *sctx)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static reg_errcode_t build_sifted_states (const re_match_context_t *mctx,
Packit Service 20376f
					  re_sift_context_t *sctx, int str_idx,
Packit Service 20376f
					  re_node_set *cur_dest)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx,
Packit Service 20376f
					      re_sift_context_t *sctx,
Packit Service 20376f
					      int str_idx,
Packit Service 20376f
					      re_node_set *dest_nodes)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa,
Packit Service 20376f
					    re_node_set *dest_nodes,
Packit Service 20376f
					    const re_node_set *candidates)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static int check_dst_limits (const re_match_context_t *mctx,
Packit Service 20376f
			     re_node_set *limits,
Packit Service 20376f
			     int dst_node, int dst_idx, int src_node,
Packit Service 20376f
			     int src_idx) internal_function;
Packit Service 20376f
static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx,
Packit Service 20376f
					int boundaries, int subexp_idx,
Packit Service 20376f
					int from_node, int bkref_idx)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static int check_dst_limits_calc_pos (const re_match_context_t *mctx,
Packit Service 20376f
				      int limit, int subexp_idx,
Packit Service 20376f
				      int node, int str_idx,
Packit Service 20376f
				      int bkref_idx) internal_function;
Packit Service 20376f
static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa,
Packit Service 20376f
					  re_node_set *dest_nodes,
Packit Service 20376f
					  const re_node_set *candidates,
Packit Service 20376f
					  re_node_set *limits,
Packit Service 20376f
					  struct re_backref_cache_entry *bkref_ents,
Packit Service 20376f
					  int str_idx) internal_function;
Packit Service 20376f
static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx,
Packit Service 20376f
					re_sift_context_t *sctx,
Packit Service 20376f
					int str_idx, const re_node_set *candidates)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static reg_errcode_t merge_state_array (const re_dfa_t *dfa,
Packit Service 20376f
					re_dfastate_t **dst,
Packit Service 20376f
					re_dfastate_t **src, int num)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static re_dfastate_t *find_recover_state (reg_errcode_t *err,
Packit Service 20376f
					 re_match_context_t *mctx) internal_function;
Packit Service 20376f
static re_dfastate_t *transit_state (reg_errcode_t *err,
Packit Service 20376f
				     re_match_context_t *mctx,
Packit Service 20376f
				     re_dfastate_t *state) internal_function;
Packit Service 20376f
static re_dfastate_t *merge_state_with_log (reg_errcode_t *err,
Packit Service 20376f
					    re_match_context_t *mctx,
Packit Service 20376f
					    re_dfastate_t *next_state)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx,
Packit Service 20376f
						re_node_set *cur_nodes,
Packit Service 20376f
						int str_idx) internal_function;
Packit Service 20376f
#if 0
Packit Service 20376f
static re_dfastate_t *transit_state_sb (reg_errcode_t *err,
Packit Service 20376f
					re_match_context_t *mctx,
Packit Service 20376f
					re_dfastate_t *pstate)
Packit Service 20376f
     internal_function;
Packit Service 20376f
#endif
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
static reg_errcode_t transit_state_mb (re_match_context_t *mctx,
Packit Service 20376f
				       re_dfastate_t *pstate)
Packit Service 20376f
     internal_function;
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
static reg_errcode_t transit_state_bkref (re_match_context_t *mctx,
Packit Service 20376f
					  const re_node_set *nodes)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static reg_errcode_t get_subexp (re_match_context_t *mctx,
Packit Service 20376f
				 int bkref_node, int bkref_str_idx)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static reg_errcode_t get_subexp_sub (re_match_context_t *mctx,
Packit Service 20376f
				     const re_sub_match_top_t *sub_top,
Packit Service 20376f
				     re_sub_match_last_t *sub_last,
Packit Service 20376f
				     int bkref_node, int bkref_str)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static int find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,
Packit Service 20376f
			     int subexp_idx, int type) internal_function;
Packit Service 20376f
static reg_errcode_t check_arrival (re_match_context_t *mctx,
Packit Service 20376f
				    state_array_t *path, int top_node,
Packit Service 20376f
				    int top_str, int last_node, int last_str,
Packit Service 20376f
				    int type) internal_function;
Packit Service 20376f
static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx,
Packit Service 20376f
						   int str_idx,
Packit Service 20376f
						   re_node_set *cur_nodes,
Packit Service 20376f
						   re_node_set *next_nodes)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa,
Packit Service 20376f
					       re_node_set *cur_nodes,
Packit Service 20376f
					       int ex_subexp, int type)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa,
Packit Service 20376f
						   re_node_set *dst_nodes,
Packit Service 20376f
						   int target, int ex_subexp,
Packit Service 20376f
						   int type) internal_function;
Packit Service 20376f
static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx,
Packit Service 20376f
					 re_node_set *cur_nodes, int cur_str,
Packit Service 20376f
					 int subexp_num, int type)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static int build_trtable (const re_dfa_t *dfa,
Packit Service 20376f
			  re_dfastate_t *state) internal_function;
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
static int check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,
Packit Service 20376f
				    const re_string_t *input, int idx)
Packit Service 20376f
     internal_function;
Packit Service 20376f
# ifdef _LIBC
Packit Service 20376f
static unsigned int find_collation_sequence_value (const unsigned char *mbs,
Packit Service 20376f
						   size_t name_len)
Packit Service 20376f
     internal_function;
Packit Service 20376f
# endif /* _LIBC */
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
static int group_nodes_into_DFAstates (const re_dfa_t *dfa,
Packit Service 20376f
				       const re_dfastate_t *state,
Packit Service 20376f
				       re_node_set *states_node,
Packit Service 20376f
				       bitset_t *states_ch) internal_function;
Packit Service 20376f
static int check_node_accept (const re_match_context_t *mctx,
Packit Service 20376f
			      const re_token_t *node, int idx)
Packit Service 20376f
     internal_function;
Packit Service 20376f
static reg_errcode_t extend_buffers (re_match_context_t *mctx)
Packit Service 20376f
     internal_function;
Packit Service 20376f

Packit Service 20376f
/* Entry point for POSIX code.  */
Packit Service 20376f
Packit Service 20376f
/* regexec searches for a given pattern, specified by PREG, in the
Packit Service 20376f
   string STRING.
Packit Service 20376f
Packit Service 20376f
   If NMATCH is zero or REG_NOSUB was set in the cflags argument to
Packit Service 20376f
   `regcomp', we ignore PMATCH.  Otherwise, we assume PMATCH has at
Packit Service 20376f
   least NMATCH elements, and we set them to the offsets of the
Packit Service 20376f
   corresponding matched substrings.
Packit Service 20376f
Packit Service 20376f
   EFLAGS specifies `execution flags' which affect matching: if
Packit Service 20376f
   REG_NOTBOL is set, then ^ does not match at the beginning of the
Packit Service 20376f
   string; if REG_NOTEOL is set, then $ does not match at the end.
Packit Service 20376f
Packit Service 20376f
   We return 0 if we find a match and REG_NOMATCH if not.  */
Packit Service 20376f
Packit Service 20376f
int
Packit Service 20376f
regexec (
Packit Service 20376f
	const regex_t *__restrict preg,
Packit Service 20376f
	const char *__restrict string,
Packit Service 20376f
	size_t nmatch,
Packit Service 20376f
	regmatch_t pmatch[],
Packit Service 20376f
	int eflags)
Packit Service 20376f
{
Packit Service 20376f
  reg_errcode_t err;
Packit Service 20376f
  int start, length;
Packit Service 20376f
Packit Service 20376f
  if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND))
Packit Service 20376f
    return REG_BADPAT;
Packit Service 20376f
Packit Service 20376f
  if (eflags & REG_STARTEND)
Packit Service 20376f
    {
Packit Service 20376f
      start = pmatch[0].rm_so;
Packit Service 20376f
      length = pmatch[0].rm_eo;
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
    {
Packit Service 20376f
      start = 0;
Packit Service 20376f
      length = strlen (string);
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  __libc_lock_lock (dfa->lock);
Packit Service 20376f
  if (preg->no_sub)
Packit Service 20376f
    err = re_search_internal (preg, string, length, start, length - start,
Packit Service 20376f
			      length, 0, NULL, eflags);
Packit Service 20376f
  else
Packit Service 20376f
    err = re_search_internal (preg, string, length, start, length - start,
Packit Service 20376f
			      length, nmatch, pmatch, eflags);
Packit Service 20376f
  __libc_lock_unlock (dfa->lock);
Packit Service 20376f
  return err != REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
#ifdef _LIBC
Packit Service 20376f
# include <shlib-compat.h>
Packit Service 20376f
versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4);
Packit Service 20376f
Packit Service 20376f
# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
Packit Service 20376f
__typeof__ (__regexec) __compat_regexec;
Packit Service 20376f
Packit Service 20376f
int
Packit Service 20376f
attribute_compat_text_section
Packit Service 20376f
__compat_regexec (const regex_t *__restrict preg,
Packit Service 20376f
		  const char *__restrict string, size_t nmatch,
Packit Service 20376f
		  regmatch_t pmatch[], int eflags)
Packit Service 20376f
{
Packit Service 20376f
  return regexec (preg, string, nmatch, pmatch,
Packit Service 20376f
		  eflags & (REG_NOTBOL | REG_NOTEOL));
Packit Service 20376f
}
Packit Service 20376f
compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0);
Packit Service 20376f
# endif
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
/* Entry points for GNU code.  */
Packit Service 20376f
Packit Service 20376f
/* re_match, re_search, re_match_2, re_search_2
Packit Service 20376f
Packit Service 20376f
   The former two functions operate on STRING with length LENGTH,
Packit Service 20376f
   while the later two operate on concatenation of STRING1 and STRING2
Packit Service 20376f
   with lengths LENGTH1 and LENGTH2, respectively.
Packit Service 20376f
Packit Service 20376f
   re_match() matches the compiled pattern in BUFP against the string,
Packit Service 20376f
   starting at index START.
Packit Service 20376f
Packit Service 20376f
   re_search() first tries matching at index START, then it tries to match
Packit Service 20376f
   starting from index START + 1, and so on.  The last start position tried
Packit Service 20376f
   is START + RANGE.  (Thus RANGE = 0 forces re_search to operate the same
Packit Service 20376f
   way as re_match().)
Packit Service 20376f
Packit Service 20376f
   The parameter STOP of re_{match,search}_2 specifies that no match exceeding
Packit Service 20376f
   the first STOP characters of the concatenation of the strings should be
Packit Service 20376f
   concerned.
Packit Service 20376f
Packit Service 20376f
   If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match
Packit Service 20376f
   and all groups is stroed in REGS.  (For the "_2" variants, the offsets are
Packit Service 20376f
   computed relative to the concatenation, not relative to the individual
Packit Service 20376f
   strings.)
Packit Service 20376f
Packit Service 20376f
   On success, re_match* functions return the length of the match, re_search*
Packit Service 20376f
   return the position of the start of the match.  Return value -1 means no
Packit Service 20376f
   match was found and -2 indicates an internal error.  */
Packit Service 20376f
Packit Service 20376f
int
Packit Service 20376f
re_match (struct re_pattern_buffer *bufp,
Packit Service 20376f
	  const char *string,
Packit Service 20376f
	  int length,
Packit Service 20376f
	  int start,
Packit Service 20376f
	  struct re_registers *regs)
Packit Service 20376f
{
Packit Service 20376f
  return re_search_stub (bufp, string, length, start, 0, length, regs, 1);
Packit Service 20376f
}
Packit Service 20376f
#ifdef _LIBC
Packit Service 20376f
weak_alias (__re_match, re_match)
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
int
Packit Service 20376f
re_search (struct re_pattern_buffer *bufp,
Packit Service 20376f
	   const char *string,
Packit Service 20376f
	   int length, int start, int range,
Packit Service 20376f
	   struct re_registers *regs)
Packit Service 20376f
{
Packit Service 20376f
  return re_search_stub (bufp, string, length, start, range, length, regs, 0);
Packit Service 20376f
}
Packit Service 20376f
#ifdef _LIBC
Packit Service 20376f
weak_alias (__re_search, re_search)
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
int
Packit Service 20376f
re_match_2 (struct re_pattern_buffer *bufp,
Packit Service 20376f
	    const char *string1, int length1,
Packit Service 20376f
	    const char *string2, int length2, int start,
Packit Service 20376f
	    struct re_registers *regs, int stop)
Packit Service 20376f
{
Packit Service 20376f
  return re_search_2_stub (bufp, string1, length1, string2, length2,
Packit Service 20376f
			   start, 0, regs, stop, 1);
Packit Service 20376f
}
Packit Service 20376f
#ifdef _LIBC
Packit Service 20376f
weak_alias (__re_match_2, re_match_2)
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
int
Packit Service 20376f
re_search_2 (struct re_pattern_buffer *bufp,
Packit Service 20376f
	     const char *string1, int length1,
Packit Service 20376f
	     const char *string2, int length2, int start,
Packit Service 20376f
	     int range, struct re_registers *regs,  int stop)
Packit Service 20376f
{
Packit Service 20376f
  return re_search_2_stub (bufp, string1, length1, string2, length2,
Packit Service 20376f
			   start, range, regs, stop, 0);
Packit Service 20376f
}
Packit Service 20376f
#ifdef _LIBC
Packit Service 20376f
weak_alias (__re_search_2, re_search_2)
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
static int
Packit Service 20376f
re_search_2_stub (struct re_pattern_buffer *bufp,
Packit Service 20376f
		  const char *string1, int length1,
Packit Service 20376f
		  const char *string2, int length2, int start,
Packit Service 20376f
		  int range, struct re_registers *regs,
Packit Service 20376f
		  int stop, int ret_len)
Packit Service 20376f
{
Packit Service 20376f
  const char *str;
Packit Service 20376f
  int rval;
Packit Service 20376f
  int len = length1 + length2;
Packit Service 20376f
  int free_str = 0;
Packit Service 20376f
Packit Service 20376f
  if (BE (length1 < 0 || length2 < 0 || stop < 0, 0))
Packit Service 20376f
    return -2;
Packit Service 20376f
Packit Service 20376f
  /* Concatenate the strings.  */
Packit Service 20376f
  if (length2 > 0)
Packit Service 20376f
    if (length1 > 0)
Packit Service 20376f
      {
Packit Service 20376f
	char *s = re_malloc (char, len);
Packit Service 20376f
Packit Service 20376f
	if (BE (s == NULL, 0))
Packit Service 20376f
	  return -2;
Packit Service 20376f
	memcpy (s, string1, length1);
Packit Service 20376f
	memcpy (s + length1, string2, length2);
Packit Service 20376f
	str = s;
Packit Service 20376f
	free_str = 1;
Packit Service 20376f
      }
Packit Service 20376f
    else
Packit Service 20376f
      str = string2;
Packit Service 20376f
  else
Packit Service 20376f
    str = string1;
Packit Service 20376f
Packit Service 20376f
  rval = re_search_stub (bufp, str, len, start, range, stop, regs, ret_len);
Packit Service 20376f
  if (free_str)
Packit Service 20376f
    re_free ((char *) str);
Packit Service 20376f
  return rval;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* The parameters have the same meaning as those of re_search.
Packit Service 20376f
   Additional parameters:
Packit Service 20376f
   If RET_LEN is nonzero the length of the match is returned (re_match style);
Packit Service 20376f
   otherwise the position of the match is returned.  */
Packit Service 20376f
Packit Service 20376f
static int
Packit Service 20376f
re_search_stub (struct re_pattern_buffer *bufp,
Packit Service 20376f
		const char *string, int length, int start,
Packit Service 20376f
		int range, int stop,
Packit Service 20376f
		struct re_registers *regs, int ret_len)
Packit Service 20376f
{
Packit Service 20376f
  reg_errcode_t result;
Packit Service 20376f
  regmatch_t *pmatch;
Packit Service 20376f
  int nregs, rval;
Packit Service 20376f
  int eflags = 0;
Packit Service 20376f
Packit Service 20376f
  /* Check for out-of-range.  */
Packit Service 20376f
  if (BE (start < 0 || start > length, 0))
Packit Service 20376f
    return -1;
Packit Service 20376f
  if (BE (start + range > length, 0))
Packit Service 20376f
    range = length - start;
Packit Service 20376f
  else if (BE (start + range < 0, 0))
Packit Service 20376f
    range = -start;
Packit Service 20376f
Packit Service 20376f
  __libc_lock_lock (dfa->lock);
Packit Service 20376f
Packit Service 20376f
  eflags |= (bufp->not_bol) ? REG_NOTBOL : 0;
Packit Service 20376f
  eflags |= (bufp->not_eol) ? REG_NOTEOL : 0;
Packit Service 20376f
Packit Service 20376f
  /* Compile fastmap if we haven't yet.  */
Packit Service 20376f
  if (range > 0 && bufp->fastmap != NULL && !bufp->fastmap_accurate)
Packit Service 20376f
    re_compile_fastmap (bufp);
Packit Service 20376f
Packit Service 20376f
  if (BE (bufp->no_sub, 0))
Packit Service 20376f
    regs = NULL;
Packit Service 20376f
Packit Service 20376f
  /* We need at least 1 register.  */
Packit Service 20376f
  if (regs == NULL)
Packit Service 20376f
    nregs = 1;
Packit Service 20376f
  else if (BE (bufp->regs_allocated == REGS_FIXED &&
Packit Service 20376f
	       regs->num_regs < bufp->re_nsub + 1, 0))
Packit Service 20376f
    {
Packit Service 20376f
      nregs = regs->num_regs;
Packit Service 20376f
      if (BE (nregs < 1, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  /* Nothing can be copied to regs.  */
Packit Service 20376f
	  regs = NULL;
Packit Service 20376f
	  nregs = 1;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
    nregs = bufp->re_nsub + 1;
Packit Service 20376f
  pmatch = re_malloc (regmatch_t, nregs);
Packit Service 20376f
  if (BE (pmatch == NULL, 0))
Packit Service 20376f
    {
Packit Service 20376f
      rval = -2;
Packit Service 20376f
      goto out;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  result = re_search_internal (bufp, string, length, start, range, stop,
Packit Service 20376f
			       nregs, pmatch, eflags);
Packit Service 20376f
Packit Service 20376f
  rval = 0;
Packit Service 20376f
Packit Service 20376f
  /* I hope we needn't fill ther regs with -1's when no match was found.  */
Packit Service 20376f
  if (result != REG_NOERROR)
Packit Service 20376f
    rval = -1;
Packit Service 20376f
  else if (regs != NULL)
Packit Service 20376f
    {
Packit Service 20376f
      /* If caller wants register contents data back, copy them.  */
Packit Service 20376f
      bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs,
Packit Service 20376f
					   bufp->regs_allocated);
Packit Service 20376f
      if (BE (bufp->regs_allocated == REGS_UNALLOCATED, 0))
Packit Service 20376f
	rval = -2;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  if (BE (rval == 0, 1))
Packit Service 20376f
    {
Packit Service 20376f
      if (ret_len)
Packit Service 20376f
	{
Packit Service 20376f
	  assert (pmatch[0].rm_so == start);
Packit Service 20376f
	  rval = pmatch[0].rm_eo - start;
Packit Service 20376f
	}
Packit Service 20376f
      else
Packit Service 20376f
	rval = pmatch[0].rm_so;
Packit Service 20376f
    }
Packit Service 20376f
  re_free (pmatch);
Packit Service 20376f
 out:
Packit Service 20376f
  __libc_lock_unlock (dfa->lock);
Packit Service 20376f
  return rval;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static unsigned
Packit Service 20376f
re_copy_regs (struct re_registers *regs,
Packit Service 20376f
	      regmatch_t *pmatch,
Packit Service 20376f
	      unsigned int nregs, int regs_allocated)
Packit Service 20376f
{
Packit Service 20376f
  int rval = REGS_REALLOCATE;
Packit Service 20376f
  unsigned int i;
Packit Service 20376f
  unsigned int need_regs = nregs + 1;
Packit Service 20376f
  /* We need one extra element beyond `num_regs' for the `-1' marker GNU code
Packit Service 20376f
     uses.  */
Packit Service 20376f
Packit Service 20376f
  /* Have the register data arrays been allocated?  */
Packit Service 20376f
  if (regs_allocated == REGS_UNALLOCATED)
Packit Service 20376f
    { /* No.  So allocate them with malloc.  */
Packit Service 20376f
      regs->start = re_malloc (regoff_t, need_regs);
Packit Service 20376f
      if (BE (regs->start == NULL, 0))
Packit Service 20376f
	return REGS_UNALLOCATED;
Packit Service 20376f
      regs->end = re_malloc (regoff_t, need_regs);
Packit Service 20376f
      if (BE (regs->end == NULL, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  re_free (regs->start);
Packit Service 20376f
	  return REGS_UNALLOCATED;
Packit Service 20376f
	}
Packit Service 20376f
      regs->num_regs = need_regs;
Packit Service 20376f
    }
Packit Service 20376f
  else if (regs_allocated == REGS_REALLOCATE)
Packit Service 20376f
    { /* Yes.  If we need more elements than were already
Packit Service 20376f
	 allocated, reallocate them.  If we need fewer, just
Packit Service 20376f
	 leave it alone.  */
Packit Service 20376f
      if (BE (need_regs > regs->num_regs, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs);
Packit Service 20376f
	  regoff_t *new_end;
Packit Service 20376f
	  if (BE (new_start == NULL, 0))
Packit Service 20376f
	    return REGS_UNALLOCATED;
Packit Service 20376f
	  new_end = re_realloc (regs->end, regoff_t, need_regs);
Packit Service 20376f
	  if (BE (new_end == NULL, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      re_free (new_start);
Packit Service 20376f
	      return REGS_UNALLOCATED;
Packit Service 20376f
	    }
Packit Service 20376f
	  regs->start = new_start;
Packit Service 20376f
	  regs->end = new_end;
Packit Service 20376f
	  regs->num_regs = need_regs;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
    {
Packit Service 20376f
      assert (regs_allocated == REGS_FIXED);
Packit Service 20376f
      /* This function may not be called with REGS_FIXED and nregs too big.  */
Packit Service 20376f
      assert (regs->num_regs >= nregs);
Packit Service 20376f
      rval = REGS_FIXED;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  /* Copy the regs.  */
Packit Service 20376f
  for (i = 0; i < nregs; ++i)
Packit Service 20376f
    {
Packit Service 20376f
      regs->start[i] = pmatch[i].rm_so;
Packit Service 20376f
      regs->end[i] = pmatch[i].rm_eo;
Packit Service 20376f
    }
Packit Service 20376f
  for ( ; i < regs->num_regs; ++i)
Packit Service 20376f
    regs->start[i] = regs->end[i] = -1;
Packit Service 20376f
Packit Service 20376f
  return rval;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Set REGS to hold NUM_REGS registers, storing them in STARTS and
Packit Service 20376f
   ENDS.  Subsequent matches using PATTERN_BUFFER and REGS will use
Packit Service 20376f
   this memory for recording register information.  STARTS and ENDS
Packit Service 20376f
   must be allocated using the malloc library routine, and must each
Packit Service 20376f
   be at least NUM_REGS * sizeof (regoff_t) bytes long.
Packit Service 20376f
Packit Service 20376f
   If NUM_REGS == 0, then subsequent matches should allocate their own
Packit Service 20376f
   register data.
Packit Service 20376f
Packit Service 20376f
   Unless this function is called, the first search or match using
Packit Service 20376f
   PATTERN_BUFFER will allocate its own register data, without
Packit Service 20376f
   freeing the old data.  */
Packit Service 20376f
Packit Service 20376f
void
Packit Service 20376f
re_set_registers (struct re_pattern_buffer *bufp,
Packit Service 20376f
		  struct re_registers *regs,
Packit Service 20376f
		  unsigned num_regs,
Packit Service 20376f
		  regoff_t *starts,
Packit Service 20376f
		  regoff_t *ends)
Packit Service 20376f
{
Packit Service 20376f
  if (num_regs)
Packit Service 20376f
    {
Packit Service 20376f
      bufp->regs_allocated = REGS_REALLOCATE;
Packit Service 20376f
      regs->num_regs = num_regs;
Packit Service 20376f
      regs->start = starts;
Packit Service 20376f
      regs->end = ends;
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
    {
Packit Service 20376f
      bufp->regs_allocated = REGS_UNALLOCATED;
Packit Service 20376f
      regs->num_regs = 0;
Packit Service 20376f
      regs->start = regs->end = (regoff_t *) 0;
Packit Service 20376f
    }
Packit Service 20376f
}
Packit Service 20376f
#ifdef _LIBC
Packit Service 20376f
weak_alias (__re_set_registers, re_set_registers)
Packit Service 20376f
#endif
Packit Service 20376f

Packit Service 20376f
/* Entry points compatible with 4.2 BSD regex library.  We don't define
Packit Service 20376f
   them unless specifically requested.  */
Packit Service 20376f
Packit Service 20376f
#if defined _REGEX_RE_COMP || defined _LIBC
Packit Service 20376f
int
Packit Service 20376f
# ifdef _LIBC
Packit Service 20376f
weak_function
Packit Service 20376f
# endif
Packit Service 20376f
re_exec (s)
Packit Service 20376f
     const char *s;
Packit Service 20376f
{
Packit Service 20376f
  return 0 == regexec (&re_comp_buf, s, 0, NULL, 0);
Packit Service 20376f
}
Packit Service 20376f
#endif /* _REGEX_RE_COMP */
Packit Service 20376f

Packit Service 20376f
/* Internal entry point.  */
Packit Service 20376f
Packit Service 20376f
/* Searches for a compiled pattern PREG in the string STRING, whose
Packit Service 20376f
   length is LENGTH.  NMATCH, PMATCH, and EFLAGS have the same
Packit Service 20376f
   mingings with regexec.  START, and RANGE have the same meanings
Packit Service 20376f
   with re_search.
Packit Service 20376f
   Return REG_NOERROR if we find a match, and REG_NOMATCH if not,
Packit Service 20376f
   otherwise return the error code.
Packit Service 20376f
   Note: We assume front end functions already check ranges.
Packit Service 20376f
   (START + RANGE >= 0 && START + RANGE <= LENGTH)  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
re_search_internal (const regex_t *preg,
Packit Service 20376f
		    const char *string,
Packit Service 20376f
		    int length, int start, int range, int stop,
Packit Service 20376f
		    size_t nmatch, regmatch_t pmatch[],
Packit Service 20376f
		    int eflags)
Packit Service 20376f
{
Packit Service 20376f
  reg_errcode_t err;
Packit Service 20376f
  const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer;
Packit Service 20376f
  int left_lim, right_lim, incr;
Packit Service 20376f
  int fl_longest_match, match_first, match_kind, match_last = -1;
Packit Service 20376f
  unsigned int extra_nmatch;
Packit Service 20376f
  int sb, ch;
Packit Service 20376f
#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
Packit Service 20376f
  re_match_context_t mctx = { .dfa = dfa };
Packit Service 20376f
#else
Packit Service 20376f
  re_match_context_t mctx;
Packit Service 20376f
#endif
Packit Service 20376f
  char *fastmap = (preg->fastmap != NULL && preg->fastmap_accurate
Packit Service 20376f
		   && range && !preg->can_be_null) ? preg->fastmap : NULL;
Packit Service 20376f
  RE_TRANSLATE_TYPE t = preg->translate;
Packit Service 20376f
Packit Service 20376f
#if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L))
Packit Service 20376f
  memset (&mctx, '\0', sizeof (re_match_context_t));
Packit Service 20376f
  mctx.dfa = dfa;
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
  extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0;
Packit Service 20376f
  nmatch -= extra_nmatch;
Packit Service 20376f
Packit Service 20376f
  /* Check if the DFA haven't been compiled.  */
Packit Service 20376f
  if (BE (preg->used == 0 || dfa->init_state == NULL
Packit Service 20376f
	  || dfa->init_state_word == NULL || dfa->init_state_nl == NULL
Packit Service 20376f
	  || dfa->init_state_begbuf == NULL, 0))
Packit Service 20376f
    return REG_NOMATCH;
Packit Service 20376f
Packit Service 20376f
#ifdef DEBUG
Packit Service 20376f
  /* We assume front-end functions already check them.  */
Packit Service 20376f
  assert (start + range >= 0 && start + range <= length);
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
  /* If initial states with non-begbuf contexts have no elements,
Packit Service 20376f
     the regex must be anchored.  If preg->newline_anchor is set,
Packit Service 20376f
     we'll never use init_state_nl, so do not check it.  */
Packit Service 20376f
  if (dfa->init_state->nodes.nelem == 0
Packit Service 20376f
      && dfa->init_state_word->nodes.nelem == 0
Packit Service 20376f
      && (dfa->init_state_nl->nodes.nelem == 0
Packit Service 20376f
	  || !preg->newline_anchor))
Packit Service 20376f
    {
Packit Service 20376f
      if (start != 0 && start + range != 0)
Packit Service 20376f
	return REG_NOMATCH;
Packit Service 20376f
      start = range = 0;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  /* We must check the longest matching, if nmatch > 0.  */
Packit Service 20376f
  fl_longest_match = (nmatch != 0 || dfa->nbackref);
Packit Service 20376f
Packit Service 20376f
  err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1,
Packit Service 20376f
			    preg->translate, preg->syntax & RE_ICASE, dfa);
Packit Service 20376f
  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
    goto free_return;
Packit Service 20376f
  mctx.input.stop = stop;
Packit Service 20376f
  mctx.input.raw_stop = stop;
Packit Service 20376f
  mctx.input.newline_anchor = preg->newline_anchor;
Packit Service 20376f
Packit Service 20376f
  err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2);
Packit Service 20376f
  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
    goto free_return;
Packit Service 20376f
Packit Service 20376f
  /* We will log all the DFA states through which the dfa pass,
Packit Service 20376f
     if nmatch > 1, or this dfa has "multibyte node", which is a
Packit Service 20376f
     back-reference or a node which can accept multibyte character or
Packit Service 20376f
     multi character collating element.  */
Packit Service 20376f
  if (nmatch > 1 || dfa->has_mb_node)
Packit Service 20376f
    {
Packit Service 20376f
      /* Avoid overflow.  */
Packit Service 20376f
      if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= (size_t)mctx.input.bufs_len, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  err = REG_ESPACE;
Packit Service 20376f
	  goto free_return;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1);
Packit Service 20376f
      if (BE (mctx.state_log == NULL, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  err = REG_ESPACE;
Packit Service 20376f
	  goto free_return;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
    mctx.state_log = NULL;
Packit Service 20376f
Packit Service 20376f
  match_first = start;
Packit Service 20376f
  mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
Packit Service 20376f
			   : CONTEXT_NEWLINE | CONTEXT_BEGBUF;
Packit Service 20376f
Packit Service 20376f
  /* Check incrementally whether of not the input string match.  */
Packit Service 20376f
  incr = (range < 0) ? -1 : 1;
Packit Service 20376f
  left_lim = (range < 0) ? start + range : start;
Packit Service 20376f
  right_lim = (range < 0) ? start : start + range;
Packit Service 20376f
  sb = dfa->mb_cur_max == 1;
Packit Service 20376f
  match_kind =
Packit Service 20376f
    (fastmap
Packit Service 20376f
     ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0)
Packit Service 20376f
	| (range >= 0 ? 2 : 0)
Packit Service 20376f
	| (t != NULL ? 1 : 0))
Packit Service 20376f
     : 8);
Packit Service 20376f
Packit Service 20376f
  for (;; match_first += incr)
Packit Service 20376f
    {
Packit Service 20376f
      err = REG_NOMATCH;
Packit Service 20376f
      if (match_first < left_lim || right_lim < match_first)
Packit Service 20376f
	goto free_return;
Packit Service 20376f
Packit Service 20376f
      /* Advance as rapidly as possible through the string, until we
Packit Service 20376f
	 find a plausible place to start matching.  This may be done
Packit Service 20376f
	 with varying efficiency, so there are various possibilities:
Packit Service 20376f
	 only the most common of them are specialized, in order to
Packit Service 20376f
	 save on code size.  We use a switch statement for speed.  */
Packit Service 20376f
      switch (match_kind)
Packit Service 20376f
	{
Packit Service 20376f
	case 8:
Packit Service 20376f
	  /* No fastmap.  */
Packit Service 20376f
	  break;
Packit Service 20376f
Packit Service 20376f
	case 7:
Packit Service 20376f
	  /* Fastmap with single-byte translation, match forward.  */
Packit Service 20376f
	  while (BE (match_first < right_lim, 1)
Packit Service 20376f
		 && !fastmap[t[(unsigned char) string[match_first]]])
Packit Service 20376f
	    ++match_first;
Packit Service 20376f
	  goto forward_match_found_start_or_reached_end;
Packit Service 20376f
Packit Service 20376f
	case 6:
Packit Service 20376f
	  /* Fastmap without translation, match forward.  */
Packit Service 20376f
	  while (BE (match_first < right_lim, 1)
Packit Service 20376f
		 && !fastmap[(unsigned char) string[match_first]])
Packit Service 20376f
	    ++match_first;
Packit Service 20376f
Packit Service 20376f
	forward_match_found_start_or_reached_end:
Packit Service 20376f
	  if (BE (match_first == right_lim, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      ch = match_first >= length
Packit Service 20376f
		       ? 0 : (unsigned char) string[match_first];
Packit Service 20376f
	      if (!fastmap[t ? t[ch] : ch])
Packit Service 20376f
		goto free_return;
Packit Service 20376f
	    }
Packit Service 20376f
	  break;
Packit Service 20376f
Packit Service 20376f
	case 4:
Packit Service 20376f
	case 5:
Packit Service 20376f
	  /* Fastmap without multi-byte translation, match backwards.  */
Packit Service 20376f
	  while (match_first >= left_lim)
Packit Service 20376f
	    {
Packit Service 20376f
	      ch = match_first >= length
Packit Service 20376f
		       ? 0 : (unsigned char) string[match_first];
Packit Service 20376f
	      if (fastmap[t ? t[ch] : ch])
Packit Service 20376f
		break;
Packit Service 20376f
	      --match_first;
Packit Service 20376f
	    }
Packit Service 20376f
	  if (match_first < left_lim)
Packit Service 20376f
	    goto free_return;
Packit Service 20376f
	  break;
Packit Service 20376f
Packit Service 20376f
	default:
Packit Service 20376f
	  /* In this case, we can't determine easily the current byte,
Packit Service 20376f
	     since it might be a component byte of a multibyte
Packit Service 20376f
	     character.  Then we use the constructed buffer instead.  */
Packit Service 20376f
	  for (;;)
Packit Service 20376f
	    {
Packit Service 20376f
	      /* If MATCH_FIRST is out of the valid range, reconstruct the
Packit Service 20376f
		 buffers.  */
Packit Service 20376f
	      unsigned int offset = match_first - mctx.input.raw_mbs_idx;
Packit Service 20376f
	      if (BE (offset >= (unsigned int) mctx.input.valid_raw_len, 0))
Packit Service 20376f
		{
Packit Service 20376f
		  err = re_string_reconstruct (&mctx.input, match_first,
Packit Service 20376f
					       eflags);
Packit Service 20376f
		  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
		    goto free_return;
Packit Service 20376f
Packit Service 20376f
		  offset = match_first - mctx.input.raw_mbs_idx;
Packit Service 20376f
		}
Packit Service 20376f
	      /* If MATCH_FIRST is out of the buffer, leave it as '\0'.
Packit Service 20376f
		 Note that MATCH_FIRST must not be smaller than 0.  */
Packit Service 20376f
	      ch = (match_first >= length
Packit Service 20376f
		    ? 0 : re_string_byte_at (&mctx.input, offset));
Packit Service 20376f
	      if (fastmap[ch])
Packit Service 20376f
		break;
Packit Service 20376f
	      match_first += incr;
Packit Service 20376f
	      if (match_first < left_lim || match_first > right_lim)
Packit Service 20376f
		{
Packit Service 20376f
		  err = REG_NOMATCH;
Packit Service 20376f
		  goto free_return;
Packit Service 20376f
		}
Packit Service 20376f
	    }
Packit Service 20376f
	  break;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      /* Reconstruct the buffers so that the matcher can assume that
Packit Service 20376f
	 the matching starts from the beginning of the buffer.  */
Packit Service 20376f
      err = re_string_reconstruct (&mctx.input, match_first, eflags);
Packit Service 20376f
      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	goto free_return;
Packit Service 20376f
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
     /* Don't consider this char as a possible match start if it part,
Packit Service 20376f
	yet isn't the head, of a multibyte character.  */
Packit Service 20376f
      if (!sb && !re_string_first_byte (&mctx.input, 0))
Packit Service 20376f
	continue;
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
      /* It seems to be appropriate one, then use the matcher.  */
Packit Service 20376f
      /* We assume that the matching starts from 0.  */
Packit Service 20376f
      mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0;
Packit Service 20376f
      match_last = check_matching (&mctx, fl_longest_match,
Packit Service 20376f
				   range >= 0 ? &match_first : NULL);
Packit Service 20376f
      if (match_last != -1)
Packit Service 20376f
	{
Packit Service 20376f
	  if (BE (match_last == -2, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      err = REG_ESPACE;
Packit Service 20376f
	      goto free_return;
Packit Service 20376f
	    }
Packit Service 20376f
	  else
Packit Service 20376f
	    {
Packit Service 20376f
	      mctx.match_last = match_last;
Packit Service 20376f
	      if ((!preg->no_sub && nmatch > 1) || dfa->nbackref)
Packit Service 20376f
		{
Packit Service 20376f
		  re_dfastate_t *pstate = mctx.state_log[match_last];
Packit Service 20376f
		  mctx.last_node = check_halt_state_context (&mctx, pstate,
Packit Service 20376f
							     match_last);
Packit Service 20376f
		}
Packit Service 20376f
	      if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match)
Packit Service 20376f
		  || dfa->nbackref)
Packit Service 20376f
		{
Packit Service 20376f
		  err = prune_impossible_nodes (&mctx);
Packit Service 20376f
		  if (err == REG_NOERROR)
Packit Service 20376f
		    break;
Packit Service 20376f
		  if (BE (err != REG_NOMATCH, 0))
Packit Service 20376f
		    goto free_return;
Packit Service 20376f
		  match_last = -1;
Packit Service 20376f
		}
Packit Service 20376f
	      else
Packit Service 20376f
		break; /* We found a match.  */
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      match_ctx_clean (&mctx);
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
#ifdef DEBUG
Packit Service 20376f
  assert (match_last != -1);
Packit Service 20376f
  assert (err == REG_NOERROR);
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
  /* Set pmatch[] if we need.  */
Packit Service 20376f
  if (nmatch > 0)
Packit Service 20376f
    {
Packit Service 20376f
      unsigned int reg_idx;
Packit Service 20376f
Packit Service 20376f
      /* Initialize registers.  */
Packit Service 20376f
      for (reg_idx = 1; reg_idx < nmatch; ++reg_idx)
Packit Service 20376f
	pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1;
Packit Service 20376f
Packit Service 20376f
      /* Set the points where matching start/end.  */
Packit Service 20376f
      pmatch[0].rm_so = 0;
Packit Service 20376f
      pmatch[0].rm_eo = mctx.match_last;
Packit Service 20376f
Packit Service 20376f
      if (!preg->no_sub && nmatch > 1)
Packit Service 20376f
	{
Packit Service 20376f
	  err = set_regs (preg, &mctx, nmatch, pmatch,
Packit Service 20376f
			  dfa->has_plural_match && dfa->nbackref > 0);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    goto free_return;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      /* At last, add the offset to the each registers, since we slided
Packit Service 20376f
	 the buffers so that we could assume that the matching starts
Packit Service 20376f
	 from 0.  */
Packit Service 20376f
      for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
Packit Service 20376f
	if (pmatch[reg_idx].rm_so != -1)
Packit Service 20376f
	  {
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
	    if (BE (mctx.input.offsets_needed != 0, 0))
Packit Service 20376f
	      {
Packit Service 20376f
		pmatch[reg_idx].rm_so =
Packit Service 20376f
		  (pmatch[reg_idx].rm_so == mctx.input.valid_len
Packit Service 20376f
		   ? mctx.input.valid_raw_len
Packit Service 20376f
		   : mctx.input.offsets[pmatch[reg_idx].rm_so]);
Packit Service 20376f
		pmatch[reg_idx].rm_eo =
Packit Service 20376f
		  (pmatch[reg_idx].rm_eo == mctx.input.valid_len
Packit Service 20376f
		   ? mctx.input.valid_raw_len
Packit Service 20376f
		   : mctx.input.offsets[pmatch[reg_idx].rm_eo]);
Packit Service 20376f
	      }
Packit Service 20376f
#else
Packit Service 20376f
	    assert (mctx.input.offsets_needed == 0);
Packit Service 20376f
#endif
Packit Service 20376f
	    pmatch[reg_idx].rm_so += match_first;
Packit Service 20376f
	    pmatch[reg_idx].rm_eo += match_first;
Packit Service 20376f
	  }
Packit Service 20376f
      for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx)
Packit Service 20376f
	{
Packit Service 20376f
	  pmatch[nmatch + reg_idx].rm_so = -1;
Packit Service 20376f
	  pmatch[nmatch + reg_idx].rm_eo = -1;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      if (dfa->subexp_map)
Packit Service 20376f
	for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++)
Packit Service 20376f
	  if (dfa->subexp_map[reg_idx] != (int)reg_idx)
Packit Service 20376f
	    {
Packit Service 20376f
	      pmatch[reg_idx + 1].rm_so
Packit Service 20376f
		= pmatch[dfa->subexp_map[reg_idx] + 1].rm_so;
Packit Service 20376f
	      pmatch[reg_idx + 1].rm_eo
Packit Service 20376f
		= pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo;
Packit Service 20376f
	    }
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
 free_return:
Packit Service 20376f
  re_free (mctx.state_log);
Packit Service 20376f
  if (dfa->nbackref)
Packit Service 20376f
    match_ctx_free (&mctx);
Packit Service 20376f
  re_string_destruct (&mctx.input);
Packit Service 20376f
  return err;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
prune_impossible_nodes (re_match_context_t *mctx)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  int halt_node, match_last;
Packit Service 20376f
  reg_errcode_t ret;
Packit Service 20376f
  re_dfastate_t **sifted_states;
Packit Service 20376f
  re_dfastate_t **lim_states = NULL;
Packit Service 20376f
  re_sift_context_t sctx;
Packit Service 20376f
#ifdef DEBUG
Packit Service 20376f
  assert (mctx->state_log != NULL);
Packit Service 20376f
#endif
Packit Service 20376f
  match_last = mctx->match_last;
Packit Service 20376f
  halt_node = mctx->last_node;
Packit Service 20376f
Packit Service 20376f
  /* Avoid overflow.  */
Packit Service 20376f
  if (BE (SIZE_MAX / sizeof (re_dfastate_t *) <= (size_t)match_last, 0))
Packit Service 20376f
    return REG_ESPACE;
Packit Service 20376f
Packit Service 20376f
  sifted_states = re_malloc (re_dfastate_t *, match_last + 1);
Packit Service 20376f
  if (BE (sifted_states == NULL, 0))
Packit Service 20376f
    {
Packit Service 20376f
      ret = REG_ESPACE;
Packit Service 20376f
      goto free_return;
Packit Service 20376f
    }
Packit Service 20376f
  if (dfa->nbackref)
Packit Service 20376f
    {
Packit Service 20376f
      lim_states = re_malloc (re_dfastate_t *, match_last + 1);
Packit Service 20376f
      if (BE (lim_states == NULL, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  ret = REG_ESPACE;
Packit Service 20376f
	  goto free_return;
Packit Service 20376f
	}
Packit Service 20376f
      while (1)
Packit Service 20376f
	{
Packit Service 20376f
	  memset (lim_states, '\0',
Packit Service 20376f
		  sizeof (re_dfastate_t *) * (match_last + 1));
Packit Service 20376f
	  sift_ctx_init (&sctx, sifted_states, lim_states, halt_node,
Packit Service 20376f
			 match_last);
Packit Service 20376f
	  ret = sift_states_backward (mctx, &sctx);
Packit Service 20376f
	  re_node_set_free (&sctx.limits);
Packit Service 20376f
	  if (BE (ret != REG_NOERROR, 0))
Packit Service 20376f
	      goto free_return;
Packit Service 20376f
	  if (sifted_states[0] != NULL || lim_states[0] != NULL)
Packit Service 20376f
	    break;
Packit Service 20376f
	  do
Packit Service 20376f
	    {
Packit Service 20376f
	      --match_last;
Packit Service 20376f
	      if (match_last < 0)
Packit Service 20376f
		{
Packit Service 20376f
		  ret = REG_NOMATCH;
Packit Service 20376f
		  goto free_return;
Packit Service 20376f
		}
Packit Service 20376f
	    } while (mctx->state_log[match_last] == NULL
Packit Service 20376f
		     || !mctx->state_log[match_last]->halt);
Packit Service 20376f
	  halt_node = check_halt_state_context (mctx,
Packit Service 20376f
						mctx->state_log[match_last],
Packit Service 20376f
						match_last);
Packit Service 20376f
	}
Packit Service 20376f
      ret = merge_state_array (dfa, sifted_states, lim_states,
Packit Service 20376f
			       match_last + 1);
Packit Service 20376f
      re_free (lim_states);
Packit Service 20376f
      lim_states = NULL;
Packit Service 20376f
      if (BE (ret != REG_NOERROR, 0))
Packit Service 20376f
	goto free_return;
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
    {
Packit Service 20376f
      sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last);
Packit Service 20376f
      ret = sift_states_backward (mctx, &sctx);
Packit Service 20376f
      re_node_set_free (&sctx.limits);
Packit Service 20376f
      if (BE (ret != REG_NOERROR, 0))
Packit Service 20376f
	goto free_return;
Packit Service 20376f
      if (sifted_states[0] == NULL)
Packit Service 20376f
	{
Packit Service 20376f
	  ret = REG_NOMATCH;
Packit Service 20376f
	  goto free_return;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  re_free (mctx->state_log);
Packit Service 20376f
  mctx->state_log = sifted_states;
Packit Service 20376f
  sifted_states = NULL;
Packit Service 20376f
  mctx->last_node = halt_node;
Packit Service 20376f
  mctx->match_last = match_last;
Packit Service 20376f
  ret = REG_NOERROR;
Packit Service 20376f
 free_return:
Packit Service 20376f
  re_free (sifted_states);
Packit Service 20376f
  re_free (lim_states);
Packit Service 20376f
  return ret;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Acquire an initial state and return it.
Packit Service 20376f
   We must select appropriate initial state depending on the context,
Packit Service 20376f
   since initial states may have constraints like "\<", "^", etc..  */
Packit Service 20376f
Packit Service 20376f
static inline re_dfastate_t *
Packit Service 20376f
__attribute ((always_inline)) internal_function
Packit Service 20376f
acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx,
Packit Service 20376f
			    int idx)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  if (dfa->init_state->has_constraint)
Packit Service 20376f
    {
Packit Service 20376f
      unsigned int context;
Packit Service 20376f
      context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags);
Packit Service 20376f
      if (IS_WORD_CONTEXT (context))
Packit Service 20376f
	return dfa->init_state_word;
Packit Service 20376f
      else if (IS_ORDINARY_CONTEXT (context))
Packit Service 20376f
	return dfa->init_state;
Packit Service 20376f
      else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context))
Packit Service 20376f
	return dfa->init_state_begbuf;
Packit Service 20376f
      else if (IS_NEWLINE_CONTEXT (context))
Packit Service 20376f
	return dfa->init_state_nl;
Packit Service 20376f
      else if (IS_BEGBUF_CONTEXT (context))
Packit Service 20376f
	{
Packit Service 20376f
	  /* It is relatively rare case, then calculate on demand.  */
Packit Service 20376f
	  return re_acquire_state_context (err, dfa,
Packit Service 20376f
					   dfa->init_state->entrance_nodes,
Packit Service 20376f
					   context);
Packit Service 20376f
	}
Packit Service 20376f
      else
Packit Service 20376f
	/* Must not happen?  */
Packit Service 20376f
	return dfa->init_state;
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
    return dfa->init_state;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Check whether the regular expression match input string INPUT or not,
Packit Service 20376f
   and return the index where the matching end, return -1 if not match,
Packit Service 20376f
   or return -2 in case of an error.
Packit Service 20376f
   FL_LONGEST_MATCH means we want the POSIX longest matching.
Packit Service 20376f
   If P_MATCH_FIRST is not NULL, and the match fails, it is set to the
Packit Service 20376f
   next place where we may want to try matching.
Packit Service 20376f
   Note that the matcher assume that the maching starts from the current
Packit Service 20376f
   index of the buffer.  */
Packit Service 20376f
Packit Service 20376f
static int
Packit Service 20376f
internal_function
Packit Service 20376f
check_matching (re_match_context_t *mctx, int fl_longest_match,
Packit Service 20376f
		int *p_match_first)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  reg_errcode_t err;
Packit Service 20376f
  int match = 0;
Packit Service 20376f
  int match_last = -1;
Packit Service 20376f
  int cur_str_idx = re_string_cur_idx (&mctx->input);
Packit Service 20376f
  re_dfastate_t *cur_state;
Packit Service 20376f
  int at_init_state = p_match_first != NULL;
Packit Service 20376f
  int next_start_idx = cur_str_idx;
Packit Service 20376f
Packit Service 20376f
  err = REG_NOERROR;
Packit Service 20376f
  cur_state = acquire_init_state_context (&err, mctx, cur_str_idx);
Packit Service 20376f
  /* An initial state must not be NULL (invalid).  */
Packit Service 20376f
  if (BE (cur_state == NULL, 0))
Packit Service 20376f
    {
Packit Service 20376f
      assert (err == REG_ESPACE);
Packit Service 20376f
      return -2;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  if (mctx->state_log != NULL)
Packit Service 20376f
    {
Packit Service 20376f
      mctx->state_log[cur_str_idx] = cur_state;
Packit Service 20376f
Packit Service 20376f
      /* Check OP_OPEN_SUBEXP in the initial state in case that we use them
Packit Service 20376f
	 later.  E.g. Processing back references.  */
Packit Service 20376f
      if (BE (dfa->nbackref, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  at_init_state = 0;
Packit Service 20376f
	  err = check_subexp_matching_top (mctx, &cur_state->nodes, 0);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    return err;
Packit Service 20376f
Packit Service 20376f
	  if (cur_state->has_backref)
Packit Service 20376f
	    {
Packit Service 20376f
	      err = transit_state_bkref (mctx, &cur_state->nodes);
Packit Service 20376f
	      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
		return err;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  /* If the RE accepts NULL string.  */
Packit Service 20376f
  if (BE (cur_state->halt, 0))
Packit Service 20376f
    {
Packit Service 20376f
      if (!cur_state->has_constraint
Packit Service 20376f
	  || check_halt_state_context (mctx, cur_state, cur_str_idx))
Packit Service 20376f
	{
Packit Service 20376f
	  if (!fl_longest_match)
Packit Service 20376f
	    return cur_str_idx;
Packit Service 20376f
	  else
Packit Service 20376f
	    {
Packit Service 20376f
	      match_last = cur_str_idx;
Packit Service 20376f
	      match = 1;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  while (!re_string_eoi (&mctx->input))
Packit Service 20376f
    {
Packit Service 20376f
      re_dfastate_t *old_state = cur_state;
Packit Service 20376f
      int next_char_idx = re_string_cur_idx (&mctx->input) + 1;
Packit Service 20376f
Packit Service 20376f
      if (BE (next_char_idx >= mctx->input.bufs_len, 0)
Packit Service 20376f
	  || (BE (next_char_idx >= mctx->input.valid_len, 0)
Packit Service 20376f
	      && mctx->input.valid_len < mctx->input.len))
Packit Service 20376f
	{
Packit Service 20376f
	  err = extend_buffers (mctx);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      assert (err == REG_ESPACE);
Packit Service 20376f
	      return -2;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      cur_state = transit_state (&err, mctx, cur_state);
Packit Service 20376f
      if (mctx->state_log != NULL)
Packit Service 20376f
	cur_state = merge_state_with_log (&err, mctx, cur_state);
Packit Service 20376f
Packit Service 20376f
      if (cur_state == NULL)
Packit Service 20376f
	{
Packit Service 20376f
	  /* Reached the invalid state or an error.  Try to recover a valid
Packit Service 20376f
	     state using the state log, if available and if we have not
Packit Service 20376f
	     already found a valid (even if not the longest) match.  */
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    return -2;
Packit Service 20376f
Packit Service 20376f
	  if (mctx->state_log == NULL
Packit Service 20376f
	      || (match && !fl_longest_match)
Packit Service 20376f
	      || (cur_state = find_recover_state (&err, mctx)) == NULL)
Packit Service 20376f
	    break;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      if (BE (at_init_state, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  if (old_state == cur_state)
Packit Service 20376f
	    next_start_idx = next_char_idx;
Packit Service 20376f
	  else
Packit Service 20376f
	    at_init_state = 0;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      if (cur_state->halt)
Packit Service 20376f
	{
Packit Service 20376f
	  /* Reached a halt state.
Packit Service 20376f
	     Check the halt state can satisfy the current context.  */
Packit Service 20376f
	  if (!cur_state->has_constraint
Packit Service 20376f
	      || check_halt_state_context (mctx, cur_state,
Packit Service 20376f
					   re_string_cur_idx (&mctx->input)))
Packit Service 20376f
	    {
Packit Service 20376f
	      /* We found an appropriate halt state.  */
Packit Service 20376f
	      match_last = re_string_cur_idx (&mctx->input);
Packit Service 20376f
	      match = 1;
Packit Service 20376f
Packit Service 20376f
	      /* We found a match, do not modify match_first below.  */
Packit Service 20376f
	      p_match_first = NULL;
Packit Service 20376f
	      if (!fl_longest_match)
Packit Service 20376f
		break;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  if (p_match_first)
Packit Service 20376f
    *p_match_first += next_start_idx;
Packit Service 20376f
Packit Service 20376f
  return match_last;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Check NODE match the current context.  */
Packit Service 20376f
Packit Service 20376f
static int
Packit Service 20376f
internal_function
Packit Service 20376f
check_halt_node_context (const re_dfa_t *dfa, int node, unsigned int context)
Packit Service 20376f
{
Packit Service 20376f
  re_token_type_t type = dfa->nodes[node].type;
Packit Service 20376f
  unsigned int constraint = dfa->nodes[node].constraint;
Packit Service 20376f
  if (type != END_OF_RE)
Packit Service 20376f
    return 0;
Packit Service 20376f
  if (!constraint)
Packit Service 20376f
    return 1;
Packit Service 20376f
  if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context))
Packit Service 20376f
    return 0;
Packit Service 20376f
  return 1;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Check the halt state STATE match the current context.
Packit Service 20376f
   Return 0 if not match, if the node, STATE has, is a halt node and
Packit Service 20376f
   match the context, return the node.  */
Packit Service 20376f
Packit Service 20376f
static int
Packit Service 20376f
internal_function
Packit Service 20376f
check_halt_state_context (const re_match_context_t *mctx,
Packit Service 20376f
			  const re_dfastate_t *state, int idx)
Packit Service 20376f
{
Packit Service 20376f
  int i;
Packit Service 20376f
  unsigned int context;
Packit Service 20376f
#ifdef DEBUG
Packit Service 20376f
  assert (state->halt);
Packit Service 20376f
#endif
Packit Service 20376f
  context = re_string_context_at (&mctx->input, idx, mctx->eflags);
Packit Service 20376f
  for (i = 0; i < state->nodes.nelem; ++i)
Packit Service 20376f
    if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context))
Packit Service 20376f
      return state->nodes.elems[i];
Packit Service 20376f
  return 0;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA
Packit Service 20376f
   corresponding to the DFA).
Packit Service 20376f
   Return the destination node, and update EPS_VIA_NODES, return -1 in case
Packit Service 20376f
   of errors.  */
Packit Service 20376f
Packit Service 20376f
static int
Packit Service 20376f
internal_function
Packit Service 20376f
proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs,
Packit Service 20376f
		   int *pidx, int node, re_node_set *eps_via_nodes,
Packit Service 20376f
		   struct re_fail_stack_t *fs)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  int i, err;
Packit Service 20376f
  if (IS_EPSILON_NODE (dfa->nodes[node].type))
Packit Service 20376f
    {
Packit Service 20376f
      re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes;
Packit Service 20376f
      re_node_set *edests = &dfa->edests[node];
Packit Service 20376f
      int dest_node;
Packit Service 20376f
      err = re_node_set_insert (eps_via_nodes, node);
Packit Service 20376f
      if (BE (err < 0, 0))
Packit Service 20376f
	return -2;
Packit Service 20376f
      /* Pick up a valid destination, or return -1 if none is found.  */
Packit Service 20376f
      for (dest_node = -1, i = 0; i < edests->nelem; ++i)
Packit Service 20376f
	{
Packit Service 20376f
	  int candidate = edests->elems[i];
Packit Service 20376f
	  if (!re_node_set_contains (cur_nodes, candidate))
Packit Service 20376f
	    continue;
Packit Service 20376f
	  if (dest_node == -1)
Packit Service 20376f
	    dest_node = candidate;
Packit Service 20376f
Packit Service 20376f
	  else
Packit Service 20376f
	    {
Packit Service 20376f
	      /* In order to avoid infinite loop like "(a*)*", return the second
Packit Service 20376f
		 epsilon-transition if the first was already considered.  */
Packit Service 20376f
	      if (re_node_set_contains (eps_via_nodes, dest_node))
Packit Service 20376f
		return candidate;
Packit Service 20376f
Packit Service 20376f
	      /* Otherwise, push the second epsilon-transition on the fail stack.  */
Packit Service 20376f
	      else if (fs != NULL
Packit Service 20376f
		       && push_fail_stack (fs, *pidx, candidate, nregs, regs,
Packit Service 20376f
					   eps_via_nodes))
Packit Service 20376f
		return -2;
Packit Service 20376f
Packit Service 20376f
	      /* We know we are going to exit.  */
Packit Service 20376f
	      break;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
      return dest_node;
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
    {
Packit Service 20376f
      int naccepted = 0;
Packit Service 20376f
      re_token_type_t type = dfa->nodes[node].type;
Packit Service 20376f
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
      if (dfa->nodes[node].accept_mb)
Packit Service 20376f
	naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx);
Packit Service 20376f
      else
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
      if (type == OP_BACK_REF)
Packit Service 20376f
	{
Packit Service 20376f
	  int subexp_idx = dfa->nodes[node].opr.idx + 1;
Packit Service 20376f
	  naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so;
Packit Service 20376f
	  if (fs != NULL)
Packit Service 20376f
	    {
Packit Service 20376f
	      if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1)
Packit Service 20376f
		return -1;
Packit Service 20376f
	      else if (naccepted)
Packit Service 20376f
		{
Packit Service 20376f
		  char *buf = (char *) re_string_get_buffer (&mctx->input);
Packit Service 20376f
		  if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx,
Packit Service 20376f
			      naccepted) != 0)
Packit Service 20376f
		    return -1;
Packit Service 20376f
		}
Packit Service 20376f
	    }
Packit Service 20376f
Packit Service 20376f
	  if (naccepted == 0)
Packit Service 20376f
	    {
Packit Service 20376f
	      int dest_node;
Packit Service 20376f
	      err = re_node_set_insert (eps_via_nodes, node);
Packit Service 20376f
	      if (BE (err < 0, 0))
Packit Service 20376f
		return -2;
Packit Service 20376f
	      dest_node = dfa->edests[node].elems[0];
Packit Service 20376f
	      if (re_node_set_contains (&mctx->state_log[*pidx]->nodes,
Packit Service 20376f
					dest_node))
Packit Service 20376f
		return dest_node;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      if (naccepted != 0
Packit Service 20376f
	  || check_node_accept (mctx, dfa->nodes + node, *pidx))
Packit Service 20376f
	{
Packit Service 20376f
	  int dest_node = dfa->nexts[node];
Packit Service 20376f
	  *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted;
Packit Service 20376f
	  if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL
Packit Service 20376f
		     || !re_node_set_contains (&mctx->state_log[*pidx]->nodes,
Packit Service 20376f
					       dest_node)))
Packit Service 20376f
	    return -1;
Packit Service 20376f
	  re_node_set_empty (eps_via_nodes);
Packit Service 20376f
	  return dest_node;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  return -1;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
push_fail_stack (struct re_fail_stack_t *fs, int str_idx, int dest_node,
Packit Service 20376f
		 int nregs, regmatch_t *regs, re_node_set *eps_via_nodes)
Packit Service 20376f
{
Packit Service 20376f
  reg_errcode_t err;
Packit Service 20376f
  int num = fs->num++;
Packit Service 20376f
  if (fs->num == fs->alloc)
Packit Service 20376f
    {
Packit Service 20376f
      struct re_fail_stack_ent_t *new_array;
Packit Service 20376f
      new_array = realloc (fs->stack, (sizeof (struct re_fail_stack_ent_t)
Packit Service 20376f
				       * fs->alloc * 2));
Packit Service 20376f
      if (new_array == NULL)
Packit Service 20376f
	return REG_ESPACE;
Packit Service 20376f
      fs->alloc *= 2;
Packit Service 20376f
      fs->stack = new_array;
Packit Service 20376f
    }
Packit Service 20376f
  fs->stack[num].idx = str_idx;
Packit Service 20376f
  fs->stack[num].node = dest_node;
Packit Service 20376f
  fs->stack[num].regs = re_malloc (regmatch_t, nregs);
Packit Service 20376f
  if (fs->stack[num].regs == NULL)
Packit Service 20376f
    return REG_ESPACE;
Packit Service 20376f
  memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs);
Packit Service 20376f
  err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes);
Packit Service 20376f
  return err;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static int
Packit Service 20376f
internal_function
Packit Service 20376f
pop_fail_stack (struct re_fail_stack_t *fs, int *pidx, int nregs,
Packit Service 20376f
		regmatch_t *regs, re_node_set *eps_via_nodes)
Packit Service 20376f
{
Packit Service 20376f
  int num = --fs->num;
Packit Service 20376f
  assert (num >= 0);
Packit Service 20376f
  *pidx = fs->stack[num].idx;
Packit Service 20376f
  memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs);
Packit Service 20376f
  re_node_set_free (eps_via_nodes);
Packit Service 20376f
  re_free (fs->stack[num].regs);
Packit Service 20376f
  *eps_via_nodes = fs->stack[num].eps_via_nodes;
Packit Service 20376f
  return fs->stack[num].node;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Set the positions where the subexpressions are starts/ends to registers
Packit Service 20376f
   PMATCH.
Packit Service 20376f
   Note: We assume that pmatch[0] is already set, and
Packit Service 20376f
   pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,
Packit Service 20376f
	  regmatch_t *pmatch, int fl_backtrack)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer;
Packit Service 20376f
  int idx, cur_node;
Packit Service 20376f
  re_node_set eps_via_nodes;
Packit Service 20376f
  struct re_fail_stack_t *fs;
Packit Service 20376f
  struct re_fail_stack_t fs_body = { 0, 2, NULL };
Packit Service 20376f
  regmatch_t *prev_idx_match;
Packit Service 20376f
  int prev_idx_match_malloced = 0;
Packit Service 20376f
Packit Service 20376f
#ifdef DEBUG
Packit Service 20376f
  assert (nmatch > 1);
Packit Service 20376f
  assert (mctx->state_log != NULL);
Packit Service 20376f
#endif
Packit Service 20376f
  if (fl_backtrack)
Packit Service 20376f
    {
Packit Service 20376f
      fs = &fs_body;
Packit Service 20376f
      fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc);
Packit Service 20376f
      if (fs->stack == NULL)
Packit Service 20376f
	return REG_ESPACE;
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
    fs = NULL;
Packit Service 20376f
Packit Service 20376f
  cur_node = dfa->init_node;
Packit Service 20376f
  re_node_set_init_empty (&eps_via_nodes);
Packit Service 20376f
Packit Service 20376f
#ifdef HAVE_ALLOCA
Packit Service 20376f
  if (__libc_use_alloca (nmatch * sizeof (regmatch_t)))
Packit Service 20376f
    prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t));
Packit Service 20376f
  else
Packit Service 20376f
#endif
Packit Service 20376f
    {
Packit Service 20376f
      prev_idx_match = re_malloc (regmatch_t, nmatch);
Packit Service 20376f
      if (prev_idx_match == NULL)
Packit Service 20376f
	{
Packit Service 20376f
	  free_fail_stack_return (fs);
Packit Service 20376f
	  return REG_ESPACE;
Packit Service 20376f
	}
Packit Service 20376f
      prev_idx_match_malloced = 1;
Packit Service 20376f
    }
Packit Service 20376f
  memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);
Packit Service 20376f
Packit Service 20376f
  for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;)
Packit Service 20376f
    {
Packit Service 20376f
      update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch);
Packit Service 20376f
Packit Service 20376f
      if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node)
Packit Service 20376f
	{
Packit Service 20376f
	  unsigned int reg_idx;
Packit Service 20376f
	  if (fs)
Packit Service 20376f
	    {
Packit Service 20376f
	      for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
Packit Service 20376f
		if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1)
Packit Service 20376f
		  break;
Packit Service 20376f
	      if (reg_idx == nmatch)
Packit Service 20376f
		{
Packit Service 20376f
		  re_node_set_free (&eps_via_nodes);
Packit Service 20376f
		  if (prev_idx_match_malloced)
Packit Service 20376f
		    re_free (prev_idx_match);
Packit Service 20376f
		  return free_fail_stack_return (fs);
Packit Service 20376f
		}
Packit Service 20376f
	      cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
Packit Service 20376f
					 &eps_via_nodes);
Packit Service 20376f
	    }
Packit Service 20376f
	  else
Packit Service 20376f
	    {
Packit Service 20376f
	      re_node_set_free (&eps_via_nodes);
Packit Service 20376f
	      if (prev_idx_match_malloced)
Packit Service 20376f
		re_free (prev_idx_match);
Packit Service 20376f
	      return REG_NOERROR;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      /* Proceed to next node.  */
Packit Service 20376f
      cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node,
Packit Service 20376f
				    &eps_via_nodes, fs);
Packit Service 20376f
Packit Service 20376f
      if (BE (cur_node < 0, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  if (BE (cur_node == -2, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      re_node_set_free (&eps_via_nodes);
Packit Service 20376f
	      if (prev_idx_match_malloced)
Packit Service 20376f
		re_free (prev_idx_match);
Packit Service 20376f
	      free_fail_stack_return (fs);
Packit Service 20376f
	      return REG_ESPACE;
Packit Service 20376f
	    }
Packit Service 20376f
	  if (fs)
Packit Service 20376f
	    cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,
Packit Service 20376f
				       &eps_via_nodes);
Packit Service 20376f
	  else
Packit Service 20376f
	    {
Packit Service 20376f
	      re_node_set_free (&eps_via_nodes);
Packit Service 20376f
	      if (prev_idx_match_malloced)
Packit Service 20376f
		re_free (prev_idx_match);
Packit Service 20376f
	      return REG_NOMATCH;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  re_node_set_free (&eps_via_nodes);
Packit Service 20376f
  if (prev_idx_match_malloced)
Packit Service 20376f
    re_free (prev_idx_match);
Packit Service 20376f
  return free_fail_stack_return (fs);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
free_fail_stack_return (struct re_fail_stack_t *fs)
Packit Service 20376f
{
Packit Service 20376f
  if (fs)
Packit Service 20376f
    {
Packit Service 20376f
      int fs_idx;
Packit Service 20376f
      for (fs_idx = 0; fs_idx < fs->num; ++fs_idx)
Packit Service 20376f
	{
Packit Service 20376f
	  re_node_set_free (&fs->stack[fs_idx].eps_via_nodes);
Packit Service 20376f
	  re_free (fs->stack[fs_idx].regs);
Packit Service 20376f
	}
Packit Service 20376f
      re_free (fs->stack);
Packit Service 20376f
    }
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static void
Packit Service 20376f
internal_function
Packit Service 20376f
update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,
Packit Service 20376f
	     regmatch_t *prev_idx_match, int cur_node, int cur_idx, int nmatch)
Packit Service 20376f
{
Packit Service 20376f
  int type = dfa->nodes[cur_node].type;
Packit Service 20376f
  if (type == OP_OPEN_SUBEXP)
Packit Service 20376f
    {
Packit Service 20376f
      int reg_num = dfa->nodes[cur_node].opr.idx + 1;
Packit Service 20376f
Packit Service 20376f
      /* We are at the first node of this sub expression.  */
Packit Service 20376f
      if (reg_num < nmatch)
Packit Service 20376f
	{
Packit Service 20376f
	  pmatch[reg_num].rm_so = cur_idx;
Packit Service 20376f
	  pmatch[reg_num].rm_eo = -1;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  else if (type == OP_CLOSE_SUBEXP)
Packit Service 20376f
    {
Packit Service 20376f
      int reg_num = dfa->nodes[cur_node].opr.idx + 1;
Packit Service 20376f
      if (reg_num < nmatch)
Packit Service 20376f
	{
Packit Service 20376f
	  /* We are at the last node of this sub expression.  */
Packit Service 20376f
	  if (pmatch[reg_num].rm_so < cur_idx)
Packit Service 20376f
	    {
Packit Service 20376f
	      pmatch[reg_num].rm_eo = cur_idx;
Packit Service 20376f
	      /* This is a non-empty match or we are not inside an optional
Packit Service 20376f
		 subexpression.  Accept this right away.  */
Packit Service 20376f
	      memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);
Packit Service 20376f
	    }
Packit Service 20376f
	  else
Packit Service 20376f
	    {
Packit Service 20376f
	      if (dfa->nodes[cur_node].opt_subexp
Packit Service 20376f
		  && prev_idx_match[reg_num].rm_so != -1)
Packit Service 20376f
		/* We transited through an empty match for an optional
Packit Service 20376f
		   subexpression, like (a?)*, and this is not the subexp's
Packit Service 20376f
		   first match.  Copy back the old content of the registers
Packit Service 20376f
		   so that matches of an inner subexpression are undone as
Packit Service 20376f
		   well, like in ((a?))*.  */
Packit Service 20376f
		memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch);
Packit Service 20376f
	      else
Packit Service 20376f
		/* We completed a subexpression, but it may be part of
Packit Service 20376f
		   an optional one, so do not update PREV_IDX_MATCH.  */
Packit Service 20376f
		pmatch[reg_num].rm_eo = cur_idx;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* This function checks the STATE_LOG from the SCTX->last_str_idx to 0
Packit Service 20376f
   and sift the nodes in each states according to the following rules.
Packit Service 20376f
   Updated state_log will be wrote to STATE_LOG.
Packit Service 20376f
Packit Service 20376f
   Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if...
Packit Service 20376f
     1. When STR_IDX == MATCH_LAST(the last index in the state_log):
Packit Service 20376f
	If `a' isn't the LAST_NODE and `a' can't epsilon transit to
Packit Service 20376f
	the LAST_NODE, we throw away the node `a'.
Packit Service 20376f
     2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts
Packit Service 20376f
	string `s' and transit to `b':
Packit Service 20376f
	i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw
Packit Service 20376f
	   away the node `a'.
Packit Service 20376f
	ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is
Packit Service 20376f
	    thrown away, we throw away the node `a'.
Packit Service 20376f
     3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b':
Packit Service 20376f
	i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the
Packit Service 20376f
	   node `a'.
Packit Service 20376f
	ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away,
Packit Service 20376f
	    we throw away the node `a'.  */
Packit Service 20376f
Packit Service 20376f
#define STATE_NODE_CONTAINS(state,node) \
Packit Service 20376f
  ((state) != NULL && re_node_set_contains (&(state)->nodes, node))
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx)
Packit Service 20376f
{
Packit Service 20376f
  reg_errcode_t err;
Packit Service 20376f
  int null_cnt = 0;
Packit Service 20376f
  int str_idx = sctx->last_str_idx;
Packit Service 20376f
  re_node_set cur_dest;
Packit Service 20376f
Packit Service 20376f
#ifdef DEBUG
Packit Service 20376f
  assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL);
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
  /* Build sifted state_log[str_idx].  It has the nodes which can epsilon
Packit Service 20376f
     transit to the last_node and the last_node itself.  */
Packit Service 20376f
  err = re_node_set_init_1 (&cur_dest, sctx->last_node);
Packit Service 20376f
  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
    return err;
Packit Service 20376f
  err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest);
Packit Service 20376f
  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
    goto free_return;
Packit Service 20376f
Packit Service 20376f
  /* Then check each states in the state_log.  */
Packit Service 20376f
  while (str_idx > 0)
Packit Service 20376f
    {
Packit Service 20376f
      /* Update counters.  */
Packit Service 20376f
      null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0;
Packit Service 20376f
      if (null_cnt > mctx->max_mb_elem_len)
Packit Service 20376f
	{
Packit Service 20376f
	  memset (sctx->sifted_states, '\0',
Packit Service 20376f
		  sizeof (re_dfastate_t *) * str_idx);
Packit Service 20376f
	  re_node_set_free (&cur_dest);
Packit Service 20376f
	  return REG_NOERROR;
Packit Service 20376f
	}
Packit Service 20376f
      re_node_set_empty (&cur_dest);
Packit Service 20376f
      --str_idx;
Packit Service 20376f
Packit Service 20376f
      if (mctx->state_log[str_idx])
Packit Service 20376f
	{
Packit Service 20376f
	  err = build_sifted_states (mctx, sctx, str_idx, &cur_dest);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    goto free_return;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      /* Add all the nodes which satisfy the following conditions:
Packit Service 20376f
	 - It can epsilon transit to a node in CUR_DEST.
Packit Service 20376f
	 - It is in CUR_SRC.
Packit Service 20376f
	 And update state_log.  */
Packit Service 20376f
      err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest);
Packit Service 20376f
      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	goto free_return;
Packit Service 20376f
    }
Packit Service 20376f
  err = REG_NOERROR;
Packit Service 20376f
 free_return:
Packit Service 20376f
  re_node_set_free (&cur_dest);
Packit Service 20376f
  return err;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx,
Packit Service 20376f
		     int str_idx, re_node_set *cur_dest)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes;
Packit Service 20376f
  int i;
Packit Service 20376f
Packit Service 20376f
  /* Then build the next sifted state.
Packit Service 20376f
     We build the next sifted state on `cur_dest', and update
Packit Service 20376f
     `sifted_states[str_idx]' with `cur_dest'.
Packit Service 20376f
     Note:
Packit Service 20376f
     `cur_dest' is the sifted state from `state_log[str_idx + 1]'.
Packit Service 20376f
     `cur_src' points the node_set of the old `state_log[str_idx]'
Packit Service 20376f
     (with the epsilon nodes pre-filtered out).  */
Packit Service 20376f
  for (i = 0; i < cur_src->nelem; i++)
Packit Service 20376f
    {
Packit Service 20376f
      int prev_node = cur_src->elems[i];
Packit Service 20376f
      int naccepted = 0;
Packit Service 20376f
      int ret;
Packit Service 20376f
Packit Service 20376f
#ifdef DEBUG
Packit Service 20376f
      re_token_type_t type = dfa->nodes[prev_node].type;
Packit Service 20376f
      assert (!IS_EPSILON_NODE (type));
Packit Service 20376f
#endif
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
      /* If the node may accept `multi byte'.  */
Packit Service 20376f
      if (dfa->nodes[prev_node].accept_mb)
Packit Service 20376f
	naccepted = sift_states_iter_mb (mctx, sctx, prev_node,
Packit Service 20376f
					 str_idx, sctx->last_str_idx);
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
Packit Service 20376f
      /* We don't check backreferences here.
Packit Service 20376f
	 See update_cur_sifted_state().  */
Packit Service 20376f
      if (!naccepted
Packit Service 20376f
	  && check_node_accept (mctx, dfa->nodes + prev_node, str_idx)
Packit Service 20376f
	  && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1],
Packit Service 20376f
				  dfa->nexts[prev_node]))
Packit Service 20376f
	naccepted = 1;
Packit Service 20376f
Packit Service 20376f
      if (naccepted == 0)
Packit Service 20376f
	continue;
Packit Service 20376f
Packit Service 20376f
      if (sctx->limits.nelem)
Packit Service 20376f
	{
Packit Service 20376f
	  int to_idx = str_idx + naccepted;
Packit Service 20376f
	  if (check_dst_limits (mctx, &sctx->limits,
Packit Service 20376f
				dfa->nexts[prev_node], to_idx,
Packit Service 20376f
				prev_node, str_idx))
Packit Service 20376f
	    continue;
Packit Service 20376f
	}
Packit Service 20376f
      ret = re_node_set_insert (cur_dest, prev_node);
Packit Service 20376f
      if (BE (ret == -1, 0))
Packit Service 20376f
	return REG_ESPACE;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Helper functions.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
clean_state_log_if_needed (re_match_context_t *mctx, int next_state_log_idx)
Packit Service 20376f
{
Packit Service 20376f
  int top = mctx->state_log_top;
Packit Service 20376f
Packit Service 20376f
  if (next_state_log_idx >= mctx->input.bufs_len
Packit Service 20376f
      || (next_state_log_idx >= mctx->input.valid_len
Packit Service 20376f
	  && mctx->input.valid_len < mctx->input.len))
Packit Service 20376f
    {
Packit Service 20376f
      reg_errcode_t err;
Packit Service 20376f
      err = extend_buffers (mctx);
Packit Service 20376f
      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	return err;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  if (top < next_state_log_idx)
Packit Service 20376f
    {
Packit Service 20376f
      memset (mctx->state_log + top + 1, '\0',
Packit Service 20376f
	      sizeof (re_dfastate_t *) * (next_state_log_idx - top));
Packit Service 20376f
      mctx->state_log_top = next_state_log_idx;
Packit Service 20376f
    }
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst,
Packit Service 20376f
		   re_dfastate_t **src, int num)
Packit Service 20376f
{
Packit Service 20376f
  int st_idx;
Packit Service 20376f
  reg_errcode_t err;
Packit Service 20376f
  for (st_idx = 0; st_idx < num; ++st_idx)
Packit Service 20376f
    {
Packit Service 20376f
      if (dst[st_idx] == NULL)
Packit Service 20376f
	dst[st_idx] = src[st_idx];
Packit Service 20376f
      else if (src[st_idx] != NULL)
Packit Service 20376f
	{
Packit Service 20376f
	  re_node_set merged_set;
Packit Service 20376f
	  err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes,
Packit Service 20376f
					&src[st_idx]->nodes);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    return err;
Packit Service 20376f
	  dst[st_idx] = re_acquire_state (&err, dfa, &merged_set);
Packit Service 20376f
	  re_node_set_free (&merged_set);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    return err;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
update_cur_sifted_state (const re_match_context_t *mctx,
Packit Service 20376f
			 re_sift_context_t *sctx, int str_idx,
Packit Service 20376f
			 re_node_set *dest_nodes)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  reg_errcode_t err = REG_NOERROR;
Packit Service 20376f
  const re_node_set *candidates;
Packit Service 20376f
  candidates = ((mctx->state_log[str_idx] == NULL) ? NULL
Packit Service 20376f
		: &mctx->state_log[str_idx]->nodes);
Packit Service 20376f
Packit Service 20376f
  if (dest_nodes->nelem == 0)
Packit Service 20376f
    sctx->sifted_states[str_idx] = NULL;
Packit Service 20376f
  else
Packit Service 20376f
    {
Packit Service 20376f
      if (candidates)
Packit Service 20376f
	{
Packit Service 20376f
	  /* At first, add the nodes which can epsilon transit to a node in
Packit Service 20376f
	     DEST_NODE.  */
Packit Service 20376f
	  err = add_epsilon_src_nodes (dfa, dest_nodes, candidates);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    return err;
Packit Service 20376f
Packit Service 20376f
	  /* Then, check the limitations in the current sift_context.  */
Packit Service 20376f
	  if (sctx->limits.nelem)
Packit Service 20376f
	    {
Packit Service 20376f
	      err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits,
Packit Service 20376f
					 mctx->bkref_ents, str_idx);
Packit Service 20376f
	      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
		return err;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes);
Packit Service 20376f
      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	return err;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  if (candidates && mctx->state_log[str_idx]->has_backref)
Packit Service 20376f
    {
Packit Service 20376f
      err = sift_states_bkref (mctx, sctx, str_idx, candidates);
Packit Service 20376f
      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	return err;
Packit Service 20376f
    }
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes,
Packit Service 20376f
		       const re_node_set *candidates)
Packit Service 20376f
{
Packit Service 20376f
  reg_errcode_t err = REG_NOERROR;
Packit Service 20376f
  int i;
Packit Service 20376f
Packit Service 20376f
  re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes);
Packit Service 20376f
  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
    return err;
Packit Service 20376f
Packit Service 20376f
  if (!state->inveclosure.alloc)
Packit Service 20376f
    {
Packit Service 20376f
      err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem);
Packit Service 20376f
      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	return REG_ESPACE;
Packit Service 20376f
      for (i = 0; i < dest_nodes->nelem; i++)
Packit Service 20376f
	{
Packit Service 20376f
	  err = re_node_set_merge (&state->inveclosure,
Packit Service 20376f
				   dfa->inveclosures + dest_nodes->elems[i]);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    return REG_ESPACE;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  return re_node_set_add_intersect (dest_nodes, candidates,
Packit Service 20376f
				    &state->inveclosure);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
sub_epsilon_src_nodes (const re_dfa_t *dfa, int node, re_node_set *dest_nodes,
Packit Service 20376f
		       const re_node_set *candidates)
Packit Service 20376f
{
Packit Service 20376f
    int ecl_idx;
Packit Service 20376f
    reg_errcode_t err;
Packit Service 20376f
    re_node_set *inv_eclosure = dfa->inveclosures + node;
Packit Service 20376f
    re_node_set except_nodes;
Packit Service 20376f
    re_node_set_init_empty (&except_nodes);
Packit Service 20376f
    for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)
Packit Service 20376f
      {
Packit Service 20376f
	int cur_node = inv_eclosure->elems[ecl_idx];
Packit Service 20376f
	if (cur_node == node)
Packit Service 20376f
	  continue;
Packit Service 20376f
	if (IS_EPSILON_NODE (dfa->nodes[cur_node].type))
Packit Service 20376f
	  {
Packit Service 20376f
	    int edst1 = dfa->edests[cur_node].elems[0];
Packit Service 20376f
	    int edst2 = ((dfa->edests[cur_node].nelem > 1)
Packit Service 20376f
			 ? dfa->edests[cur_node].elems[1] : -1);
Packit Service 20376f
	    if ((!re_node_set_contains (inv_eclosure, edst1)
Packit Service 20376f
		 && re_node_set_contains (dest_nodes, edst1))
Packit Service 20376f
		|| (edst2 > 0
Packit Service 20376f
		    && !re_node_set_contains (inv_eclosure, edst2)
Packit Service 20376f
		    && re_node_set_contains (dest_nodes, edst2)))
Packit Service 20376f
	      {
Packit Service 20376f
		err = re_node_set_add_intersect (&except_nodes, candidates,
Packit Service 20376f
						 dfa->inveclosures + cur_node);
Packit Service 20376f
		if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
		  {
Packit Service 20376f
		    re_node_set_free (&except_nodes);
Packit Service 20376f
		    return err;
Packit Service 20376f
		  }
Packit Service 20376f
	      }
Packit Service 20376f
	  }
Packit Service 20376f
      }
Packit Service 20376f
    for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)
Packit Service 20376f
      {
Packit Service 20376f
	int cur_node = inv_eclosure->elems[ecl_idx];
Packit Service 20376f
	if (!re_node_set_contains (&except_nodes, cur_node))
Packit Service 20376f
	  {
Packit Service 20376f
	    int idx = re_node_set_contains (dest_nodes, cur_node) - 1;
Packit Service 20376f
	    re_node_set_remove_at (dest_nodes, idx);
Packit Service 20376f
	  }
Packit Service 20376f
      }
Packit Service 20376f
    re_node_set_free (&except_nodes);
Packit Service 20376f
    return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static int
Packit Service 20376f
internal_function
Packit Service 20376f
check_dst_limits (const re_match_context_t *mctx, re_node_set *limits,
Packit Service 20376f
		  int dst_node, int dst_idx, int src_node, int src_idx)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  int lim_idx, src_pos, dst_pos;
Packit Service 20376f
Packit Service 20376f
  int dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx);
Packit Service 20376f
  int src_bkref_idx = search_cur_bkref_entry (mctx, src_idx);
Packit Service 20376f
  for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
Packit Service 20376f
    {
Packit Service 20376f
      int subexp_idx;
Packit Service 20376f
      struct re_backref_cache_entry *ent;
Packit Service 20376f
      ent = mctx->bkref_ents + limits->elems[lim_idx];
Packit Service 20376f
      subexp_idx = dfa->nodes[ent->node].opr.idx;
Packit Service 20376f
Packit Service 20376f
      dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx],
Packit Service 20376f
					   subexp_idx, dst_node, dst_idx,
Packit Service 20376f
					   dst_bkref_idx);
Packit Service 20376f
      src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx],
Packit Service 20376f
					   subexp_idx, src_node, src_idx,
Packit Service 20376f
					   src_bkref_idx);
Packit Service 20376f
Packit Service 20376f
      /* In case of:
Packit Service 20376f
	 <src> <dst> ( <subexp> )
Packit Service 20376f
	 ( <subexp> ) <src> <dst>
Packit Service 20376f
	 ( <subexp1> <src> <subexp2> <dst> <subexp3> )  */
Packit Service 20376f
      if (src_pos == dst_pos)
Packit Service 20376f
	continue; /* This is unrelated limitation.  */
Packit Service 20376f
      else
Packit Service 20376f
	return 1;
Packit Service 20376f
    }
Packit Service 20376f
  return 0;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static int
Packit Service 20376f
internal_function
Packit Service 20376f
check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries,
Packit Service 20376f
			     int subexp_idx, int from_node, int bkref_idx)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  const re_node_set *eclosures = dfa->eclosures + from_node;
Packit Service 20376f
  int node_idx;
Packit Service 20376f
Packit Service 20376f
  /* Else, we are on the boundary: examine the nodes on the epsilon
Packit Service 20376f
     closure.  */
Packit Service 20376f
  for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx)
Packit Service 20376f
    {
Packit Service 20376f
      int node = eclosures->elems[node_idx];
Packit Service 20376f
      switch (dfa->nodes[node].type)
Packit Service 20376f
	{
Packit Service 20376f
	case OP_BACK_REF:
Packit Service 20376f
	  if (bkref_idx != -1)
Packit Service 20376f
	    {
Packit Service 20376f
	      struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx;
Packit Service 20376f
	      do
Packit Service 20376f
		{
Packit Service 20376f
		  int dst, cpos;
Packit Service 20376f
Packit Service 20376f
		  if (ent->node != node)
Packit Service 20376f
		    continue;
Packit Service 20376f
Packit Service 20376f
		  if (subexp_idx < BITSET_WORD_BITS
Packit Service 20376f
		      && !(ent->eps_reachable_subexps_map
Packit Service 20376f
			   & ((bitset_word_t) 1 << subexp_idx)))
Packit Service 20376f
		    continue;
Packit Service 20376f
Packit Service 20376f
		  /* Recurse trying to reach the OP_OPEN_SUBEXP and
Packit Service 20376f
		     OP_CLOSE_SUBEXP cases below.  But, if the
Packit Service 20376f
		     destination node is the same node as the source
Packit Service 20376f
		     node, don't recurse because it would cause an
Packit Service 20376f
		     infinite loop: a regex that exhibits this behavior
Packit Service 20376f
		     is ()\1*\1*  */
Packit Service 20376f
		  dst = dfa->edests[node].elems[0];
Packit Service 20376f
		  if (dst == from_node)
Packit Service 20376f
		    {
Packit Service 20376f
		      if (boundaries & 1)
Packit Service 20376f
			return -1;
Packit Service 20376f
		      else /* if (boundaries & 2) */
Packit Service 20376f
			return 0;
Packit Service 20376f
		    }
Packit Service 20376f
Packit Service 20376f
		  cpos =
Packit Service 20376f
		    check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx,
Packit Service 20376f
						 dst, bkref_idx);
Packit Service 20376f
		  if (cpos == -1 /* && (boundaries & 1) */)
Packit Service 20376f
		    return -1;
Packit Service 20376f
		  if (cpos == 0 && (boundaries & 2))
Packit Service 20376f
		    return 0;
Packit Service 20376f
Packit Service 20376f
		  if (subexp_idx < BITSET_WORD_BITS)
Packit Service 20376f
		    ent->eps_reachable_subexps_map
Packit Service 20376f
		      &= ~((bitset_word_t) 1 << subexp_idx);
Packit Service 20376f
		}
Packit Service 20376f
	      while (ent++->more);
Packit Service 20376f
	    }
Packit Service 20376f
	  break;
Packit Service 20376f
Packit Service 20376f
	case OP_OPEN_SUBEXP:
Packit Service 20376f
	  if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx)
Packit Service 20376f
	    return -1;
Packit Service 20376f
	  break;
Packit Service 20376f
Packit Service 20376f
	case OP_CLOSE_SUBEXP:
Packit Service 20376f
	  if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx)
Packit Service 20376f
	    return 0;
Packit Service 20376f
	  break;
Packit Service 20376f
Packit Service 20376f
	default:
Packit Service 20376f
	    break;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  return (boundaries & 2) ? 1 : 0;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static int
Packit Service 20376f
internal_function
Packit Service 20376f
check_dst_limits_calc_pos (const re_match_context_t *mctx, int limit,
Packit Service 20376f
			   int subexp_idx, int from_node, int str_idx,
Packit Service 20376f
			   int bkref_idx)
Packit Service 20376f
{
Packit Service 20376f
  struct re_backref_cache_entry *lim = mctx->bkref_ents + limit;
Packit Service 20376f
  int boundaries;
Packit Service 20376f
Packit Service 20376f
  /* If we are outside the range of the subexpression, return -1 or 1.  */
Packit Service 20376f
  if (str_idx < lim->subexp_from)
Packit Service 20376f
    return -1;
Packit Service 20376f
Packit Service 20376f
  if (lim->subexp_to < str_idx)
Packit Service 20376f
    return 1;
Packit Service 20376f
Packit Service 20376f
  /* If we are within the subexpression, return 0.  */
Packit Service 20376f
  boundaries = (str_idx == lim->subexp_from);
Packit Service 20376f
  boundaries |= (str_idx == lim->subexp_to) << 1;
Packit Service 20376f
  if (boundaries == 0)
Packit Service 20376f
    return 0;
Packit Service 20376f
Packit Service 20376f
  /* Else, examine epsilon closure.  */
Packit Service 20376f
  return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx,
Packit Service 20376f
				      from_node, bkref_idx);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Check the limitations of sub expressions LIMITS, and remove the nodes
Packit Service 20376f
   which are against limitations from DEST_NODES. */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes,
Packit Service 20376f
		     const re_node_set *candidates, re_node_set *limits,
Packit Service 20376f
		     struct re_backref_cache_entry *bkref_ents, int str_idx)
Packit Service 20376f
{
Packit Service 20376f
  reg_errcode_t err;
Packit Service 20376f
  int node_idx, lim_idx;
Packit Service 20376f
Packit Service 20376f
  for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)
Packit Service 20376f
    {
Packit Service 20376f
      int subexp_idx;
Packit Service 20376f
      struct re_backref_cache_entry *ent;
Packit Service 20376f
      ent = bkref_ents + limits->elems[lim_idx];
Packit Service 20376f
Packit Service 20376f
      if (str_idx <= ent->subexp_from || ent->str_idx < str_idx)
Packit Service 20376f
	continue; /* This is unrelated limitation.  */
Packit Service 20376f
Packit Service 20376f
      subexp_idx = dfa->nodes[ent->node].opr.idx;
Packit Service 20376f
      if (ent->subexp_to == str_idx)
Packit Service 20376f
	{
Packit Service 20376f
	  int ops_node = -1;
Packit Service 20376f
	  int cls_node = -1;
Packit Service 20376f
	  for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
Packit Service 20376f
	    {
Packit Service 20376f
	      int node = dest_nodes->elems[node_idx];
Packit Service 20376f
	      re_token_type_t type = dfa->nodes[node].type;
Packit Service 20376f
	      if (type == OP_OPEN_SUBEXP
Packit Service 20376f
		  && subexp_idx == dfa->nodes[node].opr.idx)
Packit Service 20376f
		ops_node = node;
Packit Service 20376f
	      else if (type == OP_CLOSE_SUBEXP
Packit Service 20376f
		       && subexp_idx == dfa->nodes[node].opr.idx)
Packit Service 20376f
		cls_node = node;
Packit Service 20376f
	    }
Packit Service 20376f
Packit Service 20376f
	  /* Check the limitation of the open subexpression.  */
Packit Service 20376f
	  /* Note that (ent->subexp_to = str_idx != ent->subexp_from).  */
Packit Service 20376f
	  if (ops_node >= 0)
Packit Service 20376f
	    {
Packit Service 20376f
	      err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes,
Packit Service 20376f
					   candidates);
Packit Service 20376f
	      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
		return err;
Packit Service 20376f
	    }
Packit Service 20376f
Packit Service 20376f
	  /* Check the limitation of the close subexpression.  */
Packit Service 20376f
	  if (cls_node >= 0)
Packit Service 20376f
	    for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
Packit Service 20376f
	      {
Packit Service 20376f
		int node = dest_nodes->elems[node_idx];
Packit Service 20376f
		if (!re_node_set_contains (dfa->inveclosures + node,
Packit Service 20376f
					   cls_node)
Packit Service 20376f
		    && !re_node_set_contains (dfa->eclosures + node,
Packit Service 20376f
					      cls_node))
Packit Service 20376f
		  {
Packit Service 20376f
		    /* It is against this limitation.
Packit Service 20376f
		       Remove it form the current sifted state.  */
Packit Service 20376f
		    err = sub_epsilon_src_nodes (dfa, node, dest_nodes,
Packit Service 20376f
						 candidates);
Packit Service 20376f
		    if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
		      return err;
Packit Service 20376f
		    --node_idx;
Packit Service 20376f
		  }
Packit Service 20376f
	      }
Packit Service 20376f
	}
Packit Service 20376f
      else /* (ent->subexp_to != str_idx)  */
Packit Service 20376f
	{
Packit Service 20376f
	  for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)
Packit Service 20376f
	    {
Packit Service 20376f
	      int node = dest_nodes->elems[node_idx];
Packit Service 20376f
	      re_token_type_t type = dfa->nodes[node].type;
Packit Service 20376f
	      if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP)
Packit Service 20376f
		{
Packit Service 20376f
		  if (subexp_idx != dfa->nodes[node].opr.idx)
Packit Service 20376f
		    continue;
Packit Service 20376f
		  /* It is against this limitation.
Packit Service 20376f
		     Remove it form the current sifted state.  */
Packit Service 20376f
		  err = sub_epsilon_src_nodes (dfa, node, dest_nodes,
Packit Service 20376f
					       candidates);
Packit Service 20376f
		  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
		    return err;
Packit Service 20376f
		}
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx,
Packit Service 20376f
		   int str_idx, const re_node_set *candidates)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  reg_errcode_t err;
Packit Service 20376f
  int node_idx, node;
Packit Service 20376f
  re_sift_context_t local_sctx;
Packit Service 20376f
  int first_idx = search_cur_bkref_entry (mctx, str_idx);
Packit Service 20376f
Packit Service 20376f
  if (first_idx == -1)
Packit Service 20376f
    return REG_NOERROR;
Packit Service 20376f
Packit Service 20376f
  local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized.  */
Packit Service 20376f
Packit Service 20376f
  for (node_idx = 0; node_idx < candidates->nelem; ++node_idx)
Packit Service 20376f
    {
Packit Service 20376f
      int enabled_idx;
Packit Service 20376f
      re_token_type_t type;
Packit Service 20376f
      struct re_backref_cache_entry *entry;
Packit Service 20376f
      node = candidates->elems[node_idx];
Packit Service 20376f
      type = dfa->nodes[node].type;
Packit Service 20376f
      /* Avoid infinite loop for the REs like "()\1+".  */
Packit Service 20376f
      if (node == sctx->last_node && str_idx == sctx->last_str_idx)
Packit Service 20376f
	continue;
Packit Service 20376f
      if (type != OP_BACK_REF)
Packit Service 20376f
	continue;
Packit Service 20376f
Packit Service 20376f
      entry = mctx->bkref_ents + first_idx;
Packit Service 20376f
      enabled_idx = first_idx;
Packit Service 20376f
      do
Packit Service 20376f
	{
Packit Service 20376f
	  int subexp_len;
Packit Service 20376f
	  int to_idx;
Packit Service 20376f
	  int dst_node;
Packit Service 20376f
	  int ret;
Packit Service 20376f
	  re_dfastate_t *cur_state;
Packit Service 20376f
Packit Service 20376f
	  if (entry->node != node)
Packit Service 20376f
	    continue;
Packit Service 20376f
	  subexp_len = entry->subexp_to - entry->subexp_from;
Packit Service 20376f
	  to_idx = str_idx + subexp_len;
Packit Service 20376f
	  dst_node = (subexp_len ? dfa->nexts[node]
Packit Service 20376f
		      : dfa->edests[node].elems[0]);
Packit Service 20376f
Packit Service 20376f
	  if (to_idx > sctx->last_str_idx
Packit Service 20376f
	      || sctx->sifted_states[to_idx] == NULL
Packit Service 20376f
	      || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node)
Packit Service 20376f
	      || check_dst_limits (mctx, &sctx->limits, node,
Packit Service 20376f
				   str_idx, dst_node, to_idx))
Packit Service 20376f
	    continue;
Packit Service 20376f
Packit Service 20376f
	  if (local_sctx.sifted_states == NULL)
Packit Service 20376f
	    {
Packit Service 20376f
	      local_sctx = *sctx;
Packit Service 20376f
	      err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits);
Packit Service 20376f
	      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
		goto free_return;
Packit Service 20376f
	    }
Packit Service 20376f
	  local_sctx.last_node = node;
Packit Service 20376f
	  local_sctx.last_str_idx = str_idx;
Packit Service 20376f
	  ret = re_node_set_insert (&local_sctx.limits, enabled_idx);
Packit Service 20376f
	  if (BE (ret < 0, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      err = REG_ESPACE;
Packit Service 20376f
	      goto free_return;
Packit Service 20376f
	    }
Packit Service 20376f
	  cur_state = local_sctx.sifted_states[str_idx];
Packit Service 20376f
	  err = sift_states_backward (mctx, &local_sctx);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    goto free_return;
Packit Service 20376f
	  if (sctx->limited_states != NULL)
Packit Service 20376f
	    {
Packit Service 20376f
	      err = merge_state_array (dfa, sctx->limited_states,
Packit Service 20376f
				       local_sctx.sifted_states,
Packit Service 20376f
				       str_idx + 1);
Packit Service 20376f
	      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
		goto free_return;
Packit Service 20376f
	    }
Packit Service 20376f
	  local_sctx.sifted_states[str_idx] = cur_state;
Packit Service 20376f
	  re_node_set_remove (&local_sctx.limits, enabled_idx);
Packit Service 20376f
Packit Service 20376f
	  /* mctx->bkref_ents may have changed, reload the pointer.  */
Packit Service 20376f
	  entry = mctx->bkref_ents + enabled_idx;
Packit Service 20376f
	}
Packit Service 20376f
      while (enabled_idx++, entry++->more);
Packit Service 20376f
    }
Packit Service 20376f
  err = REG_NOERROR;
Packit Service 20376f
 free_return:
Packit Service 20376f
  if (local_sctx.sifted_states != NULL)
Packit Service 20376f
    {
Packit Service 20376f
      re_node_set_free (&local_sctx.limits);
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  return err;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
static int
Packit Service 20376f
internal_function
Packit Service 20376f
sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx,
Packit Service 20376f
		     int node_idx, int str_idx, int max_str_idx)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  int naccepted;
Packit Service 20376f
  /* Check the node can accept `multi byte'.  */
Packit Service 20376f
  naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx);
Packit Service 20376f
  if (naccepted > 0 && str_idx + naccepted <= max_str_idx &&
Packit Service 20376f
      !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted],
Packit Service 20376f
			    dfa->nexts[node_idx]))
Packit Service 20376f
    /* The node can't accept the `multi byte', or the
Packit Service 20376f
       destination was already thrown away, then the node
Packit Service 20376f
       could't accept the current input `multi byte'.   */
Packit Service 20376f
    naccepted = 0;
Packit Service 20376f
  /* Otherwise, it is sure that the node could accept
Packit Service 20376f
     `naccepted' bytes input.  */
Packit Service 20376f
  return naccepted;
Packit Service 20376f
}
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
Packit Service 20376f

Packit Service 20376f
/* Functions for state transition.  */
Packit Service 20376f
Packit Service 20376f
/* Return the next state to which the current state STATE will transit by
Packit Service 20376f
   accepting the current input byte, and update STATE_LOG if necessary.
Packit Service 20376f
   If STATE can accept a multibyte char/collating element/back reference
Packit Service 20376f
   update the destination of STATE_LOG.  */
Packit Service 20376f
Packit Service 20376f
static re_dfastate_t *
Packit Service 20376f
internal_function
Packit Service 20376f
transit_state (reg_errcode_t *err, re_match_context_t *mctx,
Packit Service 20376f
	       re_dfastate_t *state)
Packit Service 20376f
{
Packit Service 20376f
  re_dfastate_t **trtable;
Packit Service 20376f
  unsigned char ch;
Packit Service 20376f
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  /* If the current state can accept multibyte.  */
Packit Service 20376f
  if (BE (state->accept_mb, 0))
Packit Service 20376f
    {
Packit Service 20376f
      *err = transit_state_mb (mctx, state);
Packit Service 20376f
      if (BE (*err != REG_NOERROR, 0))
Packit Service 20376f
	return NULL;
Packit Service 20376f
    }
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
Packit Service 20376f
  /* Then decide the next state with the single byte.  */
Packit Service 20376f
#if 0
Packit Service 20376f
  if (0)
Packit Service 20376f
    /* don't use transition table  */
Packit Service 20376f
    return transit_state_sb (err, mctx, state);
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
  /* Use transition table  */
Packit Service 20376f
  ch = re_string_fetch_byte (&mctx->input);
Packit Service 20376f
  for (;;)
Packit Service 20376f
    {
Packit Service 20376f
      trtable = state->trtable;
Packit Service 20376f
      if (BE (trtable != NULL, 1))
Packit Service 20376f
	return trtable[ch];
Packit Service 20376f
Packit Service 20376f
      trtable = state->word_trtable;
Packit Service 20376f
      if (BE (trtable != NULL, 1))
Packit Service 20376f
	{
Packit Service 20376f
	  unsigned int context;
Packit Service 20376f
	  context
Packit Service 20376f
	    = re_string_context_at (&mctx->input,
Packit Service 20376f
				    re_string_cur_idx (&mctx->input) - 1,
Packit Service 20376f
				    mctx->eflags);
Packit Service 20376f
	  if (IS_WORD_CONTEXT (context))
Packit Service 20376f
	    return trtable[ch + SBC_MAX];
Packit Service 20376f
	  else
Packit Service 20376f
	    return trtable[ch];
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      if (!build_trtable (mctx->dfa, state))
Packit Service 20376f
	{
Packit Service 20376f
	  *err = REG_ESPACE;
Packit Service 20376f
	  return NULL;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      /* Retry, we now have a transition table.  */
Packit Service 20376f
    }
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Update the state_log if we need */
Packit Service 20376f
re_dfastate_t *
Packit Service 20376f
internal_function
Packit Service 20376f
merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx,
Packit Service 20376f
		      re_dfastate_t *next_state)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  int cur_idx = re_string_cur_idx (&mctx->input);
Packit Service 20376f
Packit Service 20376f
  if (cur_idx > mctx->state_log_top)
Packit Service 20376f
    {
Packit Service 20376f
      mctx->state_log[cur_idx] = next_state;
Packit Service 20376f
      mctx->state_log_top = cur_idx;
Packit Service 20376f
    }
Packit Service 20376f
  else if (mctx->state_log[cur_idx] == 0)
Packit Service 20376f
    {
Packit Service 20376f
      mctx->state_log[cur_idx] = next_state;
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
    {
Packit Service 20376f
      re_dfastate_t *pstate;
Packit Service 20376f
      unsigned int context;
Packit Service 20376f
      re_node_set next_nodes, *log_nodes, *table_nodes = NULL;
Packit Service 20376f
      /* If (state_log[cur_idx] != 0), it implies that cur_idx is
Packit Service 20376f
	 the destination of a multibyte char/collating element/
Packit Service 20376f
	 back reference.  Then the next state is the union set of
Packit Service 20376f
	 these destinations and the results of the transition table.  */
Packit Service 20376f
      pstate = mctx->state_log[cur_idx];
Packit Service 20376f
      log_nodes = pstate->entrance_nodes;
Packit Service 20376f
      if (next_state != NULL)
Packit Service 20376f
	{
Packit Service 20376f
	  table_nodes = next_state->entrance_nodes;
Packit Service 20376f
	  *err = re_node_set_init_union (&next_nodes, table_nodes,
Packit Service 20376f
					     log_nodes);
Packit Service 20376f
	  if (BE (*err != REG_NOERROR, 0))
Packit Service 20376f
	    return NULL;
Packit Service 20376f
	}
Packit Service 20376f
      else
Packit Service 20376f
	next_nodes = *log_nodes;
Packit Service 20376f
      /* Note: We already add the nodes of the initial state,
Packit Service 20376f
	 then we don't need to add them here.  */
Packit Service 20376f
Packit Service 20376f
      context = re_string_context_at (&mctx->input,
Packit Service 20376f
				      re_string_cur_idx (&mctx->input) - 1,
Packit Service 20376f
				      mctx->eflags);
Packit Service 20376f
      next_state = mctx->state_log[cur_idx]
Packit Service 20376f
	= re_acquire_state_context (err, dfa, &next_nodes, context);
Packit Service 20376f
      /* We don't need to check errors here, since the return value of
Packit Service 20376f
	 this function is next_state and ERR is already set.  */
Packit Service 20376f
Packit Service 20376f
      if (table_nodes != NULL)
Packit Service 20376f
	re_node_set_free (&next_nodes);
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  if (BE (dfa->nbackref, 0) && next_state != NULL)
Packit Service 20376f
    {
Packit Service 20376f
      /* Check OP_OPEN_SUBEXP in the current state in case that we use them
Packit Service 20376f
	 later.  We must check them here, since the back references in the
Packit Service 20376f
	 next state might use them.  */
Packit Service 20376f
      *err = check_subexp_matching_top (mctx, &next_state->nodes,
Packit Service 20376f
					cur_idx);
Packit Service 20376f
      if (BE (*err != REG_NOERROR, 0))
Packit Service 20376f
	return NULL;
Packit Service 20376f
Packit Service 20376f
      /* If the next state has back references.  */
Packit Service 20376f
      if (next_state->has_backref)
Packit Service 20376f
	{
Packit Service 20376f
	  *err = transit_state_bkref (mctx, &next_state->nodes);
Packit Service 20376f
	  if (BE (*err != REG_NOERROR, 0))
Packit Service 20376f
	    return NULL;
Packit Service 20376f
	  next_state = mctx->state_log[cur_idx];
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  return next_state;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Skip bytes in the input that correspond to part of a
Packit Service 20376f
   multi-byte match, then look in the log for a state
Packit Service 20376f
   from which to restart matching.  */
Packit Service 20376f
re_dfastate_t *
Packit Service 20376f
internal_function
Packit Service 20376f
find_recover_state (reg_errcode_t *err, re_match_context_t *mctx)
Packit Service 20376f
{
Packit Service 20376f
  re_dfastate_t *cur_state;
Packit Service 20376f
  do
Packit Service 20376f
    {
Packit Service 20376f
      int max = mctx->state_log_top;
Packit Service 20376f
      int cur_str_idx = re_string_cur_idx (&mctx->input);
Packit Service 20376f
Packit Service 20376f
      do
Packit Service 20376f
	{
Packit Service 20376f
	  if (++cur_str_idx > max)
Packit Service 20376f
	    return NULL;
Packit Service 20376f
	  re_string_skip_bytes (&mctx->input, 1);
Packit Service 20376f
	}
Packit Service 20376f
      while (mctx->state_log[cur_str_idx] == NULL);
Packit Service 20376f
Packit Service 20376f
      cur_state = merge_state_with_log (err, mctx, NULL);
Packit Service 20376f
    }
Packit Service 20376f
  while (*err == REG_NOERROR && cur_state == NULL);
Packit Service 20376f
  return cur_state;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Helper functions for transit_state.  */
Packit Service 20376f
Packit Service 20376f
/* From the node set CUR_NODES, pick up the nodes whose types are
Packit Service 20376f
   OP_OPEN_SUBEXP and which have corresponding back references in the regular
Packit Service 20376f
   expression. And register them to use them later for evaluating the
Packit Service 20376f
   correspoding back references.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes,
Packit Service 20376f
			   int str_idx)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  int node_idx;
Packit Service 20376f
  reg_errcode_t err;
Packit Service 20376f
Packit Service 20376f
  /* TODO: This isn't efficient.
Packit Service 20376f
	   Because there might be more than one nodes whose types are
Packit Service 20376f
	   OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all
Packit Service 20376f
	   nodes.
Packit Service 20376f
	   E.g. RE: (a){2}  */
Packit Service 20376f
  for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx)
Packit Service 20376f
    {
Packit Service 20376f
      int node = cur_nodes->elems[node_idx];
Packit Service 20376f
      if (dfa->nodes[node].type == OP_OPEN_SUBEXP
Packit Service 20376f
	  && dfa->nodes[node].opr.idx < BITSET_WORD_BITS
Packit Service 20376f
	  && (dfa->used_bkref_map
Packit Service 20376f
	      & ((bitset_word_t) 1 << dfa->nodes[node].opr.idx)))
Packit Service 20376f
	{
Packit Service 20376f
	  err = match_ctx_add_subtop (mctx, node, str_idx);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    return err;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
#if 0
Packit Service 20376f
/* Return the next state to which the current state STATE will transit by
Packit Service 20376f
   accepting the current input byte.  */
Packit Service 20376f
Packit Service 20376f
static re_dfastate_t *
Packit Service 20376f
transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx,
Packit Service 20376f
		  re_dfastate_t *state)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  re_node_set next_nodes;
Packit Service 20376f
  re_dfastate_t *next_state;
Packit Service 20376f
  int node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input);
Packit Service 20376f
  unsigned int context;
Packit Service 20376f
Packit Service 20376f
  *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1);
Packit Service 20376f
  if (BE (*err != REG_NOERROR, 0))
Packit Service 20376f
    return NULL;
Packit Service 20376f
  for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt)
Packit Service 20376f
    {
Packit Service 20376f
      int cur_node = state->nodes.elems[node_cnt];
Packit Service 20376f
      if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx))
Packit Service 20376f
	{
Packit Service 20376f
	  *err = re_node_set_merge (&next_nodes,
Packit Service 20376f
				    dfa->eclosures + dfa->nexts[cur_node]);
Packit Service 20376f
	  if (BE (*err != REG_NOERROR, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      re_node_set_free (&next_nodes);
Packit Service 20376f
	      return NULL;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags);
Packit Service 20376f
  next_state = re_acquire_state_context (err, dfa, &next_nodes, context);
Packit Service 20376f
  /* We don't need to check errors here, since the return value of
Packit Service 20376f
     this function is next_state and ERR is already set.  */
Packit Service 20376f
Packit Service 20376f
  re_node_set_free (&next_nodes);
Packit Service 20376f
  re_string_skip_bytes (&mctx->input, 1);
Packit Service 20376f
  return next_state;
Packit Service 20376f
}
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  reg_errcode_t err;
Packit Service 20376f
  int i;
Packit Service 20376f
Packit Service 20376f
  for (i = 0; i < pstate->nodes.nelem; ++i)
Packit Service 20376f
    {
Packit Service 20376f
      re_node_set dest_nodes, *new_nodes;
Packit Service 20376f
      int cur_node_idx = pstate->nodes.elems[i];
Packit Service 20376f
      int naccepted, dest_idx;
Packit Service 20376f
      unsigned int context;
Packit Service 20376f
      re_dfastate_t *dest_state;
Packit Service 20376f
Packit Service 20376f
      if (!dfa->nodes[cur_node_idx].accept_mb)
Packit Service 20376f
	continue;
Packit Service 20376f
Packit Service 20376f
      if (dfa->nodes[cur_node_idx].constraint)
Packit Service 20376f
	{
Packit Service 20376f
	  context = re_string_context_at (&mctx->input,
Packit Service 20376f
					  re_string_cur_idx (&mctx->input),
Packit Service 20376f
					  mctx->eflags);
Packit Service 20376f
	  if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint,
Packit Service 20376f
					   context))
Packit Service 20376f
	    continue;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      /* How many bytes the node can accept?  */
Packit Service 20376f
      naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input,
Packit Service 20376f
					   re_string_cur_idx (&mctx->input));
Packit Service 20376f
      if (naccepted == 0)
Packit Service 20376f
	continue;
Packit Service 20376f
Packit Service 20376f
      /* The node can accepts `naccepted' bytes.  */
Packit Service 20376f
      dest_idx = re_string_cur_idx (&mctx->input) + naccepted;
Packit Service 20376f
      mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted
Packit Service 20376f
			       : mctx->max_mb_elem_len);
Packit Service 20376f
      err = clean_state_log_if_needed (mctx, dest_idx);
Packit Service 20376f
      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	return err;
Packit Service 20376f
#ifdef DEBUG
Packit Service 20376f
      assert (dfa->nexts[cur_node_idx] != -1);
Packit Service 20376f
#endif
Packit Service 20376f
      new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx];
Packit Service 20376f
Packit Service 20376f
      dest_state = mctx->state_log[dest_idx];
Packit Service 20376f
      if (dest_state == NULL)
Packit Service 20376f
	dest_nodes = *new_nodes;
Packit Service 20376f
      else
Packit Service 20376f
	{
Packit Service 20376f
	  err = re_node_set_init_union (&dest_nodes,
Packit Service 20376f
					dest_state->entrance_nodes, new_nodes);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    return err;
Packit Service 20376f
	}
Packit Service 20376f
      context = re_string_context_at (&mctx->input, dest_idx - 1,
Packit Service 20376f
				      mctx->eflags);
Packit Service 20376f
      mctx->state_log[dest_idx]
Packit Service 20376f
	= re_acquire_state_context (&err, dfa, &dest_nodes, context);
Packit Service 20376f
      if (dest_state != NULL)
Packit Service 20376f
	re_node_set_free (&dest_nodes);
Packit Service 20376f
      if (BE (mctx->state_log[dest_idx] == NULL && err != REG_NOERROR, 0))
Packit Service 20376f
	return err;
Packit Service 20376f
    }
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  reg_errcode_t err;
Packit Service 20376f
  int i;
Packit Service 20376f
  int cur_str_idx = re_string_cur_idx (&mctx->input);
Packit Service 20376f
Packit Service 20376f
  for (i = 0; i < nodes->nelem; ++i)
Packit Service 20376f
    {
Packit Service 20376f
      int dest_str_idx, prev_nelem, bkc_idx;
Packit Service 20376f
      int node_idx = nodes->elems[i];
Packit Service 20376f
      unsigned int context;
Packit Service 20376f
      const re_token_t *node = dfa->nodes + node_idx;
Packit Service 20376f
      re_node_set *new_dest_nodes;
Packit Service 20376f
Packit Service 20376f
      /* Check whether `node' is a backreference or not.  */
Packit Service 20376f
      if (node->type != OP_BACK_REF)
Packit Service 20376f
	continue;
Packit Service 20376f
Packit Service 20376f
      if (node->constraint)
Packit Service 20376f
	{
Packit Service 20376f
	  context = re_string_context_at (&mctx->input, cur_str_idx,
Packit Service 20376f
					  mctx->eflags);
Packit Service 20376f
	  if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context))
Packit Service 20376f
	    continue;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      /* `node' is a backreference.
Packit Service 20376f
	 Check the substring which the substring matched.  */
Packit Service 20376f
      bkc_idx = mctx->nbkref_ents;
Packit Service 20376f
      err = get_subexp (mctx, node_idx, cur_str_idx);
Packit Service 20376f
      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	goto free_return;
Packit Service 20376f
Packit Service 20376f
      /* And add the epsilon closures (which is `new_dest_nodes') of
Packit Service 20376f
	 the backreference to appropriate state_log.  */
Packit Service 20376f
#ifdef DEBUG
Packit Service 20376f
      assert (dfa->nexts[node_idx] != -1);
Packit Service 20376f
#endif
Packit Service 20376f
      for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx)
Packit Service 20376f
	{
Packit Service 20376f
	  int subexp_len;
Packit Service 20376f
	  re_dfastate_t *dest_state;
Packit Service 20376f
	  struct re_backref_cache_entry *bkref_ent;
Packit Service 20376f
	  bkref_ent = mctx->bkref_ents + bkc_idx;
Packit Service 20376f
	  if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx)
Packit Service 20376f
	    continue;
Packit Service 20376f
	  subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from;
Packit Service 20376f
	  new_dest_nodes = (subexp_len == 0
Packit Service 20376f
			    ? dfa->eclosures + dfa->edests[node_idx].elems[0]
Packit Service 20376f
			    : dfa->eclosures + dfa->nexts[node_idx]);
Packit Service 20376f
	  dest_str_idx = (cur_str_idx + bkref_ent->subexp_to
Packit Service 20376f
			  - bkref_ent->subexp_from);
Packit Service 20376f
	  context = re_string_context_at (&mctx->input, dest_str_idx - 1,
Packit Service 20376f
					  mctx->eflags);
Packit Service 20376f
	  dest_state = mctx->state_log[dest_str_idx];
Packit Service 20376f
	  prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0
Packit Service 20376f
			: mctx->state_log[cur_str_idx]->nodes.nelem);
Packit Service 20376f
	  /* Add `new_dest_node' to state_log.  */
Packit Service 20376f
	  if (dest_state == NULL)
Packit Service 20376f
	    {
Packit Service 20376f
	      mctx->state_log[dest_str_idx]
Packit Service 20376f
		= re_acquire_state_context (&err, dfa, new_dest_nodes,
Packit Service 20376f
					    context);
Packit Service 20376f
	      if (BE (mctx->state_log[dest_str_idx] == NULL
Packit Service 20376f
		      && err != REG_NOERROR, 0))
Packit Service 20376f
		goto free_return;
Packit Service 20376f
	    }
Packit Service 20376f
	  else
Packit Service 20376f
	    {
Packit Service 20376f
	      re_node_set dest_nodes;
Packit Service 20376f
	      err = re_node_set_init_union (&dest_nodes,
Packit Service 20376f
					    dest_state->entrance_nodes,
Packit Service 20376f
					    new_dest_nodes);
Packit Service 20376f
	      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
		{
Packit Service 20376f
		  re_node_set_free (&dest_nodes);
Packit Service 20376f
		  goto free_return;
Packit Service 20376f
		}
Packit Service 20376f
	      mctx->state_log[dest_str_idx]
Packit Service 20376f
		= re_acquire_state_context (&err, dfa, &dest_nodes, context);
Packit Service 20376f
	      re_node_set_free (&dest_nodes);
Packit Service 20376f
	      if (BE (mctx->state_log[dest_str_idx] == NULL
Packit Service 20376f
		      && err != REG_NOERROR, 0))
Packit Service 20376f
		goto free_return;
Packit Service 20376f
	    }
Packit Service 20376f
	  /* We need to check recursively if the backreference can epsilon
Packit Service 20376f
	     transit.  */
Packit Service 20376f
	  if (subexp_len == 0
Packit Service 20376f
	      && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem)
Packit Service 20376f
	    {
Packit Service 20376f
	      err = check_subexp_matching_top (mctx, new_dest_nodes,
Packit Service 20376f
					       cur_str_idx);
Packit Service 20376f
	      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
		goto free_return;
Packit Service 20376f
	      err = transit_state_bkref (mctx, new_dest_nodes);
Packit Service 20376f
	      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
		goto free_return;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  err = REG_NOERROR;
Packit Service 20376f
 free_return:
Packit Service 20376f
  return err;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Enumerate all the candidates which the backreference BKREF_NODE can match
Packit Service 20376f
   at BKREF_STR_IDX, and register them by match_ctx_add_entry().
Packit Service 20376f
   Note that we might collect inappropriate candidates here.
Packit Service 20376f
   However, the cost of checking them strictly here is too high, then we
Packit Service 20376f
   delay these checking for prune_impossible_nodes().  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  int subexp_num, sub_top_idx;
Packit Service 20376f
  const char *buf = (const char *) re_string_get_buffer (&mctx->input);
Packit Service 20376f
  /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX.  */
Packit Service 20376f
  int cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx);
Packit Service 20376f
  if (cache_idx != -1)
Packit Service 20376f
    {
Packit Service 20376f
      const struct re_backref_cache_entry *entry
Packit Service 20376f
	= mctx->bkref_ents + cache_idx;
Packit Service 20376f
      do
Packit Service 20376f
	if (entry->node == bkref_node)
Packit Service 20376f
	  return REG_NOERROR; /* We already checked it.  */
Packit Service 20376f
      while (entry++->more);
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  subexp_num = dfa->nodes[bkref_node].opr.idx;
Packit Service 20376f
Packit Service 20376f
  /* For each sub expression  */
Packit Service 20376f
  for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx)
Packit Service 20376f
    {
Packit Service 20376f
      reg_errcode_t err;
Packit Service 20376f
      re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx];
Packit Service 20376f
      re_sub_match_last_t *sub_last;
Packit Service 20376f
      int sub_last_idx, sl_str, bkref_str_off;
Packit Service 20376f
Packit Service 20376f
      if (dfa->nodes[sub_top->node].opr.idx != subexp_num)
Packit Service 20376f
	continue; /* It isn't related.  */
Packit Service 20376f
Packit Service 20376f
      sl_str = sub_top->str_idx;
Packit Service 20376f
      bkref_str_off = bkref_str_idx;
Packit Service 20376f
      /* At first, check the last node of sub expressions we already
Packit Service 20376f
	 evaluated.  */
Packit Service 20376f
      for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx)
Packit Service 20376f
	{
Packit Service 20376f
	  int sl_str_diff;
Packit Service 20376f
	  sub_last = sub_top->lasts[sub_last_idx];
Packit Service 20376f
	  sl_str_diff = sub_last->str_idx - sl_str;
Packit Service 20376f
	  /* The matched string by the sub expression match with the substring
Packit Service 20376f
	     at the back reference?  */
Packit Service 20376f
	  if (sl_str_diff > 0)
Packit Service 20376f
	    {
Packit Service 20376f
	      if (BE (bkref_str_off + sl_str_diff > mctx->input.valid_len, 0))
Packit Service 20376f
		{
Packit Service 20376f
		  /* Not enough chars for a successful match.  */
Packit Service 20376f
		  if (bkref_str_off + sl_str_diff > mctx->input.len)
Packit Service 20376f
		    break;
Packit Service 20376f
Packit Service 20376f
		  err = clean_state_log_if_needed (mctx,
Packit Service 20376f
						   bkref_str_off
Packit Service 20376f
						   + sl_str_diff);
Packit Service 20376f
		  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
		    return err;
Packit Service 20376f
		  buf = (const char *) re_string_get_buffer (&mctx->input);
Packit Service 20376f
		}
Packit Service 20376f
	      if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0)
Packit Service 20376f
		/* We don't need to search this sub expression any more.  */
Packit Service 20376f
		break;
Packit Service 20376f
	    }
Packit Service 20376f
	  bkref_str_off += sl_str_diff;
Packit Service 20376f
	  sl_str += sl_str_diff;
Packit Service 20376f
	  err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node,
Packit Service 20376f
				bkref_str_idx);
Packit Service 20376f
Packit Service 20376f
	  /* Reload buf, since the preceding call might have reallocated
Packit Service 20376f
	     the buffer.  */
Packit Service 20376f
	  buf = (const char *) re_string_get_buffer (&mctx->input);
Packit Service 20376f
Packit Service 20376f
	  if (err == REG_NOMATCH)
Packit Service 20376f
	    continue;
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    return err;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      if (sub_last_idx < sub_top->nlasts)
Packit Service 20376f
	continue;
Packit Service 20376f
      if (sub_last_idx > 0)
Packit Service 20376f
	++sl_str;
Packit Service 20376f
      /* Then, search for the other last nodes of the sub expression.  */
Packit Service 20376f
      for (; sl_str <= bkref_str_idx; ++sl_str)
Packit Service 20376f
	{
Packit Service 20376f
	  int cls_node, sl_str_off;
Packit Service 20376f
	  const re_node_set *nodes;
Packit Service 20376f
	  sl_str_off = sl_str - sub_top->str_idx;
Packit Service 20376f
	  /* The matched string by the sub expression match with the substring
Packit Service 20376f
	     at the back reference?  */
Packit Service 20376f
	  if (sl_str_off > 0)
Packit Service 20376f
	    {
Packit Service 20376f
	      if (BE (bkref_str_off >= mctx->input.valid_len, 0))
Packit Service 20376f
		{
Packit Service 20376f
		  /* If we are at the end of the input, we cannot match.  */
Packit Service 20376f
		  if (bkref_str_off >= mctx->input.len)
Packit Service 20376f
		    break;
Packit Service 20376f
Packit Service 20376f
		  err = extend_buffers (mctx);
Packit Service 20376f
		  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
		    return err;
Packit Service 20376f
Packit Service 20376f
		  buf = (const char *) re_string_get_buffer (&mctx->input);
Packit Service 20376f
		}
Packit Service 20376f
	      if (buf [bkref_str_off++] != buf[sl_str - 1])
Packit Service 20376f
		break; /* We don't need to search this sub expression
Packit Service 20376f
			  any more.  */
Packit Service 20376f
	    }
Packit Service 20376f
	  if (mctx->state_log[sl_str] == NULL)
Packit Service 20376f
	    continue;
Packit Service 20376f
	  /* Does this state have a ')' of the sub expression?  */
Packit Service 20376f
	  nodes = &mctx->state_log[sl_str]->nodes;
Packit Service 20376f
	  cls_node = find_subexp_node (dfa, nodes, subexp_num,
Packit Service 20376f
				       OP_CLOSE_SUBEXP);
Packit Service 20376f
	  if (cls_node == -1)
Packit Service 20376f
	    continue; /* No.  */
Packit Service 20376f
	  if (sub_top->path == NULL)
Packit Service 20376f
	    {
Packit Service 20376f
	      sub_top->path = calloc (sizeof (state_array_t),
Packit Service 20376f
				      sl_str - sub_top->str_idx + 1);
Packit Service 20376f
	      if (sub_top->path == NULL)
Packit Service 20376f
		return REG_ESPACE;
Packit Service 20376f
	    }
Packit Service 20376f
	  /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node
Packit Service 20376f
	     in the current context?  */
Packit Service 20376f
	  err = check_arrival (mctx, sub_top->path, sub_top->node,
Packit Service 20376f
			       sub_top->str_idx, cls_node, sl_str,
Packit Service 20376f
			       OP_CLOSE_SUBEXP);
Packit Service 20376f
	  if (err == REG_NOMATCH)
Packit Service 20376f
	      continue;
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	      return err;
Packit Service 20376f
	  sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str);
Packit Service 20376f
	  if (BE (sub_last == NULL, 0))
Packit Service 20376f
	    return REG_ESPACE;
Packit Service 20376f
	  err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node,
Packit Service 20376f
				bkref_str_idx);
Packit Service 20376f
	  if (err == REG_NOMATCH)
Packit Service 20376f
	    continue;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Helper functions for get_subexp().  */
Packit Service 20376f
Packit Service 20376f
/* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR.
Packit Service 20376f
   If it can arrive, register the sub expression expressed with SUB_TOP
Packit Service 20376f
   and SUB_LAST.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top,
Packit Service 20376f
		re_sub_match_last_t *sub_last, int bkref_node, int bkref_str)
Packit Service 20376f
{
Packit Service 20376f
  reg_errcode_t err;
Packit Service 20376f
  int to_idx;
Packit Service 20376f
  /* Can the subexpression arrive the back reference?  */
Packit Service 20376f
  err = check_arrival (mctx, &sub_last->path, sub_last->node,
Packit Service 20376f
		       sub_last->str_idx, bkref_node, bkref_str,
Packit Service 20376f
		       OP_OPEN_SUBEXP);
Packit Service 20376f
  if (err != REG_NOERROR)
Packit Service 20376f
    return err;
Packit Service 20376f
  err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx,
Packit Service 20376f
			     sub_last->str_idx);
Packit Service 20376f
  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
    return err;
Packit Service 20376f
  to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx;
Packit Service 20376f
  return clean_state_log_if_needed (mctx, to_idx);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX.
Packit Service 20376f
   Search '(' if FL_OPEN, or search ')' otherwise.
Packit Service 20376f
   TODO: This function isn't efficient...
Packit Service 20376f
	 Because there might be more than one nodes whose types are
Packit Service 20376f
	 OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all
Packit Service 20376f
	 nodes.
Packit Service 20376f
	 E.g. RE: (a){2}  */
Packit Service 20376f
Packit Service 20376f
static int
Packit Service 20376f
internal_function
Packit Service 20376f
find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,
Packit Service 20376f
		  int subexp_idx, int type)
Packit Service 20376f
{
Packit Service 20376f
  int cls_idx;
Packit Service 20376f
  for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx)
Packit Service 20376f
    {
Packit Service 20376f
      int cls_node = nodes->elems[cls_idx];
Packit Service 20376f
      const re_token_t *node = dfa->nodes + cls_node;
Packit Service 20376f
      if (node->type == type
Packit Service 20376f
	  && node->opr.idx == subexp_idx)
Packit Service 20376f
	return cls_node;
Packit Service 20376f
    }
Packit Service 20376f
  return -1;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Check whether the node TOP_NODE at TOP_STR can arrive to the node
Packit Service 20376f
   LAST_NODE at LAST_STR.  We record the path onto PATH since it will be
Packit Service 20376f
   heavily reused.
Packit Service 20376f
   Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node,
Packit Service 20376f
	       int top_str, int last_node, int last_str, int type)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  reg_errcode_t err = REG_NOERROR;
Packit Service 20376f
  int subexp_num, backup_cur_idx, str_idx, null_cnt;
Packit Service 20376f
  re_dfastate_t *cur_state = NULL;
Packit Service 20376f
  re_node_set *cur_nodes, next_nodes;
Packit Service 20376f
  re_dfastate_t **backup_state_log;
Packit Service 20376f
  unsigned int context;
Packit Service 20376f
Packit Service 20376f
  subexp_num = dfa->nodes[top_node].opr.idx;
Packit Service 20376f
  /* Extend the buffer if we need.  */
Packit Service 20376f
  if (BE (path->alloc < last_str + mctx->max_mb_elem_len + 1, 0))
Packit Service 20376f
    {
Packit Service 20376f
      re_dfastate_t **new_array;
Packit Service 20376f
      int old_alloc = path->alloc;
Packit Service 20376f
      path->alloc += last_str + mctx->max_mb_elem_len + 1;
Packit Service 20376f
      new_array = re_realloc (path->array, re_dfastate_t *, path->alloc);
Packit Service 20376f
      if (BE (new_array == NULL, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  path->alloc = old_alloc;
Packit Service 20376f
	  return REG_ESPACE;
Packit Service 20376f
	}
Packit Service 20376f
      path->array = new_array;
Packit Service 20376f
      memset (new_array + old_alloc, '\0',
Packit Service 20376f
	      sizeof (re_dfastate_t *) * (path->alloc - old_alloc));
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  str_idx = path->next_idx ? path->next_idx : top_str;
Packit Service 20376f
Packit Service 20376f
  /* Temporary modify MCTX.  */
Packit Service 20376f
  backup_state_log = mctx->state_log;
Packit Service 20376f
  backup_cur_idx = mctx->input.cur_idx;
Packit Service 20376f
  mctx->state_log = path->array;
Packit Service 20376f
  mctx->input.cur_idx = str_idx;
Packit Service 20376f
Packit Service 20376f
  /* Setup initial node set.  */
Packit Service 20376f
  context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags);
Packit Service 20376f
  if (str_idx == top_str)
Packit Service 20376f
    {
Packit Service 20376f
      err = re_node_set_init_1 (&next_nodes, top_node);
Packit Service 20376f
      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	return err;
Packit Service 20376f
      err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type);
Packit Service 20376f
      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  re_node_set_free (&next_nodes);
Packit Service 20376f
	  return err;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
    {
Packit Service 20376f
      cur_state = mctx->state_log[str_idx];
Packit Service 20376f
      if (cur_state && cur_state->has_backref)
Packit Service 20376f
	{
Packit Service 20376f
	  err = re_node_set_init_copy (&next_nodes, &cur_state->nodes);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    return err;
Packit Service 20376f
	}
Packit Service 20376f
      else
Packit Service 20376f
	re_node_set_init_empty (&next_nodes);
Packit Service 20376f
    }
Packit Service 20376f
  if (str_idx == top_str || (cur_state && cur_state->has_backref))
Packit Service 20376f
    {
Packit Service 20376f
      if (next_nodes.nelem)
Packit Service 20376f
	{
Packit Service 20376f
	  err = expand_bkref_cache (mctx, &next_nodes, str_idx,
Packit Service 20376f
				    subexp_num, type);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      re_node_set_free (&next_nodes);
Packit Service 20376f
	      return err;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
      cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context);
Packit Service 20376f
      if (BE (cur_state == NULL && err != REG_NOERROR, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  re_node_set_free (&next_nodes);
Packit Service 20376f
	  return err;
Packit Service 20376f
	}
Packit Service 20376f
      mctx->state_log[str_idx] = cur_state;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;)
Packit Service 20376f
    {
Packit Service 20376f
      re_node_set_empty (&next_nodes);
Packit Service 20376f
      if (mctx->state_log[str_idx + 1])
Packit Service 20376f
	{
Packit Service 20376f
	  err = re_node_set_merge (&next_nodes,
Packit Service 20376f
				   &mctx->state_log[str_idx + 1]->nodes);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      re_node_set_free (&next_nodes);
Packit Service 20376f
	      return err;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
      if (cur_state)
Packit Service 20376f
	{
Packit Service 20376f
	  err = check_arrival_add_next_nodes (mctx, str_idx,
Packit Service 20376f
					      &cur_state->non_eps_nodes,
Packit Service 20376f
					      &next_nodes);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      re_node_set_free (&next_nodes);
Packit Service 20376f
	      return err;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
      ++str_idx;
Packit Service 20376f
      if (next_nodes.nelem)
Packit Service 20376f
	{
Packit Service 20376f
	  err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      re_node_set_free (&next_nodes);
Packit Service 20376f
	      return err;
Packit Service 20376f
	    }
Packit Service 20376f
	  err = expand_bkref_cache (mctx, &next_nodes, str_idx,
Packit Service 20376f
				    subexp_num, type);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      re_node_set_free (&next_nodes);
Packit Service 20376f
	      return err;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
      context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags);
Packit Service 20376f
      cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context);
Packit Service 20376f
      if (BE (cur_state == NULL && err != REG_NOERROR, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  re_node_set_free (&next_nodes);
Packit Service 20376f
	  return err;
Packit Service 20376f
	}
Packit Service 20376f
      mctx->state_log[str_idx] = cur_state;
Packit Service 20376f
      null_cnt = cur_state == NULL ? null_cnt + 1 : 0;
Packit Service 20376f
    }
Packit Service 20376f
  re_node_set_free (&next_nodes);
Packit Service 20376f
  cur_nodes = (mctx->state_log[last_str] == NULL ? NULL
Packit Service 20376f
	       : &mctx->state_log[last_str]->nodes);
Packit Service 20376f
  path->next_idx = str_idx;
Packit Service 20376f
Packit Service 20376f
  /* Fix MCTX.  */
Packit Service 20376f
  mctx->state_log = backup_state_log;
Packit Service 20376f
  mctx->input.cur_idx = backup_cur_idx;
Packit Service 20376f
Packit Service 20376f
  /* Then check the current node set has the node LAST_NODE.  */
Packit Service 20376f
  if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node))
Packit Service 20376f
    return REG_NOERROR;
Packit Service 20376f
Packit Service 20376f
  return REG_NOMATCH;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Helper functions for check_arrival.  */
Packit Service 20376f
Packit Service 20376f
/* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them
Packit Service 20376f
   to NEXT_NODES.
Packit Service 20376f
   TODO: This function is similar to the functions transit_state*(),
Packit Service 20376f
	 however this function has many additional works.
Packit Service 20376f
	 Can't we unify them?  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx,
Packit Service 20376f
			      re_node_set *cur_nodes, re_node_set *next_nodes)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  int result;
Packit Service 20376f
  int cur_idx;
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  reg_errcode_t err = REG_NOERROR;
Packit Service 20376f
#endif
Packit Service 20376f
  re_node_set union_set;
Packit Service 20376f
  re_node_set_init_empty (&union_set);
Packit Service 20376f
  for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx)
Packit Service 20376f
    {
Packit Service 20376f
      int naccepted = 0;
Packit Service 20376f
      int cur_node = cur_nodes->elems[cur_idx];
Packit Service 20376f
#ifdef DEBUG
Packit Service 20376f
      re_token_type_t type = dfa->nodes[cur_node].type;
Packit Service 20376f
      assert (!IS_EPSILON_NODE (type));
Packit Service 20376f
#endif
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
      /* If the node may accept `multi byte'.  */
Packit Service 20376f
      if (dfa->nodes[cur_node].accept_mb)
Packit Service 20376f
	{
Packit Service 20376f
	  naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input,
Packit Service 20376f
					       str_idx);
Packit Service 20376f
	  if (naccepted > 1)
Packit Service 20376f
	    {
Packit Service 20376f
	      re_dfastate_t *dest_state;
Packit Service 20376f
	      int next_node = dfa->nexts[cur_node];
Packit Service 20376f
	      int next_idx = str_idx + naccepted;
Packit Service 20376f
	      dest_state = mctx->state_log[next_idx];
Packit Service 20376f
	      re_node_set_empty (&union_set);
Packit Service 20376f
	      if (dest_state)
Packit Service 20376f
		{
Packit Service 20376f
		  err = re_node_set_merge (&union_set, &dest_state->nodes);
Packit Service 20376f
		  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
		    {
Packit Service 20376f
		      re_node_set_free (&union_set);
Packit Service 20376f
		      return err;
Packit Service 20376f
		    }
Packit Service 20376f
		}
Packit Service 20376f
	      result = re_node_set_insert (&union_set, next_node);
Packit Service 20376f
	      if (BE (result < 0, 0))
Packit Service 20376f
		{
Packit Service 20376f
		  re_node_set_free (&union_set);
Packit Service 20376f
		  return REG_ESPACE;
Packit Service 20376f
		}
Packit Service 20376f
	      mctx->state_log[next_idx] = re_acquire_state (&err, dfa,
Packit Service 20376f
							    &union_set);
Packit Service 20376f
	      if (BE (mctx->state_log[next_idx] == NULL
Packit Service 20376f
		      && err != REG_NOERROR, 0))
Packit Service 20376f
		{
Packit Service 20376f
		  re_node_set_free (&union_set);
Packit Service 20376f
		  return err;
Packit Service 20376f
		}
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
      if (naccepted
Packit Service 20376f
	  || check_node_accept (mctx, dfa->nodes + cur_node, str_idx))
Packit Service 20376f
	{
Packit Service 20376f
	  result = re_node_set_insert (next_nodes, dfa->nexts[cur_node]);
Packit Service 20376f
	  if (BE (result < 0, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      re_node_set_free (&union_set);
Packit Service 20376f
	      return REG_ESPACE;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  re_node_set_free (&union_set);
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* For all the nodes in CUR_NODES, add the epsilon closures of them to
Packit Service 20376f
   CUR_NODES, however exclude the nodes which are:
Packit Service 20376f
    - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN.
Packit Service 20376f
    - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN.
Packit Service 20376f
*/
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes,
Packit Service 20376f
			  int ex_subexp, int type)
Packit Service 20376f
{
Packit Service 20376f
  reg_errcode_t err;
Packit Service 20376f
  int idx, outside_node;
Packit Service 20376f
  re_node_set new_nodes;
Packit Service 20376f
#ifdef DEBUG
Packit Service 20376f
  assert (cur_nodes->nelem);
Packit Service 20376f
#endif
Packit Service 20376f
  err = re_node_set_alloc (&new_nodes, cur_nodes->nelem);
Packit Service 20376f
  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
    return err;
Packit Service 20376f
  /* Create a new node set NEW_NODES with the nodes which are epsilon
Packit Service 20376f
     closures of the node in CUR_NODES.  */
Packit Service 20376f
Packit Service 20376f
  for (idx = 0; idx < cur_nodes->nelem; ++idx)
Packit Service 20376f
    {
Packit Service 20376f
      int cur_node = cur_nodes->elems[idx];
Packit Service 20376f
      const re_node_set *eclosure = dfa->eclosures + cur_node;
Packit Service 20376f
      outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type);
Packit Service 20376f
      if (outside_node == -1)
Packit Service 20376f
	{
Packit Service 20376f
	  /* There are no problematic nodes, just merge them.  */
Packit Service 20376f
	  err = re_node_set_merge (&new_nodes, eclosure);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      re_node_set_free (&new_nodes);
Packit Service 20376f
	      return err;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
      else
Packit Service 20376f
	{
Packit Service 20376f
	  /* There are problematic nodes, re-calculate incrementally.  */
Packit Service 20376f
	  err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node,
Packit Service 20376f
					      ex_subexp, type);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      re_node_set_free (&new_nodes);
Packit Service 20376f
	      return err;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  re_node_set_free (cur_nodes);
Packit Service 20376f
  *cur_nodes = new_nodes;
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Helper function for check_arrival_expand_ecl.
Packit Service 20376f
   Check incrementally the epsilon closure of TARGET, and if it isn't
Packit Service 20376f
   problematic append it to DST_NODES.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes,
Packit Service 20376f
			      int target, int ex_subexp, int type)
Packit Service 20376f
{
Packit Service 20376f
  int cur_node;
Packit Service 20376f
  for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);)
Packit Service 20376f
    {
Packit Service 20376f
      int err;
Packit Service 20376f
Packit Service 20376f
      if (dfa->nodes[cur_node].type == type
Packit Service 20376f
	  && dfa->nodes[cur_node].opr.idx == ex_subexp)
Packit Service 20376f
	{
Packit Service 20376f
	  if (type == OP_CLOSE_SUBEXP)
Packit Service 20376f
	    {
Packit Service 20376f
	      err = re_node_set_insert (dst_nodes, cur_node);
Packit Service 20376f
	      if (BE (err == -1, 0))
Packit Service 20376f
		return REG_ESPACE;
Packit Service 20376f
	    }
Packit Service 20376f
	  break;
Packit Service 20376f
	}
Packit Service 20376f
      err = re_node_set_insert (dst_nodes, cur_node);
Packit Service 20376f
      if (BE (err == -1, 0))
Packit Service 20376f
	return REG_ESPACE;
Packit Service 20376f
      if (dfa->edests[cur_node].nelem == 0)
Packit Service 20376f
	break;
Packit Service 20376f
      if (dfa->edests[cur_node].nelem == 2)
Packit Service 20376f
	{
Packit Service 20376f
	  err = check_arrival_expand_ecl_sub (dfa, dst_nodes,
Packit Service 20376f
					      dfa->edests[cur_node].elems[1],
Packit Service 20376f
					      ex_subexp, type);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    return err;
Packit Service 20376f
	}
Packit Service 20376f
      cur_node = dfa->edests[cur_node].elems[0];
Packit Service 20376f
    }
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
Packit Service 20376f
/* For all the back references in the current state, calculate the
Packit Service 20376f
   destination of the back references by the appropriate entry
Packit Service 20376f
   in MCTX->BKREF_ENTS.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes,
Packit Service 20376f
		    int cur_str, int subexp_num, int type)
Packit Service 20376f
{
Packit Service 20376f
  const re_dfa_t *const dfa = mctx->dfa;
Packit Service 20376f
  reg_errcode_t err;
Packit Service 20376f
  int cache_idx_start = search_cur_bkref_entry (mctx, cur_str);
Packit Service 20376f
  struct re_backref_cache_entry *ent;
Packit Service 20376f
Packit Service 20376f
  if (cache_idx_start == -1)
Packit Service 20376f
    return REG_NOERROR;
Packit Service 20376f
Packit Service 20376f
 restart:
Packit Service 20376f
  ent = mctx->bkref_ents + cache_idx_start;
Packit Service 20376f
  do
Packit Service 20376f
    {
Packit Service 20376f
      int to_idx, next_node;
Packit Service 20376f
Packit Service 20376f
      /* Is this entry ENT is appropriate?  */
Packit Service 20376f
      if (!re_node_set_contains (cur_nodes, ent->node))
Packit Service 20376f
	continue; /* No.  */
Packit Service 20376f
Packit Service 20376f
      to_idx = cur_str + ent->subexp_to - ent->subexp_from;
Packit Service 20376f
      /* Calculate the destination of the back reference, and append it
Packit Service 20376f
	 to MCTX->STATE_LOG.  */
Packit Service 20376f
      if (to_idx == cur_str)
Packit Service 20376f
	{
Packit Service 20376f
	  /* The backreference did epsilon transit, we must re-check all the
Packit Service 20376f
	     node in the current state.  */
Packit Service 20376f
	  re_node_set new_dests;
Packit Service 20376f
	  reg_errcode_t err2, err3;
Packit Service 20376f
	  next_node = dfa->edests[ent->node].elems[0];
Packit Service 20376f
	  if (re_node_set_contains (cur_nodes, next_node))
Packit Service 20376f
	    continue;
Packit Service