Blame deps/regex/regcomp.c

Packit Service 20376f
/* Extended regular expression matching and search library.
Packit Service 20376f
   Copyright (C) 2002-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 re_compile_internal (regex_t *preg, const char * pattern,
Packit Service 20376f
					  size_t length, reg_syntax_t syntax);
Packit Service 20376f
static void re_compile_fastmap_iter (regex_t *bufp,
Packit Service 20376f
				     const re_dfastate_t *init_state,
Packit Service 20376f
				     char *fastmap);
Packit Service 20376f
static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len);
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
static void free_charset (re_charset_t *cset);
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
static void free_workarea_compile (regex_t *preg);
Packit Service 20376f
static reg_errcode_t create_initial_state (re_dfa_t *dfa);
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
static void optimize_utf8 (re_dfa_t *dfa);
Packit Service 20376f
#endif
Packit Service 20376f
static reg_errcode_t analyze (regex_t *preg);
Packit Service 20376f
static reg_errcode_t preorder (bin_tree_t *root,
Packit Service 20376f
			       reg_errcode_t (fn (void *, bin_tree_t *)),
Packit Service 20376f
			       void *extra);
Packit Service 20376f
static reg_errcode_t postorder (bin_tree_t *root,
Packit Service 20376f
				reg_errcode_t (fn (void *, bin_tree_t *)),
Packit Service 20376f
				void *extra);
Packit Service 20376f
static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node);
Packit Service 20376f
static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node);
Packit Service 20376f
static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg,
Packit Service 20376f
				 bin_tree_t *node);
Packit Service 20376f
static reg_errcode_t calc_first (void *extra, bin_tree_t *node);
Packit Service 20376f
static reg_errcode_t calc_next (void *extra, bin_tree_t *node);
Packit Service 20376f
static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node);
Packit Service 20376f
static int duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint);
Packit Service 20376f
static int search_duplicated_node (const re_dfa_t *dfa, int org_node,
Packit Service 20376f
				   unsigned int constraint);
Packit Service 20376f
static reg_errcode_t calc_eclosure (re_dfa_t *dfa);
Packit Service 20376f
static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa,
Packit Service 20376f
					 int node, int root);
Packit Service 20376f
static reg_errcode_t calc_inveclosure (re_dfa_t *dfa);
Packit Service 20376f
static int fetch_number (re_string_t *input, re_token_t *token,
Packit Service 20376f
			 reg_syntax_t syntax);
Packit Service 20376f
static int peek_token (re_token_t *token, re_string_t *input,
Packit Service 20376f
			reg_syntax_t syntax) internal_function;
Packit Service 20376f
static bin_tree_t *parse (re_string_t *regexp, regex_t *preg,
Packit Service 20376f
			  reg_syntax_t syntax, reg_errcode_t *err);
Packit Service 20376f
static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg,
Packit Service 20376f
				  re_token_t *token, reg_syntax_t syntax,
Packit Service 20376f
				  int nest, reg_errcode_t *err);
Packit Service 20376f
static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg,
Packit Service 20376f
				 re_token_t *token, reg_syntax_t syntax,
Packit Service 20376f
				 int nest, reg_errcode_t *err);
Packit Service 20376f
static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg,
Packit Service 20376f
				     re_token_t *token, reg_syntax_t syntax,
Packit Service 20376f
				     int nest, reg_errcode_t *err);
Packit Service 20376f
static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg,
Packit Service 20376f
				  re_token_t *token, reg_syntax_t syntax,
Packit Service 20376f
				  int nest, reg_errcode_t *err);
Packit Service 20376f
static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp,
Packit Service 20376f
				 re_dfa_t *dfa, re_token_t *token,
Packit Service 20376f
				 reg_syntax_t syntax, reg_errcode_t *err);
Packit Service 20376f
static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa,
Packit Service 20376f
				      re_token_t *token, reg_syntax_t syntax,
Packit Service 20376f
				      reg_errcode_t *err);
Packit Service 20376f
static reg_errcode_t parse_bracket_element (bracket_elem_t *elem,
Packit Service 20376f
					    re_string_t *regexp,
Packit Service 20376f
					    re_token_t *token, int token_len,
Packit Service 20376f
					    re_dfa_t *dfa,
Packit Service 20376f
					    reg_syntax_t syntax,
Packit Service 20376f
					    int accept_hyphen);
Packit Service 20376f
static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem,
Packit Service 20376f
					  re_string_t *regexp,
Packit Service 20376f
					  re_token_t *token);
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
static reg_errcode_t build_equiv_class (bitset_t sbcset,
Packit Service 20376f
					re_charset_t *mbcset,
Packit Service 20376f
					int *equiv_class_alloc,
Packit Service 20376f
					const unsigned char *name);
Packit Service 20376f
static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans,
Packit Service 20376f
				      bitset_t sbcset,
Packit Service 20376f
				      re_charset_t *mbcset,
Packit Service 20376f
				      int *char_class_alloc,
Packit Service 20376f
				      const char *class_name,
Packit Service 20376f
				      reg_syntax_t syntax);
Packit Service 20376f
#else  /* not RE_ENABLE_I18N */
Packit Service 20376f
static reg_errcode_t build_equiv_class (bitset_t sbcset,
Packit Service 20376f
					const unsigned char *name);
Packit Service 20376f
static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans,
Packit Service 20376f
				      bitset_t sbcset,
Packit Service 20376f
				      const char *class_name,
Packit Service 20376f
				      reg_syntax_t syntax);
Packit Service 20376f
#endif /* not RE_ENABLE_I18N */
Packit Service 20376f
static bin_tree_t *build_charclass_op (re_dfa_t *dfa,
Packit Service 20376f
				       RE_TRANSLATE_TYPE trans,
Packit Service 20376f
				       const char *class_name,
Packit Service 20376f
				       const char *extra,
Packit Service 20376f
				       int non_match, reg_errcode_t *err);
Packit Service 20376f
static bin_tree_t *create_tree (re_dfa_t *dfa,
Packit Service 20376f
				bin_tree_t *left, bin_tree_t *right,
Packit Service 20376f
				re_token_type_t type);
Packit Service 20376f
static bin_tree_t *create_token_tree (re_dfa_t *dfa,
Packit Service 20376f
				      bin_tree_t *left, bin_tree_t *right,
Packit Service 20376f
				      const re_token_t *token);
Packit Service 20376f
static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa);
Packit Service 20376f
static void free_token (re_token_t *node);
Packit Service 20376f
static reg_errcode_t free_tree (void *extra, bin_tree_t *node);
Packit Service 20376f
static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node);
Packit Service 20376f

Packit Service 20376f
/* This table gives an error message for each of the error codes listed
Packit Service 20376f
   in regex.h.  Obviously the order here has to be same as there.
Packit Service 20376f
   POSIX doesn't require that we do anything for REG_NOERROR,
Packit Service 20376f
   but why not be nice?  */
Packit Service 20376f
Packit Service 20376f
const char __re_error_msgid[] attribute_hidden =
Packit Service 20376f
  {
Packit Service 20376f
#define REG_NOERROR_IDX	0
Packit Service 20376f
    gettext_noop ("Success")	/* REG_NOERROR */
Packit Service 20376f
    "\0"
Packit Service 20376f
#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success")
Packit Service 20376f
    gettext_noop ("No match")	/* REG_NOMATCH */
Packit Service 20376f
    "\0"
Packit Service 20376f
#define REG_BADPAT_IDX	(REG_NOMATCH_IDX + sizeof "No match")
Packit Service 20376f
    gettext_noop ("Invalid regular expression") /* REG_BADPAT */
Packit Service 20376f
    "\0"
Packit Service 20376f
#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression")
Packit Service 20376f
    gettext_noop ("Invalid collation character") /* REG_ECOLLATE */
Packit Service 20376f
    "\0"
Packit Service 20376f
#define REG_ECTYPE_IDX	(REG_ECOLLATE_IDX + sizeof "Invalid collation character")
Packit Service 20376f
    gettext_noop ("Invalid character class name") /* REG_ECTYPE */
Packit Service 20376f
    "\0"
Packit Service 20376f
#define REG_EESCAPE_IDX	(REG_ECTYPE_IDX + sizeof "Invalid character class name")
Packit Service 20376f
    gettext_noop ("Trailing backslash") /* REG_EESCAPE */
Packit Service 20376f
    "\0"
Packit Service 20376f
#define REG_ESUBREG_IDX	(REG_EESCAPE_IDX + sizeof "Trailing backslash")
Packit Service 20376f
    gettext_noop ("Invalid back reference") /* REG_ESUBREG */
Packit Service 20376f
    "\0"
Packit Service 20376f
#define REG_EBRACK_IDX	(REG_ESUBREG_IDX + sizeof "Invalid back reference")
Packit Service 20376f
    gettext_noop ("Unmatched [ or [^")	/* REG_EBRACK */
Packit Service 20376f
    "\0"
Packit Service 20376f
#define REG_EPAREN_IDX	(REG_EBRACK_IDX + sizeof "Unmatched [ or [^")
Packit Service 20376f
    gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */
Packit Service 20376f
    "\0"
Packit Service 20376f
#define REG_EBRACE_IDX	(REG_EPAREN_IDX + sizeof "Unmatched ( or \\(")
Packit Service 20376f
    gettext_noop ("Unmatched \\{") /* REG_EBRACE */
Packit Service 20376f
    "\0"
Packit Service 20376f
#define REG_BADBR_IDX	(REG_EBRACE_IDX + sizeof "Unmatched \\{")
Packit Service 20376f
    gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */
Packit Service 20376f
    "\0"
Packit Service 20376f
#define REG_ERANGE_IDX	(REG_BADBR_IDX + sizeof "Invalid content of \\{\\}")
Packit Service 20376f
    gettext_noop ("Invalid range end")	/* REG_ERANGE */
Packit Service 20376f
    "\0"
Packit Service 20376f
#define REG_ESPACE_IDX	(REG_ERANGE_IDX + sizeof "Invalid range end")
Packit Service 20376f
    gettext_noop ("Memory exhausted") /* REG_ESPACE */
Packit Service 20376f
    "\0"
Packit Service 20376f
#define REG_BADRPT_IDX	(REG_ESPACE_IDX + sizeof "Memory exhausted")
Packit Service 20376f
    gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */
Packit Service 20376f
    "\0"
Packit Service 20376f
#define REG_EEND_IDX	(REG_BADRPT_IDX + sizeof "Invalid preceding regular expression")
Packit Service 20376f
    gettext_noop ("Premature end of regular expression") /* REG_EEND */
Packit Service 20376f
    "\0"
Packit Service 20376f
#define REG_ESIZE_IDX	(REG_EEND_IDX + sizeof "Premature end of regular expression")
Packit Service 20376f
    gettext_noop ("Regular expression too big") /* REG_ESIZE */
Packit Service 20376f
    "\0"
Packit Service 20376f
#define REG_ERPAREN_IDX	(REG_ESIZE_IDX + sizeof "Regular expression too big")
Packit Service 20376f
    gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */
Packit Service 20376f
  };
Packit Service 20376f
Packit Service 20376f
const size_t __re_error_msgid_idx[] attribute_hidden =
Packit Service 20376f
  {
Packit Service 20376f
    REG_NOERROR_IDX,
Packit Service 20376f
    REG_NOMATCH_IDX,
Packit Service 20376f
    REG_BADPAT_IDX,
Packit Service 20376f
    REG_ECOLLATE_IDX,
Packit Service 20376f
    REG_ECTYPE_IDX,
Packit Service 20376f
    REG_EESCAPE_IDX,
Packit Service 20376f
    REG_ESUBREG_IDX,
Packit Service 20376f
    REG_EBRACK_IDX,
Packit Service 20376f
    REG_EPAREN_IDX,
Packit Service 20376f
    REG_EBRACE_IDX,
Packit Service 20376f
    REG_BADBR_IDX,
Packit Service 20376f
    REG_ERANGE_IDX,
Packit Service 20376f
    REG_ESPACE_IDX,
Packit Service 20376f
    REG_BADRPT_IDX,
Packit Service 20376f
    REG_EEND_IDX,
Packit Service 20376f
    REG_ESIZE_IDX,
Packit Service 20376f
    REG_ERPAREN_IDX
Packit Service 20376f
  };
Packit Service 20376f

Packit Service 20376f
/* Entry points for GNU code.  */
Packit Service 20376f
Packit Service 20376f
Packit Service 20376f
#ifdef ZOS_USS
Packit Service 20376f
Packit Service 20376f
/* For ZOS USS we must define btowc */
Packit Service 20376f
Packit Service 20376f
wchar_t 
Packit Service 20376f
btowc (int c)
Packit Service 20376f
{
Packit Service 20376f
   wchar_t wtmp[2];
Packit Service 20376f
   char tmp[2];
Packit Service 20376f
Packit Service 20376f
   tmp[0] = c;
Packit Service 20376f
   tmp[1] = 0;
Packit Service 20376f
Packit Service 20376f
   mbtowc (wtmp, tmp, 1);
Packit Service 20376f
   return wtmp[0];
Packit Service 20376f
}
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
/* re_compile_pattern is the GNU regular expression compiler: it
Packit Service 20376f
   compiles PATTERN (of length LENGTH) and puts the result in BUFP.
Packit Service 20376f
   Returns 0 if the pattern was valid, otherwise an error string.
Packit Service 20376f
Packit Service 20376f
   Assumes the `allocated' (and perhaps `buffer') and `translate' fields
Packit Service 20376f
   are set in BUFP on entry.  */
Packit Service 20376f
Packit Service 20376f
const char *
Packit Service 20376f
re_compile_pattern (const char *pattern,
Packit Service 20376f
		    size_t length,
Packit Service 20376f
		    struct re_pattern_buffer *bufp)
Packit Service 20376f
{
Packit Service 20376f
  reg_errcode_t ret;
Packit Service 20376f
Packit Service 20376f
  /* And GNU code determines whether or not to get register information
Packit Service 20376f
     by passing null for the REGS argument to re_match, etc., not by
Packit Service 20376f
     setting no_sub, unless RE_NO_SUB is set.  */
Packit Service 20376f
  bufp->no_sub = !!(re_syntax_options & RE_NO_SUB);
Packit Service 20376f
Packit Service 20376f
  /* Match anchors at newline.  */
Packit Service 20376f
  bufp->newline_anchor = 1;
Packit Service 20376f
Packit Service 20376f
  ret = re_compile_internal (bufp, pattern, length, re_syntax_options);
Packit Service 20376f
Packit Service 20376f
  if (!ret)
Packit Service 20376f
    return NULL;
Packit Service 20376f
  return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
Packit Service 20376f
}
Packit Service 20376f
#ifdef _LIBC
Packit Service 20376f
weak_alias (__re_compile_pattern, re_compile_pattern)
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
/* Set by `re_set_syntax' to the current regexp syntax to recognize.  Can
Packit Service 20376f
   also be assigned to arbitrarily: each pattern buffer stores its own
Packit Service 20376f
   syntax, so it can be changed between regex compilations.  */
Packit Service 20376f
/* This has no initializer because initialized variables in Emacs
Packit Service 20376f
   become read-only after dumping.  */
Packit Service 20376f
reg_syntax_t re_syntax_options;
Packit Service 20376f
Packit Service 20376f
Packit Service 20376f
/* Specify the precise syntax of regexps for compilation.  This provides
Packit Service 20376f
   for compatibility for various utilities which historically have
Packit Service 20376f
   different, incompatible syntaxes.
Packit Service 20376f
Packit Service 20376f
   The argument SYNTAX is a bit mask comprised of the various bits
Packit Service 20376f
   defined in regex.h.  We return the old syntax.  */
Packit Service 20376f
Packit Service 20376f
reg_syntax_t
Packit Service 20376f
re_set_syntax (reg_syntax_t syntax)
Packit Service 20376f
{
Packit Service 20376f
  reg_syntax_t ret = re_syntax_options;
Packit Service 20376f
Packit Service 20376f
  re_syntax_options = syntax;
Packit Service 20376f
  return ret;
Packit Service 20376f
}
Packit Service 20376f
#ifdef _LIBC
Packit Service 20376f
weak_alias (__re_set_syntax, re_set_syntax)
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
int
Packit Service 20376f
re_compile_fastmap (struct re_pattern_buffer *bufp)
Packit Service 20376f
{
Packit Service 20376f
  re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
Packit Service 20376f
  char *fastmap = bufp->fastmap;
Packit Service 20376f
Packit Service 20376f
  memset (fastmap, '\0', sizeof (char) * SBC_MAX);
Packit Service 20376f
  re_compile_fastmap_iter (bufp, dfa->init_state, fastmap);
Packit Service 20376f
  if (dfa->init_state != dfa->init_state_word)
Packit Service 20376f
    re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap);
Packit Service 20376f
  if (dfa->init_state != dfa->init_state_nl)
Packit Service 20376f
    re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap);
Packit Service 20376f
  if (dfa->init_state != dfa->init_state_begbuf)
Packit Service 20376f
    re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap);
Packit Service 20376f
  bufp->fastmap_accurate = 1;
Packit Service 20376f
  return 0;
Packit Service 20376f
}
Packit Service 20376f
#ifdef _LIBC
Packit Service 20376f
weak_alias (__re_compile_fastmap, re_compile_fastmap)
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
static inline void
Packit Service 20376f
__attribute ((always_inline))
Packit Service 20376f
re_set_fastmap (char *fastmap, int icase, int ch)
Packit Service 20376f
{
Packit Service 20376f
  fastmap[ch] = 1;
Packit Service 20376f
  if (icase)
Packit Service 20376f
    fastmap[tolower (ch)] = 1;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Helper function for re_compile_fastmap.
Packit Service 20376f
   Compile fastmap for the initial_state INIT_STATE.  */
Packit Service 20376f
Packit Service 20376f
static void
Packit Service 20376f
re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
Packit Service 20376f
			 char *fastmap)
Packit Service 20376f
{
Packit Service 20376f
  volatile re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;
Packit Service 20376f
  int node_cnt;
Packit Service 20376f
  int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE));
Packit Service 20376f
  for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt)
Packit Service 20376f
    {
Packit Service 20376f
      int node = init_state->nodes.elems[node_cnt];
Packit Service 20376f
      re_token_type_t type = dfa->nodes[node].type;
Packit Service 20376f
Packit Service 20376f
      if (type == CHARACTER)
Packit Service 20376f
	{
Packit Service 20376f
	  re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c);
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
	  if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
Packit Service 20376f
	    {
Packit Service 20376f
	      unsigned char *buf = re_malloc (unsigned char, dfa->mb_cur_max), *p;
Packit Service 20376f
	      wchar_t wc;
Packit Service 20376f
	      mbstate_t state;
Packit Service 20376f
Packit Service 20376f
	      p = buf;
Packit Service 20376f
	      *p++ = dfa->nodes[node].opr.c;
Packit Service 20376f
	      while (++node < dfa->nodes_len
Packit Service 20376f
		     &&	dfa->nodes[node].type == CHARACTER
Packit Service 20376f
		     && dfa->nodes[node].mb_partial)
Packit Service 20376f
		*p++ = dfa->nodes[node].opr.c;
Packit Service 20376f
	      memset (&state, '\0', sizeof (state));
Packit Service 20376f
	      if (__mbrtowc (&wc, (const char *) buf, p - buf,
Packit Service 20376f
			     &state) == p - buf
Packit Service 20376f
		  && (__wcrtomb ((char *) buf, towlower (wc), &state)
Packit Service 20376f
		      != (size_t) -1))
Packit Service 20376f
		re_set_fastmap (fastmap, 0, buf[0]);
Packit Service 20376f
	      re_free (buf);
Packit Service 20376f
	    }
Packit Service 20376f
#endif
Packit Service 20376f
	}
Packit Service 20376f
      else if (type == SIMPLE_BRACKET)
Packit Service 20376f
	{
Packit Service 20376f
	  int i, ch;
Packit Service 20376f
	  for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
Packit Service 20376f
	    {
Packit Service 20376f
	      int j;
Packit Service 20376f
	      bitset_word_t w = dfa->nodes[node].opr.sbcset[i];
Packit Service 20376f
	      for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
Packit Service 20376f
		if (w & ((bitset_word_t) 1 << j))
Packit Service 20376f
		  re_set_fastmap (fastmap, icase, ch);
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
      else if (type == COMPLEX_BRACKET)
Packit Service 20376f
	{
Packit Service 20376f
	  re_charset_t *cset = dfa->nodes[node].opr.mbcset;
Packit Service 20376f
	  int i;
Packit Service 20376f
Packit Service 20376f
# ifdef _LIBC
Packit Service 20376f
	  /* See if we have to try all bytes which start multiple collation
Packit Service 20376f
	     elements.
Packit Service 20376f
	     e.g. In da_DK, we want to catch 'a' since "aa" is a valid
Packit Service 20376f
		  collation element, and don't catch 'b' since 'b' is
Packit Service 20376f
		  the only collation element which starts from 'b' (and
Packit Service 20376f
		  it is caught by SIMPLE_BRACKET).  */
Packit Service 20376f
	      if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0
Packit Service 20376f
		  && (cset->ncoll_syms || cset->nranges))
Packit Service 20376f
		{
Packit Service 20376f
		  const int32_t *table = (const int32_t *)
Packit Service 20376f
		    _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
Packit Service 20376f
		  for (i = 0; i < SBC_MAX; ++i)
Packit Service 20376f
		    if (table[i] < 0)
Packit Service 20376f
		      re_set_fastmap (fastmap, icase, i);
Packit Service 20376f
		}
Packit Service 20376f
# endif /* _LIBC */
Packit Service 20376f
Packit Service 20376f
	  /* See if we have to start the match at all multibyte characters,
Packit Service 20376f
	     i.e. where we would not find an invalid sequence.  This only
Packit Service 20376f
	     applies to multibyte character sets; for single byte character
Packit Service 20376f
	     sets, the SIMPLE_BRACKET again suffices.  */
Packit Service 20376f
	  if (dfa->mb_cur_max > 1
Packit Service 20376f
	      && (cset->nchar_classes || cset->non_match || cset->nranges
Packit Service 20376f
# ifdef _LIBC
Packit Service 20376f
		  || cset->nequiv_classes
Packit Service 20376f
# endif /* _LIBC */
Packit Service 20376f
		 ))
Packit Service 20376f
	    {
Packit Service 20376f
	      unsigned char c = 0;
Packit Service 20376f
	      do
Packit Service 20376f
		{
Packit Service 20376f
		  mbstate_t mbs;
Packit Service 20376f
		  memset (&mbs, 0, sizeof (mbs));
Packit Service 20376f
		  if (__mbrtowc (NULL, (char *) &c, 1, &mbs) == (size_t) -2)
Packit Service 20376f
		    re_set_fastmap (fastmap, false, (int) c);
Packit Service 20376f
		}
Packit Service 20376f
	      while (++c != 0);
Packit Service 20376f
	    }
Packit Service 20376f
Packit Service 20376f
	  else
Packit Service 20376f
	    {
Packit Service 20376f
	      /* ... Else catch all bytes which can start the mbchars.  */
Packit Service 20376f
	      for (i = 0; i < cset->nmbchars; ++i)
Packit Service 20376f
		{
Packit Service 20376f
		  char buf[256];
Packit Service 20376f
		  mbstate_t state;
Packit Service 20376f
		  memset (&state, '\0', sizeof (state));
Packit Service 20376f
		  if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1)
Packit Service 20376f
		    re_set_fastmap (fastmap, icase, *(unsigned char *) buf);
Packit Service 20376f
		  if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
Packit Service 20376f
		    {
Packit Service 20376f
		      if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state)
Packit Service 20376f
			  != (size_t) -1)
Packit Service 20376f
			re_set_fastmap (fastmap, false, *(unsigned char *) buf);
Packit Service 20376f
		    }
Packit Service 20376f
		}
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
      else if (type == OP_PERIOD
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
	       || type == OP_UTF8_PERIOD
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
	       || type == END_OF_RE)
Packit Service 20376f
	{
Packit Service 20376f
	  memset (fastmap, '\1', sizeof (char) * SBC_MAX);
Packit Service 20376f
	  if (type == END_OF_RE)
Packit Service 20376f
	    bufp->can_be_null = 1;
Packit Service 20376f
	  return;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
}
Packit Service 20376f

Packit Service 20376f
/* Entry point for POSIX code.  */
Packit Service 20376f
/* regcomp takes a regular expression as a string and compiles it.
Packit Service 20376f
Packit Service 20376f
   PREG is a regex_t *.  We do not expect any fields to be initialized,
Packit Service 20376f
   since POSIX says we shouldn't.  Thus, we set
Packit Service 20376f
Packit Service 20376f
     `buffer' to the compiled pattern;
Packit Service 20376f
     `used' to the length of the compiled pattern;
Packit Service 20376f
     `syntax' to RE_SYNTAX_POSIX_EXTENDED if the
Packit Service 20376f
       REG_EXTENDED bit in CFLAGS is set; otherwise, to
Packit Service 20376f
       RE_SYNTAX_POSIX_BASIC;
Packit Service 20376f
     `newline_anchor' to REG_NEWLINE being set in CFLAGS;
Packit Service 20376f
     `fastmap' to an allocated space for the fastmap;
Packit Service 20376f
     `fastmap_accurate' to zero;
Packit Service 20376f
     `re_nsub' to the number of subexpressions in PATTERN.
Packit Service 20376f
Packit Service 20376f
   PATTERN is the address of the pattern string.
Packit Service 20376f
Packit Service 20376f
   CFLAGS is a series of bits which affect compilation.
Packit Service 20376f
Packit Service 20376f
     If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
Packit Service 20376f
     use POSIX basic syntax.
Packit Service 20376f
Packit Service 20376f
     If REG_NEWLINE is set, then . and [^...] don't match newline.
Packit Service 20376f
     Also, regexec will try a match beginning after every newline.
Packit Service 20376f
Packit Service 20376f
     If REG_ICASE is set, then we considers upper- and lowercase
Packit Service 20376f
     versions of letters to be equivalent when matching.
Packit Service 20376f
Packit Service 20376f
     If REG_NOSUB is set, then when PREG is passed to regexec, that
Packit Service 20376f
     routine will report only success or failure, and nothing about the
Packit Service 20376f
     registers.
Packit Service 20376f
Packit Service 20376f
   It returns 0 if it succeeds, nonzero if it doesn't.  (See regex.h for
Packit Service 20376f
   the return codes and their meanings.)  */
Packit Service 20376f
Packit Service 20376f
int
Packit Service 20376f
regcomp (regex_t *__restrict preg,
Packit Service 20376f
	 const char *__restrict pattern,
Packit Service 20376f
	 int cflags)
Packit Service 20376f
{
Packit Service 20376f
  reg_errcode_t ret;
Packit Service 20376f
  reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED
Packit Service 20376f
			 : RE_SYNTAX_POSIX_BASIC);
Packit Service 20376f
Packit Service 20376f
  preg->buffer = NULL;
Packit Service 20376f
  preg->allocated = 0;
Packit Service 20376f
  preg->used = 0;
Packit Service 20376f
Packit Service 20376f
  /* Try to allocate space for the fastmap.  */
Packit Service 20376f
  preg->fastmap = re_malloc (char, SBC_MAX);
Packit Service 20376f
  if (BE (preg->fastmap == NULL, 0))
Packit Service 20376f
    return REG_ESPACE;
Packit Service 20376f
Packit Service 20376f
  syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0;
Packit Service 20376f
Packit Service 20376f
  /* If REG_NEWLINE is set, newlines are treated differently.  */
Packit Service 20376f
  if (cflags & REG_NEWLINE)
Packit Service 20376f
    { /* REG_NEWLINE implies neither . nor [^...] match newline.  */
Packit Service 20376f
      syntax &= ~RE_DOT_NEWLINE;
Packit Service 20376f
      syntax |= RE_HAT_LISTS_NOT_NEWLINE;
Packit Service 20376f
      /* It also changes the matching behavior.  */
Packit Service 20376f
      preg->newline_anchor = 1;
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
    preg->newline_anchor = 0;
Packit Service 20376f
  preg->no_sub = !!(cflags & REG_NOSUB);
Packit Service 20376f
  preg->translate = NULL;
Packit Service 20376f
Packit Service 20376f
  ret = re_compile_internal (preg, pattern, strlen (pattern), syntax);
Packit Service 20376f
Packit Service 20376f
  /* POSIX doesn't distinguish between an unmatched open-group and an
Packit Service 20376f
     unmatched close-group: both are REG_EPAREN.  */
Packit Service 20376f
  if (ret == REG_ERPAREN)
Packit Service 20376f
    ret = REG_EPAREN;
Packit Service 20376f
Packit Service 20376f
  /* We have already checked preg->fastmap != NULL.  */
Packit Service 20376f
  if (BE (ret == REG_NOERROR, 1))
Packit Service 20376f
    /* Compute the fastmap now, since regexec cannot modify the pattern
Packit Service 20376f
       buffer.  This function never fails in this implementation.  */
Packit Service 20376f
    (void) re_compile_fastmap (preg);
Packit Service 20376f
  else
Packit Service 20376f
    {
Packit Service 20376f
      /* Some error occurred while compiling the expression.  */
Packit Service 20376f
      re_free (preg->fastmap);
Packit Service 20376f
      preg->fastmap = NULL;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  return (int) ret;
Packit Service 20376f
}
Packit Service 20376f
#ifdef _LIBC
Packit Service 20376f
weak_alias (__regcomp, regcomp)
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
/* Returns a message corresponding to an error code, ERRCODE, returned
Packit Service 20376f
   from either regcomp or regexec.   We don't use PREG here.  */
Packit Service 20376f
Packit Service 20376f
size_t
Packit Service 20376f
regerror(int errcode, UNUSED const regex_t *__restrict preg,
Packit Service 20376f
	 char *__restrict errbuf, size_t errbuf_size)
Packit Service 20376f
{
Packit Service 20376f
  const char *msg;
Packit Service 20376f
  size_t msg_size;
Packit Service 20376f
Packit Service 20376f
  if (BE (errcode < 0
Packit Service 20376f
	  || errcode >= (int) (sizeof (__re_error_msgid_idx)
Packit Service 20376f
			       / sizeof (__re_error_msgid_idx[0])), 0))
Packit Service 20376f
    /* Only error codes returned by the rest of the code should be passed
Packit Service 20376f
       to this routine.  If we are given anything else, or if other regex
Packit Service 20376f
       code generates an invalid error code, then the program has a bug.
Packit Service 20376f
       Dump core so we can fix it.  */
Packit Service 20376f
    abort ();
Packit Service 20376f
Packit Service 20376f
  msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]);
Packit Service 20376f
Packit Service 20376f
  msg_size = strlen (msg) + 1; /* Includes the null.  */
Packit Service 20376f
Packit Service 20376f
  if (BE (errbuf_size != 0, 1))
Packit Service 20376f
    {
Packit Service 20376f
      if (BE (msg_size > errbuf_size, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  memcpy (errbuf, msg, errbuf_size - 1);
Packit Service 20376f
	  errbuf[errbuf_size - 1] = 0;
Packit Service 20376f
	}
Packit Service 20376f
      else
Packit Service 20376f
	memcpy (errbuf, msg, msg_size);
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  return msg_size;
Packit Service 20376f
}
Packit Service 20376f
#ifdef _LIBC
Packit Service 20376f
weak_alias (__regerror, regerror)
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
/* This static array is used for the map to single-byte characters when
Packit Service 20376f
   UTF-8 is used.  Otherwise we would allocate memory just to initialize
Packit Service 20376f
   it the same all the time.  UTF-8 is the preferred encoding so this is
Packit Service 20376f
   a worthwhile optimization.  */
Packit Service 20376f
#if __GNUC__ >= 3
Packit Service 20376f
static const bitset_t utf8_sb_map = {
Packit Service 20376f
  /* Set the first 128 bits.  */
Packit Service 20376f
  [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX
Packit Service 20376f
};
Packit Service 20376f
#else /* ! (__GNUC__ >= 3) */
Packit Service 20376f
static bitset_t utf8_sb_map;
Packit Service 20376f
#endif /* __GNUC__ >= 3 */
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
Packit Service 20376f
Packit Service 20376f
static void
Packit Service 20376f
free_dfa_content (re_dfa_t *dfa)
Packit Service 20376f
{
Packit Service 20376f
  unsigned int i;
Packit Service 20376f
  int j;
Packit Service 20376f
Packit Service 20376f
  if (dfa->nodes)
Packit Service 20376f
    for (i = 0; i < dfa->nodes_len; ++i)
Packit Service 20376f
      free_token (dfa->nodes + i);
Packit Service 20376f
  re_free (dfa->nexts);
Packit Service 20376f
  for (i = 0; i < dfa->nodes_len; ++i)
Packit Service 20376f
    {
Packit Service 20376f
      if (dfa->eclosures != NULL)
Packit Service 20376f
	re_node_set_free (dfa->eclosures + i);
Packit Service 20376f
      if (dfa->inveclosures != NULL)
Packit Service 20376f
	re_node_set_free (dfa->inveclosures + i);
Packit Service 20376f
      if (dfa->edests != NULL)
Packit Service 20376f
	re_node_set_free (dfa->edests + i);
Packit Service 20376f
    }
Packit Service 20376f
  re_free (dfa->edests);
Packit Service 20376f
  re_free (dfa->eclosures);
Packit Service 20376f
  re_free (dfa->inveclosures);
Packit Service 20376f
  re_free (dfa->nodes);
Packit Service 20376f
Packit Service 20376f
  if (dfa->state_table)
Packit Service 20376f
    for (i = 0; i <= dfa->state_hash_mask; ++i)
Packit Service 20376f
      {
Packit Service 20376f
	struct re_state_table_entry *entry = dfa->state_table + i;
Packit Service 20376f
	for (j = 0; j < entry->num; ++j)
Packit Service 20376f
	  {
Packit Service 20376f
	    re_dfastate_t *state = entry->array[j];
Packit Service 20376f
	    free_state (state);
Packit Service 20376f
	  }
Packit Service 20376f
	re_free (entry->array);
Packit Service 20376f
      }
Packit Service 20376f
  re_free (dfa->state_table);
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  if (dfa->sb_char != utf8_sb_map)
Packit Service 20376f
    re_free (dfa->sb_char);
Packit Service 20376f
#endif
Packit Service 20376f
  re_free (dfa->subexp_map);
Packit Service 20376f
#ifdef DEBUG
Packit Service 20376f
  re_free (dfa->re_str);
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
  re_free (dfa);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
Packit Service 20376f
/* Free dynamically allocated space used by PREG.  */
Packit Service 20376f
Packit Service 20376f
void
Packit Service 20376f
regfree (regex_t *preg)
Packit Service 20376f
{
Packit Service 20376f
  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
Packit Service 20376f
  if (BE (dfa != NULL, 1))
Packit Service 20376f
    free_dfa_content (dfa);
Packit Service 20376f
  preg->buffer = NULL;
Packit Service 20376f
  preg->allocated = 0;
Packit Service 20376f
Packit Service 20376f
  re_free (preg->fastmap);
Packit Service 20376f
  preg->fastmap = NULL;
Packit Service 20376f
Packit Service 20376f
  re_free (preg->translate);
Packit Service 20376f
  preg->translate = NULL;
Packit Service 20376f
}
Packit Service 20376f
#ifdef _LIBC
Packit Service 20376f
weak_alias (__regfree, regfree)
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
Packit Service 20376f
/* BSD has one and only one pattern buffer.  */
Packit Service 20376f
static struct re_pattern_buffer re_comp_buf;
Packit Service 20376f
Packit Service 20376f
char *
Packit Service 20376f
# ifdef _LIBC
Packit Service 20376f
/* Make these definitions weak in libc, so POSIX programs can redefine
Packit Service 20376f
   these names if they don't use our functions, and still use
Packit Service 20376f
   regcomp/regexec above without link errors.  */
Packit Service 20376f
weak_function
Packit Service 20376f
# endif
Packit Service 20376f
re_comp (s)
Packit Service 20376f
     const char *s;
Packit Service 20376f
{
Packit Service 20376f
  reg_errcode_t ret;
Packit Service 20376f
  char *fastmap;
Packit Service 20376f
Packit Service 20376f
  if (!s)
Packit Service 20376f
    {
Packit Service 20376f
      if (!re_comp_buf.buffer)
Packit Service 20376f
	return gettext ("No previous regular expression");
Packit Service 20376f
      return 0;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  if (re_comp_buf.buffer)
Packit Service 20376f
    {
Packit Service 20376f
      fastmap = re_comp_buf.fastmap;
Packit Service 20376f
      re_comp_buf.fastmap = NULL;
Packit Service 20376f
      __regfree (&re_comp_buf);
Packit Service 20376f
      memset (&re_comp_buf, '\0', sizeof (re_comp_buf));
Packit Service 20376f
      re_comp_buf.fastmap = fastmap;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  if (re_comp_buf.fastmap == NULL)
Packit Service 20376f
    {
Packit Service 20376f
      re_comp_buf.fastmap = (char *) malloc (SBC_MAX);
Packit Service 20376f
      if (re_comp_buf.fastmap == NULL)
Packit Service 20376f
	return (char *) gettext (__re_error_msgid
Packit Service 20376f
				 + __re_error_msgid_idx[(int) REG_ESPACE]);
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  /* Since `re_exec' always passes NULL for the `regs' argument, we
Packit Service 20376f
     don't need to initialize the pattern buffer fields which affect it.  */
Packit Service 20376f
Packit Service 20376f
  /* Match anchors at newlines.  */
Packit Service 20376f
  re_comp_buf.newline_anchor = 1;
Packit Service 20376f
Packit Service 20376f
  ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options);
Packit Service 20376f
Packit Service 20376f
  if (!ret)
Packit Service 20376f
    return NULL;
Packit Service 20376f
Packit Service 20376f
  /* Yes, we're discarding `const' here if !HAVE_LIBINTL.  */
Packit Service 20376f
  return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
#ifdef _LIBC
Packit Service 20376f
libc_freeres_fn (free_mem)
Packit Service 20376f
{
Packit Service 20376f
  __regfree (&re_comp_buf);
Packit Service 20376f
}
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
#endif /* _REGEX_RE_COMP */
Packit Service 20376f

Packit Service 20376f
/* Internal entry point.
Packit Service 20376f
   Compile the regular expression PATTERN, whose length is LENGTH.
Packit Service 20376f
   SYNTAX indicate regular expression's syntax.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
re_compile_internal (regex_t *preg, const char * pattern, size_t length,
Packit Service 20376f
		     reg_syntax_t syntax)
Packit Service 20376f
{
Packit Service 20376f
  reg_errcode_t err = REG_NOERROR;
Packit Service 20376f
  re_dfa_t *dfa;
Packit Service 20376f
  re_string_t regexp;
Packit Service 20376f
Packit Service 20376f
  /* Initialize the pattern buffer.  */
Packit Service 20376f
  preg->fastmap_accurate = 0;
Packit Service 20376f
  preg->syntax = syntax;
Packit Service 20376f
  preg->not_bol = preg->not_eol = 0;
Packit Service 20376f
  preg->used = 0;
Packit Service 20376f
  preg->re_nsub = 0;
Packit Service 20376f
  preg->can_be_null = 0;
Packit Service 20376f
  preg->regs_allocated = REGS_UNALLOCATED;
Packit Service 20376f
Packit Service 20376f
  /* Initialize the dfa.  */
Packit Service 20376f
  dfa = (re_dfa_t *) preg->buffer;
Packit Service 20376f
  if (BE (preg->allocated < sizeof (re_dfa_t), 0))
Packit Service 20376f
    {
Packit Service 20376f
      /* If zero allocated, but buffer is non-null, try to realloc
Packit Service 20376f
	 enough space.  This loses if buffer's address is bogus, but
Packit Service 20376f
	 that is the user's responsibility.  If ->buffer is NULL this
Packit Service 20376f
	 is a simple allocation.  */
Packit Service 20376f
      dfa = re_realloc (preg->buffer, re_dfa_t, 1);
Packit Service 20376f
      if (dfa == NULL)
Packit Service 20376f
	return REG_ESPACE;
Packit Service 20376f
      preg->allocated = sizeof (re_dfa_t);
Packit Service 20376f
      preg->buffer = (unsigned char *) dfa;
Packit Service 20376f
    }
Packit Service 20376f
  preg->used = sizeof (re_dfa_t);
Packit Service 20376f
Packit Service 20376f
  err = init_dfa (dfa, length);
Packit Service 20376f
  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
    {
Packit Service 20376f
      free_dfa_content (dfa);
Packit Service 20376f
      preg->buffer = NULL;
Packit Service 20376f
      preg->allocated = 0;
Packit Service 20376f
      return err;
Packit Service 20376f
    }
Packit Service 20376f
#ifdef DEBUG
Packit Service 20376f
  /* Note: length+1 will not overflow since it is checked in init_dfa.  */
Packit Service 20376f
  dfa->re_str = re_malloc (char, length + 1);
Packit Service 20376f
  strncpy (dfa->re_str, pattern, length + 1);
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
  __libc_lock_init (dfa->lock);
Packit Service 20376f
Packit Service 20376f
  err = re_string_construct (&regexp, pattern, length, preg->translate,
Packit Service 20376f
			     syntax & RE_ICASE, dfa);
Packit Service 20376f
  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
    {
Packit Service 20376f
    re_compile_internal_free_return:
Packit Service 20376f
      free_workarea_compile (preg);
Packit Service 20376f
      re_string_destruct (&regexp);
Packit Service 20376f
      free_dfa_content (dfa);
Packit Service 20376f
      preg->buffer = NULL;
Packit Service 20376f
      preg->allocated = 0;
Packit Service 20376f
      return err;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  /* Parse the regular expression, and build a structure tree.  */
Packit Service 20376f
  preg->re_nsub = 0;
Packit Service 20376f
  dfa->str_tree = parse (&regexp, preg, syntax, &err;;
Packit Service 20376f
  if (BE (dfa->str_tree == NULL, 0))
Packit Service 20376f
    goto re_compile_internal_free_return;
Packit Service 20376f
Packit Service 20376f
  /* Analyze the tree and create the nfa.  */
Packit Service 20376f
  err = analyze (preg);
Packit Service 20376f
  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
    goto re_compile_internal_free_return;
Packit Service 20376f
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  /* If possible, do searching in single byte encoding to speed things up.  */
Packit Service 20376f
  if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL)
Packit Service 20376f
    optimize_utf8 (dfa);
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
  /* Then create the initial state of the dfa.  */
Packit Service 20376f
  err = create_initial_state (dfa);
Packit Service 20376f
Packit Service 20376f
  /* Release work areas.  */
Packit Service 20376f
  free_workarea_compile (preg);
Packit Service 20376f
  re_string_destruct (&regexp);
Packit Service 20376f
Packit Service 20376f
  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
    {
Packit Service 20376f
      free_dfa_content (dfa);
Packit Service 20376f
      preg->buffer = NULL;
Packit Service 20376f
      preg->allocated = 0;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  return err;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Initialize DFA.  We use the length of the regular expression PAT_LEN
Packit Service 20376f
   as the initial length of some arrays.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
init_dfa (re_dfa_t *dfa, size_t pat_len)
Packit Service 20376f
{
Packit Service 20376f
  unsigned int table_size;
Packit Service 20376f
Packit Service 20376f
  memset (dfa, '\0', sizeof (re_dfa_t));
Packit Service 20376f
Packit Service 20376f
  /* Force allocation of str_tree_storage the first time.  */
Packit Service 20376f
  dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;
Packit Service 20376f
Packit Service 20376f
  /* Avoid overflows.  */
Packit Service 20376f
  if (pat_len == SIZE_MAX)
Packit Service 20376f
    return REG_ESPACE;
Packit Service 20376f
Packit Service 20376f
  dfa->nodes_alloc = pat_len + 1;
Packit Service 20376f
  dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc);
Packit Service 20376f
Packit Service 20376f
  /*  table_size = 2 ^ ceil(log pat_len) */
Packit Service 20376f
  for (table_size = 1; ; table_size <<= 1)
Packit Service 20376f
    if (table_size > pat_len)
Packit Service 20376f
      break;
Packit Service 20376f
Packit Service 20376f
  dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size);
Packit Service 20376f
  dfa->state_hash_mask = table_size - 1;
Packit Service 20376f
Packit Service 20376f
  dfa->mb_cur_max = MB_CUR_MAX;
Packit Service 20376f
#ifdef _LIBC
Packit Service 20376f
  if (dfa->mb_cur_max == 6
Packit Service 20376f
      && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0)
Packit Service 20376f
    dfa->is_utf8 = 1;
Packit Service 20376f
  dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII)
Packit Service 20376f
		       != 0);
Packit Service 20376f
#else
Packit Service 20376f
  dfa->is_utf8 = 1;
Packit Service 20376f
  /* We check exhaustively in the loop below if this charset is a
Packit Service 20376f
     superset of ASCII.  */
Packit Service 20376f
  dfa->map_notascii = 0;
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  if (dfa->mb_cur_max > 1)
Packit Service 20376f
    {
Packit Service 20376f
      if (dfa->is_utf8)
Packit Service 20376f
        {
Packit Service 20376f
#if !defined(__GNUC__) || __GNUC__ < 3
Packit Service 20376f
	  static short utf8_sb_map_inited = 0;
Packit Service 20376f
Packit Service 20376f
	  if (! utf8_sb_map_inited)
Packit Service 20376f
	    {
Packit Service 20376f
		int i;
Packit Service 20376f
Packit Service 20376f
	  	utf8_sb_map_inited = 0;
Packit Service 20376f
		for (i = 0; i <= 0x80 / BITSET_WORD_BITS - 1; i++)
Packit Service 20376f
		  utf8_sb_map[i] = BITSET_WORD_MAX;
Packit Service 20376f
	    }
Packit Service 20376f
#endif
Packit Service 20376f
	  dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map;
Packit Service 20376f
	}
Packit Service 20376f
      else
Packit Service 20376f
	{
Packit Service 20376f
	  int i, j, ch;
Packit Service 20376f
Packit Service 20376f
	  dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
Packit Service 20376f
	  if (BE (dfa->sb_char == NULL, 0))
Packit Service 20376f
	    return REG_ESPACE;
Packit Service 20376f
Packit Service 20376f
	  /* Set the bits corresponding to single byte chars.  */
Packit Service 20376f
	  for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
Packit Service 20376f
	    for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
Packit Service 20376f
	      {
Packit Service 20376f
		wint_t wch = __btowc (ch);
Packit Service 20376f
		if (wch != WEOF)
Packit Service 20376f
		  dfa->sb_char[i] |= (bitset_word_t) 1 << j;
Packit Service 20376f
# ifndef _LIBC
Packit Service 20376f
		if (isascii (ch) && wch != ch)
Packit Service 20376f
		  dfa->map_notascii = 1;
Packit Service 20376f
# endif
Packit Service 20376f
	      }
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
  if (BE (dfa->nodes == NULL || dfa->state_table == NULL, 0))
Packit Service 20376f
    return REG_ESPACE;
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Initialize WORD_CHAR table, which indicate which character is
Packit Service 20376f
   "word".  In this case "word" means that it is the word construction
Packit Service 20376f
   character used by some operators like "\<", "\>", etc.  */
Packit Service 20376f
Packit Service 20376f
static void
Packit Service 20376f
internal_function
Packit Service 20376f
init_word_char (re_dfa_t *dfa)
Packit Service 20376f
{
Packit Service 20376f
  int i, j, ch;
Packit Service 20376f
  dfa->word_ops_used = 1;
Packit Service 20376f
  for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
Packit Service 20376f
    for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
Packit Service 20376f
      if (isalnum (ch) || ch == '_')
Packit Service 20376f
	dfa->word_char[i] |= (bitset_word_t) 1 << j;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Free the work area which are only used while compiling.  */
Packit Service 20376f
Packit Service 20376f
static void
Packit Service 20376f
free_workarea_compile (regex_t *preg)
Packit Service 20376f
{
Packit Service 20376f
  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
Packit Service 20376f
  bin_tree_storage_t *storage, *next;
Packit Service 20376f
  for (storage = dfa->str_tree_storage; storage; storage = next)
Packit Service 20376f
    {
Packit Service 20376f
      next = storage->next;
Packit Service 20376f
      re_free (storage);
Packit Service 20376f
    }
Packit Service 20376f
  dfa->str_tree_storage = NULL;
Packit Service 20376f
  dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;
Packit Service 20376f
  dfa->str_tree = NULL;
Packit Service 20376f
  re_free (dfa->org_indices);
Packit Service 20376f
  dfa->org_indices = NULL;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Create initial states for all contexts.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
create_initial_state (re_dfa_t *dfa)
Packit Service 20376f
{
Packit Service 20376f
  int first, i;
Packit Service 20376f
  reg_errcode_t err;
Packit Service 20376f
  re_node_set init_nodes;
Packit Service 20376f
Packit Service 20376f
  /* Initial states have the epsilon closure of the node which is
Packit Service 20376f
     the first node of the regular expression.  */
Packit Service 20376f
  first = dfa->str_tree->first->node_idx;
Packit Service 20376f
  dfa->init_node = first;
Packit Service 20376f
  err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first);
Packit Service 20376f
  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
    return err;
Packit Service 20376f
Packit Service 20376f
  /* The back-references which are in initial states can epsilon transit,
Packit Service 20376f
     since in this case all of the subexpressions can be null.
Packit Service 20376f
     Then we add epsilon closures of the nodes which are the next nodes of
Packit Service 20376f
     the back-references.  */
Packit Service 20376f
  if (dfa->nbackref > 0)
Packit Service 20376f
    for (i = 0; i < init_nodes.nelem; ++i)
Packit Service 20376f
      {
Packit Service 20376f
	int node_idx = init_nodes.elems[i];
Packit Service 20376f
	re_token_type_t type = dfa->nodes[node_idx].type;
Packit Service 20376f
Packit Service 20376f
	int clexp_idx;
Packit Service 20376f
	if (type != OP_BACK_REF)
Packit Service 20376f
	  continue;
Packit Service 20376f
	for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx)
Packit Service 20376f
	  {
Packit Service 20376f
	    re_token_t *clexp_node;
Packit Service 20376f
	    clexp_node = dfa->nodes + init_nodes.elems[clexp_idx];
Packit Service 20376f
	    if (clexp_node->type == OP_CLOSE_SUBEXP
Packit Service 20376f
		&& clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx)
Packit Service 20376f
	      break;
Packit Service 20376f
	  }
Packit Service 20376f
	if (clexp_idx == init_nodes.nelem)
Packit Service 20376f
	  continue;
Packit Service 20376f
Packit Service 20376f
	if (type == OP_BACK_REF)
Packit Service 20376f
	  {
Packit Service 20376f
	    int dest_idx = dfa->edests[node_idx].elems[0];
Packit Service 20376f
	    if (!re_node_set_contains (&init_nodes, dest_idx))
Packit Service 20376f
	      {
Packit Service 20376f
		reg_errcode_t err = re_node_set_merge (&init_nodes,
Packit Service 20376f
						       dfa->eclosures
Packit Service 20376f
						       + dest_idx);
Packit Service 20376f
		if (err != REG_NOERROR)
Packit Service 20376f
		  return err;
Packit Service 20376f
		i = 0;
Packit Service 20376f
	      }
Packit Service 20376f
	  }
Packit Service 20376f
      }
Packit Service 20376f
Packit Service 20376f
  /* It must be the first time to invoke acquire_state.  */
Packit Service 20376f
  dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0);
Packit Service 20376f
  /* We don't check ERR here, since the initial state must not be NULL.  */
Packit Service 20376f
  if (BE (dfa->init_state == NULL, 0))
Packit Service 20376f
    return err;
Packit Service 20376f
  if (dfa->init_state->has_constraint)
Packit Service 20376f
    {
Packit Service 20376f
      dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes,
Packit Service 20376f
						       CONTEXT_WORD);
Packit Service 20376f
      dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes,
Packit Service 20376f
						     CONTEXT_NEWLINE);
Packit Service 20376f
      dfa->init_state_begbuf = re_acquire_state_context (&err, dfa,
Packit Service 20376f
							 &init_nodes,
Packit Service 20376f
							 CONTEXT_NEWLINE
Packit Service 20376f
							 | CONTEXT_BEGBUF);
Packit Service 20376f
      if (BE (dfa->init_state_word == NULL || dfa->init_state_nl == NULL
Packit Service 20376f
	      || dfa->init_state_begbuf == NULL, 0))
Packit Service 20376f
	return err;
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
    dfa->init_state_word = dfa->init_state_nl
Packit Service 20376f
      = dfa->init_state_begbuf = dfa->init_state;
Packit Service 20376f
Packit Service 20376f
  re_node_set_free (&init_nodes);
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f

Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
/* If it is possible to do searching in single byte encoding instead of UTF-8
Packit Service 20376f
   to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change
Packit Service 20376f
   DFA nodes where needed.  */
Packit Service 20376f
Packit Service 20376f
static void
Packit Service 20376f
optimize_utf8 (re_dfa_t *dfa)
Packit Service 20376f
{
Packit Service 20376f
  int node, i, mb_chars = 0, has_period = 0;
Packit Service 20376f
Packit Service 20376f
  for (node = 0; node < dfa->nodes_len; ++node)
Packit Service 20376f
    switch (dfa->nodes[node].type)
Packit Service 20376f
      {
Packit Service 20376f
      case CHARACTER:
Packit Service 20376f
	if (dfa->nodes[node].opr.c >= 0x80)
Packit Service 20376f
	  mb_chars = 1;
Packit Service 20376f
	break;
Packit Service 20376f
      case ANCHOR:
Packit Service 20376f
	switch (dfa->nodes[node].opr.ctx_type)
Packit Service 20376f
	  {
Packit Service 20376f
	  case LINE_FIRST:
Packit Service 20376f
	  case LINE_LAST:
Packit Service 20376f
	  case BUF_FIRST:
Packit Service 20376f
	  case BUF_LAST:
Packit Service 20376f
	    break;
Packit Service 20376f
	  default:
Packit Service 20376f
	    /* Word anchors etc. cannot be handled.  It's okay to test
Packit Service 20376f
	       opr.ctx_type since constraints (for all DFA nodes) are
Packit Service 20376f
	       created by ORing one or more opr.ctx_type values.  */
Packit Service 20376f
	    return;
Packit Service 20376f
	  }
Packit Service 20376f
	break;
Packit Service 20376f
      case OP_PERIOD:
Packit Service 20376f
	has_period = 1;
Packit Service 20376f
	break;
Packit Service 20376f
      case OP_BACK_REF:
Packit Service 20376f
      case OP_ALT:
Packit Service 20376f
      case END_OF_RE:
Packit Service 20376f
      case OP_DUP_ASTERISK:
Packit Service 20376f
      case OP_OPEN_SUBEXP:
Packit Service 20376f
      case OP_CLOSE_SUBEXP:
Packit Service 20376f
	break;
Packit Service 20376f
      case COMPLEX_BRACKET:
Packit Service 20376f
	return;
Packit Service 20376f
      case SIMPLE_BRACKET:
Packit Service 20376f
	/* Just double check.  The non-ASCII range starts at 0x80.  */
Packit Service 20376f
	assert (0x80 % BITSET_WORD_BITS == 0);
Packit Service 20376f
	for (i = 0x80 / BITSET_WORD_BITS; i < BITSET_WORDS; ++i)
Packit Service 20376f
	  if (dfa->nodes[node].opr.sbcset[i])
Packit Service 20376f
	    return;
Packit Service 20376f
	break;
Packit Service 20376f
      default:
Packit Service 20376f
	abort ();
Packit Service 20376f
      }
Packit Service 20376f
Packit Service 20376f
  if (mb_chars || has_period)
Packit Service 20376f
    for (node = 0; node < dfa->nodes_len; ++node)
Packit Service 20376f
      {
Packit Service 20376f
	if (dfa->nodes[node].type == CHARACTER
Packit Service 20376f
	    && dfa->nodes[node].opr.c >= 0x80)
Packit Service 20376f
	  dfa->nodes[node].mb_partial = 0;
Packit Service 20376f
	else if (dfa->nodes[node].type == OP_PERIOD)
Packit Service 20376f
	  dfa->nodes[node].type = OP_UTF8_PERIOD;
Packit Service 20376f
      }
Packit Service 20376f
Packit Service 20376f
  /* The search can be in single byte locale.  */
Packit Service 20376f
  dfa->mb_cur_max = 1;
Packit Service 20376f
  dfa->is_utf8 = 0;
Packit Service 20376f
  dfa->has_mb_node = dfa->nbackref > 0 || has_period;
Packit Service 20376f
}
Packit Service 20376f
#endif
Packit Service 20376f

Packit Service 20376f
/* Analyze the structure tree, and calculate "first", "next", "edest",
Packit Service 20376f
   "eclosure", and "inveclosure".  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
analyze (regex_t *preg)
Packit Service 20376f
{
Packit Service 20376f
  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
Packit Service 20376f
  reg_errcode_t ret;
Packit Service 20376f
Packit Service 20376f
  /* Allocate arrays.  */
Packit Service 20376f
  dfa->nexts = re_malloc (int, dfa->nodes_alloc);
Packit Service 20376f
  dfa->org_indices = re_malloc (int, dfa->nodes_alloc);
Packit Service 20376f
  dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc);
Packit Service 20376f
  dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc);
Packit Service 20376f
  if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL
Packit Service 20376f
	  || dfa->eclosures == NULL, 0))
Packit Service 20376f
    return REG_ESPACE;
Packit Service 20376f
Packit Service 20376f
  dfa->subexp_map = re_malloc (int, preg->re_nsub);
Packit Service 20376f
  if (dfa->subexp_map != NULL)
Packit Service 20376f
    {
Packit Service 20376f
      unsigned int i;
Packit Service 20376f
      for (i = 0; i < preg->re_nsub; i++)
Packit Service 20376f
	dfa->subexp_map[i] = i;
Packit Service 20376f
      preorder (dfa->str_tree, optimize_subexps, dfa);
Packit Service 20376f
      for (i = 0; i < preg->re_nsub; i++)
Packit Service 20376f
	if (dfa->subexp_map[i] != (int)i)
Packit Service 20376f
	  break;
Packit Service 20376f
      if (i == preg->re_nsub)
Packit Service 20376f
	{
Packit Service 20376f
	  free (dfa->subexp_map);
Packit Service 20376f
	  dfa->subexp_map = NULL;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  ret = postorder (dfa->str_tree, lower_subexps, preg);
Packit Service 20376f
  if (BE (ret != REG_NOERROR, 0))
Packit Service 20376f
    return ret;
Packit Service 20376f
  ret = postorder (dfa->str_tree, calc_first, dfa);
Packit Service 20376f
  if (BE (ret != REG_NOERROR, 0))
Packit Service 20376f
    return ret;
Packit Service 20376f
  preorder (dfa->str_tree, calc_next, dfa);
Packit Service 20376f
  ret = preorder (dfa->str_tree, link_nfa_nodes, dfa);
Packit Service 20376f
  if (BE (ret != REG_NOERROR, 0))
Packit Service 20376f
    return ret;
Packit Service 20376f
  ret = calc_eclosure (dfa);
Packit Service 20376f
  if (BE (ret != REG_NOERROR, 0))
Packit Service 20376f
    return ret;
Packit Service 20376f
Packit Service 20376f
  /* We only need this during the prune_impossible_nodes pass in regexec.c;
Packit Service 20376f
     skip it if p_i_n will not run, as calc_inveclosure can be quadratic.  */
Packit Service 20376f
  if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match)
Packit Service 20376f
      || dfa->nbackref)
Packit Service 20376f
    {
Packit Service 20376f
      dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len);
Packit Service 20376f
      if (BE (dfa->inveclosures == NULL, 0))
Packit Service 20376f
	return REG_ESPACE;
Packit Service 20376f
      ret = calc_inveclosure (dfa);
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  return ret;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Our parse trees are very unbalanced, so we cannot use a stack to
Packit Service 20376f
   implement parse tree visits.  Instead, we use parent pointers and
Packit Service 20376f
   some hairy code in these two functions.  */
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)),
Packit Service 20376f
	   void *extra)
Packit Service 20376f
{
Packit Service 20376f
  bin_tree_t *node, *prev;
Packit Service 20376f
Packit Service 20376f
  for (node = root; ; )
Packit Service 20376f
    {
Packit Service 20376f
      /* Descend down the tree, preferably to the left (or to the right
Packit Service 20376f
	 if that's the only child).  */
Packit Service 20376f
      while (node->left || node->right)
Packit Service 20376f
	if (node->left)
Packit Service 20376f
	  node = node->left;
Packit Service 20376f
	else
Packit Service 20376f
	  node = node->right;
Packit Service 20376f
Packit Service 20376f
      do
Packit Service 20376f
	{
Packit Service 20376f
	  reg_errcode_t err = fn (extra, node);
Packit Service 20376f
	  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	    return err;
Packit Service 20376f
	  if (node->parent == NULL)
Packit Service 20376f
	    return REG_NOERROR;
Packit Service 20376f
	  prev = node;
Packit Service 20376f
	  node = node->parent;
Packit Service 20376f
	}
Packit Service 20376f
      /* Go up while we have a node that is reached from the right.  */
Packit Service 20376f
      while (node->right == prev || node->right == NULL);
Packit Service 20376f
      node = node->right;
Packit Service 20376f
    }
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)),
Packit Service 20376f
	  void *extra)
Packit Service 20376f
{
Packit Service 20376f
  bin_tree_t *node;
Packit Service 20376f
Packit Service 20376f
  for (node = root; ; )
Packit Service 20376f
    {
Packit Service 20376f
      reg_errcode_t err = fn (extra, node);
Packit Service 20376f
      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	return err;
Packit Service 20376f
Packit Service 20376f
      /* Go to the left node, or up and to the right.  */
Packit Service 20376f
      if (node->left)
Packit Service 20376f
	node = node->left;
Packit Service 20376f
      else
Packit Service 20376f
	{
Packit Service 20376f
	  bin_tree_t *prev = NULL;
Packit Service 20376f
	  while (node->right == prev || node->right == NULL)
Packit Service 20376f
	    {
Packit Service 20376f
	      prev = node;
Packit Service 20376f
	      node = node->parent;
Packit Service 20376f
	      if (!node)
Packit Service 20376f
		return REG_NOERROR;
Packit Service 20376f
	    }
Packit Service 20376f
	  node = node->right;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell
Packit Service 20376f
   re_search_internal to map the inner one's opr.idx to this one's.  Adjust
Packit Service 20376f
   backreferences as well.  Requires a preorder visit.  */
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
optimize_subexps (void *extra, bin_tree_t *node)
Packit Service 20376f
{
Packit Service 20376f
  re_dfa_t *dfa = (re_dfa_t *) extra;
Packit Service 20376f
Packit Service 20376f
  if (node->token.type == OP_BACK_REF && dfa->subexp_map)
Packit Service 20376f
    {
Packit Service 20376f
      int idx = node->token.opr.idx;
Packit Service 20376f
      node->token.opr.idx = dfa->subexp_map[idx];
Packit Service 20376f
      dfa->used_bkref_map |= 1 << node->token.opr.idx;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  else if (node->token.type == SUBEXP
Packit Service 20376f
	   && node->left && node->left->token.type == SUBEXP)
Packit Service 20376f
    {
Packit Service 20376f
      int other_idx = node->left->token.opr.idx;
Packit Service 20376f
Packit Service 20376f
      node->left = node->left->left;
Packit Service 20376f
      if (node->left)
Packit Service 20376f
	node->left->parent = node;
Packit Service 20376f
Packit Service 20376f
      dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx];
Packit Service 20376f
      if (other_idx < BITSET_WORD_BITS)
Packit Service 20376f
	  dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx);
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation
Packit Service 20376f
   of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP.  */
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
lower_subexps (void *extra, bin_tree_t *node)
Packit Service 20376f
{
Packit Service 20376f
  regex_t *preg = (regex_t *) extra;
Packit Service 20376f
  reg_errcode_t err = REG_NOERROR;
Packit Service 20376f
Packit Service 20376f
  if (node->left && node->left->token.type == SUBEXP)
Packit Service 20376f
    {
Packit Service 20376f
      node->left = lower_subexp (&err, preg, node->left);
Packit Service 20376f
      if (node->left)
Packit Service 20376f
	node->left->parent = node;
Packit Service 20376f
    }
Packit Service 20376f
  if (node->right && node->right->token.type == SUBEXP)
Packit Service 20376f
    {
Packit Service 20376f
      node->right = lower_subexp (&err, preg, node->right);
Packit Service 20376f
      if (node->right)
Packit Service 20376f
	node->right->parent = node;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  return err;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static bin_tree_t *
Packit Service 20376f
lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node)
Packit Service 20376f
{
Packit Service 20376f
  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
Packit Service 20376f
  bin_tree_t *body = node->left;
Packit Service 20376f
  bin_tree_t *op, *cls, *tree1, *tree;
Packit Service 20376f
Packit Service 20376f
  if (preg->no_sub
Packit Service 20376f
      /* We do not optimize empty subexpressions, because otherwise we may
Packit Service 20376f
	 have bad CONCAT nodes with NULL children.  This is obviously not
Packit Service 20376f
	 very common, so we do not lose much.  An example that triggers
Packit Service 20376f
	 this case is the sed "script" /\(\)/x.  */
Packit Service 20376f
      && node->left != NULL
Packit Service 20376f
      && (node->token.opr.idx >= BITSET_WORD_BITS
Packit Service 20376f
	  || !(dfa->used_bkref_map
Packit Service 20376f
	       & ((bitset_word_t) 1 << node->token.opr.idx))))
Packit Service 20376f
    return node->left;
Packit Service 20376f
Packit Service 20376f
  /* Convert the SUBEXP node to the concatenation of an
Packit Service 20376f
     OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP.  */
Packit Service 20376f
  op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP);
Packit Service 20376f
  cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP);
Packit Service 20376f
  tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls;
Packit Service 20376f
  tree = create_tree (dfa, op, tree1, CONCAT);
Packit Service 20376f
  if (BE (tree == NULL || tree1 == NULL || op == NULL || cls == NULL, 0))
Packit Service 20376f
    {
Packit Service 20376f
      *err = REG_ESPACE;
Packit Service 20376f
      return NULL;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx;
Packit Service 20376f
  op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp;
Packit Service 20376f
  return tree;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton
Packit Service 20376f
   nodes.  Requires a postorder visit.  */
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
calc_first (void *extra, bin_tree_t *node)
Packit Service 20376f
{
Packit Service 20376f
  re_dfa_t *dfa = (re_dfa_t *) extra;
Packit Service 20376f
  if (node->token.type == CONCAT)
Packit Service 20376f
    {
Packit Service 20376f
      node->first = node->left->first;
Packit Service 20376f
      node->node_idx = node->left->node_idx;
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
    {
Packit Service 20376f
      node->first = node;
Packit Service 20376f
      node->node_idx = re_dfa_add_node (dfa, node->token);
Packit Service 20376f
      if (BE (node->node_idx == -1, 0))
Packit Service 20376f
	return REG_ESPACE;
Packit Service 20376f
      if (node->token.type == ANCHOR)
Packit Service 20376f
	dfa->nodes[node->node_idx].constraint = node->token.opr.ctx_type;
Packit Service 20376f
    }
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Pass 2: compute NEXT on the tree.  Preorder visit.  */
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
calc_next (UNUSED void *extra, bin_tree_t *node)
Packit Service 20376f
{
Packit Service 20376f
  switch (node->token.type)
Packit Service 20376f
    {
Packit Service 20376f
    case OP_DUP_ASTERISK:
Packit Service 20376f
      node->left->next = node;
Packit Service 20376f
      break;
Packit Service 20376f
    case CONCAT:
Packit Service 20376f
      node->left->next = node->right->first;
Packit Service 20376f
      node->right->next = node->next;
Packit Service 20376f
      break;
Packit Service 20376f
    default:
Packit Service 20376f
      if (node->left)
Packit Service 20376f
	node->left->next = node->next;
Packit Service 20376f
      if (node->right)
Packit Service 20376f
	node->right->next = node->next;
Packit Service 20376f
      break;
Packit Service 20376f
    }
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Pass 3: link all DFA nodes to their NEXT node (any order will do).  */
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
link_nfa_nodes (void *extra, bin_tree_t *node)
Packit Service 20376f
{
Packit Service 20376f
  re_dfa_t *dfa = (re_dfa_t *) extra;
Packit Service 20376f
  int idx = node->node_idx;
Packit Service 20376f
  reg_errcode_t err = REG_NOERROR;
Packit Service 20376f
Packit Service 20376f
  switch (node->token.type)
Packit Service 20376f
    {
Packit Service 20376f
    case CONCAT:
Packit Service 20376f
      break;
Packit Service 20376f
Packit Service 20376f
    case END_OF_RE:
Packit Service 20376f
      assert (node->next == NULL);
Packit Service 20376f
      break;
Packit Service 20376f
Packit Service 20376f
    case OP_DUP_ASTERISK:
Packit Service 20376f
    case OP_ALT:
Packit Service 20376f
      {
Packit Service 20376f
	int left, right;
Packit Service 20376f
	dfa->has_plural_match = 1;
Packit Service 20376f
	if (node->left != NULL)
Packit Service 20376f
	  left = node->left->first->node_idx;
Packit Service 20376f
	else
Packit Service 20376f
	  left = node->next->node_idx;
Packit Service 20376f
	if (node->right != NULL)
Packit Service 20376f
	  right = node->right->first->node_idx;
Packit Service 20376f
	else
Packit Service 20376f
	  right = node->next->node_idx;
Packit Service 20376f
	assert (left > -1);
Packit Service 20376f
	assert (right > -1);
Packit Service 20376f
	err = re_node_set_init_2 (dfa->edests + idx, left, right);
Packit Service 20376f
      }
Packit Service 20376f
      break;
Packit Service 20376f
Packit Service 20376f
    case ANCHOR:
Packit Service 20376f
    case OP_OPEN_SUBEXP:
Packit Service 20376f
    case OP_CLOSE_SUBEXP:
Packit Service 20376f
      err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx);
Packit Service 20376f
      break;
Packit Service 20376f
Packit Service 20376f
    case OP_BACK_REF:
Packit Service 20376f
      dfa->nexts[idx] = node->next->node_idx;
Packit Service 20376f
      if (node->token.type == OP_BACK_REF)
Packit Service 20376f
	err = re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]);
Packit Service 20376f
      break;
Packit Service 20376f
Packit Service 20376f
    default:
Packit Service 20376f
      assert (!IS_EPSILON_NODE (node->token.type));
Packit Service 20376f
      dfa->nexts[idx] = node->next->node_idx;
Packit Service 20376f
      break;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  return err;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Duplicate the epsilon closure of the node ROOT_NODE.
Packit Service 20376f
   Note that duplicated nodes have constraint INIT_CONSTRAINT in addition
Packit Service 20376f
   to their own constraint.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node,
Packit Service 20376f
			int root_node, unsigned int init_constraint)
Packit Service 20376f
{
Packit Service 20376f
  int org_node, clone_node, ret;
Packit Service 20376f
  unsigned int constraint = init_constraint;
Packit Service 20376f
  for (org_node = top_org_node, clone_node = top_clone_node;;)
Packit Service 20376f
    {
Packit Service 20376f
      int org_dest, clone_dest;
Packit Service 20376f
      if (dfa->nodes[org_node].type == OP_BACK_REF)
Packit Service 20376f
	{
Packit Service 20376f
	  /* If the back reference epsilon-transit, its destination must
Packit Service 20376f
	     also have the constraint.  Then duplicate the epsilon closure
Packit Service 20376f
	     of the destination of the back reference, and store it in
Packit Service 20376f
	     edests of the back reference.  */
Packit Service 20376f
	  org_dest = dfa->nexts[org_node];
Packit Service 20376f
	  re_node_set_empty (dfa->edests + clone_node);
Packit Service 20376f
	  clone_dest = duplicate_node (dfa, org_dest, constraint);
Packit Service 20376f
	  if (BE (clone_dest == -1, 0))
Packit Service 20376f
	    return REG_ESPACE;
Packit Service 20376f
	  dfa->nexts[clone_node] = dfa->nexts[org_node];
Packit Service 20376f
	  ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
Packit Service 20376f
	  if (BE (ret < 0, 0))
Packit Service 20376f
	    return REG_ESPACE;
Packit Service 20376f
	}
Packit Service 20376f
      else if (dfa->edests[org_node].nelem == 0)
Packit Service 20376f
	{
Packit Service 20376f
	  /* In case of the node can't epsilon-transit, don't duplicate the
Packit Service 20376f
	     destination and store the original destination as the
Packit Service 20376f
	     destination of the node.  */
Packit Service 20376f
	  dfa->nexts[clone_node] = dfa->nexts[org_node];
Packit Service 20376f
	  break;
Packit Service 20376f
	}
Packit Service 20376f
      else if (dfa->edests[org_node].nelem == 1)
Packit Service 20376f
	{
Packit Service 20376f
	  /* In case of the node can epsilon-transit, and it has only one
Packit Service 20376f
	     destination.  */
Packit Service 20376f
	  org_dest = dfa->edests[org_node].elems[0];
Packit Service 20376f
	  re_node_set_empty (dfa->edests + clone_node);
Packit Service 20376f
	  /* If the node is root_node itself, it means the epsilon clsoure
Packit Service 20376f
	     has a loop.   Then tie it to the destination of the root_node.  */
Packit Service 20376f
	  if (org_node == root_node && clone_node != org_node)
Packit Service 20376f
	    {
Packit Service 20376f
	      ret = re_node_set_insert (dfa->edests + clone_node, org_dest);
Packit Service 20376f
	      if (BE (ret < 0, 0))
Packit Service 20376f
		return REG_ESPACE;
Packit Service 20376f
	      break;
Packit Service 20376f
	    }
Packit Service 20376f
	  /* In case of the node has another constraint, add it.  */
Packit Service 20376f
	  constraint |= dfa->nodes[org_node].constraint;
Packit Service 20376f
	  clone_dest = duplicate_node (dfa, org_dest, constraint);
Packit Service 20376f
	  if (BE (clone_dest == -1, 0))
Packit Service 20376f
	    return REG_ESPACE;
Packit Service 20376f
	  ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
Packit Service 20376f
	  if (BE (ret < 0, 0))
Packit Service 20376f
	    return REG_ESPACE;
Packit Service 20376f
	}
Packit Service 20376f
      else /* dfa->edests[org_node].nelem == 2 */
Packit Service 20376f
	{
Packit Service 20376f
	  /* In case of the node can epsilon-transit, and it has two
Packit Service 20376f
	     destinations. In the bin_tree_t and DFA, that's '|' and '*'.   */
Packit Service 20376f
	  org_dest = dfa->edests[org_node].elems[0];
Packit Service 20376f
	  re_node_set_empty (dfa->edests + clone_node);
Packit Service 20376f
	  /* Search for a duplicated node which satisfies the constraint.  */
Packit Service 20376f
	  clone_dest = search_duplicated_node (dfa, org_dest, constraint);
Packit Service 20376f
	  if (clone_dest == -1)
Packit Service 20376f
	    {
Packit Service 20376f
	      /* There is no such duplicated node, create a new one.  */
Packit Service 20376f
	      reg_errcode_t err;
Packit Service 20376f
	      clone_dest = duplicate_node (dfa, org_dest, constraint);
Packit Service 20376f
	      if (BE (clone_dest == -1, 0))
Packit Service 20376f
		return REG_ESPACE;
Packit Service 20376f
	      ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
Packit Service 20376f
	      if (BE (ret < 0, 0))
Packit Service 20376f
		return REG_ESPACE;
Packit Service 20376f
	      err = duplicate_node_closure (dfa, org_dest, clone_dest,
Packit Service 20376f
					    root_node, constraint);
Packit Service 20376f
	      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
		return err;
Packit Service 20376f
	    }
Packit Service 20376f
	  else
Packit Service 20376f
	    {
Packit Service 20376f
	      /* There is a duplicated node which satisfies the constraint,
Packit Service 20376f
		 use it to avoid infinite loop.  */
Packit Service 20376f
	      ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
Packit Service 20376f
	      if (BE (ret < 0, 0))
Packit Service 20376f
		return REG_ESPACE;
Packit Service 20376f
	    }
Packit Service 20376f
Packit Service 20376f
	  org_dest = dfa->edests[org_node].elems[1];
Packit Service 20376f
	  clone_dest = duplicate_node (dfa, org_dest, constraint);
Packit Service 20376f
	  if (BE (clone_dest == -1, 0))
Packit Service 20376f
	    return REG_ESPACE;
Packit Service 20376f
	  ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);
Packit Service 20376f
	  if (BE (ret < 0, 0))
Packit Service 20376f
	    return REG_ESPACE;
Packit Service 20376f
	}
Packit Service 20376f
      org_node = org_dest;
Packit Service 20376f
      clone_node = clone_dest;
Packit Service 20376f
    }
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Search for a node which is duplicated from the node ORG_NODE, and
Packit Service 20376f
   satisfies the constraint CONSTRAINT.  */
Packit Service 20376f
Packit Service 20376f
static int
Packit Service 20376f
search_duplicated_node (const re_dfa_t *dfa, int org_node,
Packit Service 20376f
			unsigned int constraint)
Packit Service 20376f
{
Packit Service 20376f
  int idx;
Packit Service 20376f
  for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx)
Packit Service 20376f
    {
Packit Service 20376f
      if (org_node == dfa->org_indices[idx]
Packit Service 20376f
	  && constraint == dfa->nodes[idx].constraint)
Packit Service 20376f
	return idx; /* Found.  */
Packit Service 20376f
    }
Packit Service 20376f
  return -1; /* Not found.  */
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT.
Packit Service 20376f
   Return the index of the new node, or -1 if insufficient storage is
Packit Service 20376f
   available.  */
Packit Service 20376f
Packit Service 20376f
static int
Packit Service 20376f
duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint)
Packit Service 20376f
{
Packit Service 20376f
  int dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]);
Packit Service 20376f
  if (BE (dup_idx != -1, 1))
Packit Service 20376f
    {
Packit Service 20376f
      dfa->nodes[dup_idx].constraint = constraint;
Packit Service 20376f
      dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].constraint;
Packit Service 20376f
      dfa->nodes[dup_idx].duplicated = 1;
Packit Service 20376f
Packit Service 20376f
      /* Store the index of the original node.  */
Packit Service 20376f
      dfa->org_indices[dup_idx] = org_idx;
Packit Service 20376f
    }
Packit Service 20376f
  return dup_idx;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
calc_inveclosure (re_dfa_t *dfa)
Packit Service 20376f
{
Packit Service 20376f
  int ret;
Packit Service 20376f
  unsigned int src, idx;
Packit Service 20376f
  for (idx = 0; idx < dfa->nodes_len; ++idx)
Packit Service 20376f
    re_node_set_init_empty (dfa->inveclosures + idx);
Packit Service 20376f
Packit Service 20376f
  for (src = 0; src < dfa->nodes_len; ++src)
Packit Service 20376f
    {
Packit Service 20376f
      int *elems = dfa->eclosures[src].elems;
Packit Service 20376f
      int idx;
Packit Service 20376f
      for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx)
Packit Service 20376f
	{
Packit Service 20376f
	  ret = re_node_set_insert_last (dfa->inveclosures + elems[idx], src);
Packit Service 20376f
	  if (BE (ret == -1, 0))
Packit Service 20376f
	    return REG_ESPACE;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Calculate "eclosure" for all the node in DFA.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
calc_eclosure (re_dfa_t *dfa)
Packit Service 20376f
{
Packit Service 20376f
  size_t node_idx;
Packit Service 20376f
  int incomplete;
Packit Service 20376f
#ifdef DEBUG
Packit Service 20376f
  assert (dfa->nodes_len > 0);
Packit Service 20376f
#endif
Packit Service 20376f
  incomplete = 0;
Packit Service 20376f
  /* For each nodes, calculate epsilon closure.  */
Packit Service 20376f
  for (node_idx = 0; ; ++node_idx)
Packit Service 20376f
    {
Packit Service 20376f
      reg_errcode_t err;
Packit Service 20376f
      re_node_set eclosure_elem;
Packit Service 20376f
      if (node_idx == dfa->nodes_len)
Packit Service 20376f
	{
Packit Service 20376f
	  if (!incomplete)
Packit Service 20376f
	    break;
Packit Service 20376f
	  incomplete = 0;
Packit Service 20376f
	  node_idx = 0;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
#ifdef DEBUG
Packit Service 20376f
      assert (dfa->eclosures[node_idx].nelem != -1);
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
      /* If we have already calculated, skip it.  */
Packit Service 20376f
      if (dfa->eclosures[node_idx].nelem != 0)
Packit Service 20376f
	continue;
Packit Service 20376f
      /* Calculate epsilon closure of `node_idx'.  */
Packit Service 20376f
      err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, 1);
Packit Service 20376f
      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	return err;
Packit Service 20376f
Packit Service 20376f
      if (dfa->eclosures[node_idx].nelem == 0)
Packit Service 20376f
	{
Packit Service 20376f
	  incomplete = 1;
Packit Service 20376f
	  re_node_set_free (&eclosure_elem);
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Calculate epsilon closure of NODE.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root)
Packit Service 20376f
{
Packit Service 20376f
  reg_errcode_t err;
Packit Service 20376f
  int i;
Packit Service 20376f
  re_node_set eclosure;
Packit Service 20376f
  int ret;
Packit Service 20376f
  int incomplete = 0;
Packit Service 20376f
  err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1);
Packit Service 20376f
  if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
    return err;
Packit Service 20376f
Packit Service 20376f
  /* This indicates that we are calculating this node now.
Packit Service 20376f
     We reference this value to avoid infinite loop.  */
Packit Service 20376f
  dfa->eclosures[node].nelem = -1;
Packit Service 20376f
Packit Service 20376f
  /* If the current node has constraints, duplicate all nodes
Packit Service 20376f
     since they must inherit the constraints.  */
Packit Service 20376f
  if (dfa->nodes[node].constraint
Packit Service 20376f
      && dfa->edests[node].nelem
Packit Service 20376f
      && !dfa->nodes[dfa->edests[node].elems[0]].duplicated)
Packit Service 20376f
    {
Packit Service 20376f
      err = duplicate_node_closure (dfa, node, node, node,
Packit Service 20376f
				    dfa->nodes[node].constraint);
Packit Service 20376f
      if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	return err;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  /* Expand each epsilon destination nodes.  */
Packit Service 20376f
  if (IS_EPSILON_NODE(dfa->nodes[node].type))
Packit Service 20376f
    for (i = 0; i < dfa->edests[node].nelem; ++i)
Packit Service 20376f
      {
Packit Service 20376f
	re_node_set eclosure_elem;
Packit Service 20376f
	int edest = dfa->edests[node].elems[i];
Packit Service 20376f
	/* If calculating the epsilon closure of `edest' is in progress,
Packit Service 20376f
	   return intermediate result.  */
Packit Service 20376f
	if (dfa->eclosures[edest].nelem == -1)
Packit Service 20376f
	  {
Packit Service 20376f
	    incomplete = 1;
Packit Service 20376f
	    continue;
Packit Service 20376f
	  }
Packit Service 20376f
	/* If we haven't calculated the epsilon closure of `edest' yet,
Packit Service 20376f
	   calculate now. Otherwise use calculated epsilon closure.  */
Packit Service 20376f
	if (dfa->eclosures[edest].nelem == 0)
Packit Service 20376f
	  {
Packit Service 20376f
	    err = calc_eclosure_iter (&eclosure_elem, dfa, edest, 0);
Packit Service 20376f
	    if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	      return err;
Packit Service 20376f
	  }
Packit Service 20376f
	else
Packit Service 20376f
	  eclosure_elem = dfa->eclosures[edest];
Packit Service 20376f
	/* Merge the epsilon closure of `edest'.  */
Packit Service 20376f
	err = re_node_set_merge (&eclosure, &eclosure_elem);
Packit Service 20376f
	if (BE (err != REG_NOERROR, 0))
Packit Service 20376f
	  return err;
Packit Service 20376f
	/* If the epsilon closure of `edest' is incomplete,
Packit Service 20376f
	   the epsilon closure of this node is also incomplete.  */
Packit Service 20376f
	if (dfa->eclosures[edest].nelem == 0)
Packit Service 20376f
	  {
Packit Service 20376f
	    incomplete = 1;
Packit Service 20376f
	    re_node_set_free (&eclosure_elem);
Packit Service 20376f
	  }
Packit Service 20376f
      }
Packit Service 20376f
Packit Service 20376f
  /* An epsilon closure includes itself.  */
Packit Service 20376f
  ret = re_node_set_insert (&eclosure, node);
Packit Service 20376f
  if (BE (ret < 0, 0))
Packit Service 20376f
    return REG_ESPACE;
Packit Service 20376f
  if (incomplete && !root)
Packit Service 20376f
    dfa->eclosures[node].nelem = 0;
Packit Service 20376f
  else
Packit Service 20376f
    dfa->eclosures[node] = eclosure;
Packit Service 20376f
  *new_set = eclosure;
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f

Packit Service 20376f
/* Functions for token which are used in the parser.  */
Packit Service 20376f
Packit Service 20376f
/* Fetch a token from INPUT.
Packit Service 20376f
   We must not use this function inside bracket expressions.  */
Packit Service 20376f
Packit Service 20376f
static void
Packit Service 20376f
internal_function
Packit Service 20376f
fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax)
Packit Service 20376f
{
Packit Service 20376f
  re_string_skip_bytes (input, peek_token (result, input, syntax));
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Peek a token from INPUT, and return the length of the token.
Packit Service 20376f
   We must not use this function inside bracket expressions.  */
Packit Service 20376f
Packit Service 20376f
static int
Packit Service 20376f
internal_function
Packit Service 20376f
peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
Packit Service 20376f
{
Packit Service 20376f
  unsigned char c;
Packit Service 20376f
Packit Service 20376f
  if (re_string_eoi (input))
Packit Service 20376f
    {
Packit Service 20376f
      token->type = END_OF_RE;
Packit Service 20376f
      return 0;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  c = re_string_peek_byte (input, 0);
Packit Service 20376f
  token->opr.c = c;
Packit Service 20376f
Packit Service 20376f
  token->word_char = 0;
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  token->mb_partial = 0;
Packit Service 20376f
  if (input->mb_cur_max > 1 &&
Packit Service 20376f
      !re_string_first_byte (input, re_string_cur_idx (input)))
Packit Service 20376f
    {
Packit Service 20376f
      token->type = CHARACTER;
Packit Service 20376f
      token->mb_partial = 1;
Packit Service 20376f
      return 1;
Packit Service 20376f
    }
Packit Service 20376f
#endif
Packit Service 20376f
  if (c == '\\')
Packit Service 20376f
    {
Packit Service 20376f
      unsigned char c2;
Packit Service 20376f
      if (re_string_cur_idx (input) + 1 >= re_string_length (input))
Packit Service 20376f
	{
Packit Service 20376f
	  token->type = BACK_SLASH;
Packit Service 20376f
	  return 1;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      c2 = re_string_peek_byte_case (input, 1);
Packit Service 20376f
      token->opr.c = c2;
Packit Service 20376f
      token->type = CHARACTER;
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
      if (input->mb_cur_max > 1)
Packit Service 20376f
	{
Packit Service 20376f
	  wint_t wc = re_string_wchar_at (input,
Packit Service 20376f
					  re_string_cur_idx (input) + 1);
Packit Service 20376f
	  token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
Packit Service 20376f
	}
Packit Service 20376f
      else
Packit Service 20376f
#endif
Packit Service 20376f
	token->word_char = IS_WORD_CHAR (c2) != 0;
Packit Service 20376f
Packit Service 20376f
      switch (c2)
Packit Service 20376f
	{
Packit Service 20376f
	case '|':
Packit Service 20376f
	  if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR))
Packit Service 20376f
	    token->type = OP_ALT;
Packit Service 20376f
	  break;
Packit Service 20376f
	case '1': case '2': case '3': case '4': case '5':
Packit Service 20376f
	case '6': case '7': case '8': case '9':
Packit Service 20376f
	  if (!(syntax & RE_NO_BK_REFS))
Packit Service 20376f
	    {
Packit Service 20376f
	      token->type = OP_BACK_REF;
Packit Service 20376f
	      token->opr.idx = c2 - '1';
Packit Service 20376f
	    }
Packit Service 20376f
	  break;
Packit Service 20376f
	case '<':
Packit Service 20376f
	  if (!(syntax & RE_NO_GNU_OPS))
Packit Service 20376f
	    {
Packit Service 20376f
	      token->type = ANCHOR;
Packit Service 20376f
	      token->opr.ctx_type = WORD_FIRST;
Packit Service 20376f
	    }
Packit Service 20376f
	  break;
Packit Service 20376f
	case '>':
Packit Service 20376f
	  if (!(syntax & RE_NO_GNU_OPS))
Packit Service 20376f
	    {
Packit Service 20376f
	      token->type = ANCHOR;
Packit Service 20376f
	      token->opr.ctx_type = WORD_LAST;
Packit Service 20376f
	    }
Packit Service 20376f
	  break;
Packit Service 20376f
	case 'b':
Packit Service 20376f
	  if (!(syntax & RE_NO_GNU_OPS))
Packit Service 20376f
	    {
Packit Service 20376f
	      token->type = ANCHOR;
Packit Service 20376f
	      token->opr.ctx_type = WORD_DELIM;
Packit Service 20376f
	    }
Packit Service 20376f
	  break;
Packit Service 20376f
	case 'B':
Packit Service 20376f
	  if (!(syntax & RE_NO_GNU_OPS))
Packit Service 20376f
	    {
Packit Service 20376f
	      token->type = ANCHOR;
Packit Service 20376f
	      token->opr.ctx_type = NOT_WORD_DELIM;
Packit Service 20376f
	    }
Packit Service 20376f
	  break;
Packit Service 20376f
	case 'w':
Packit Service 20376f
	  if (!(syntax & RE_NO_GNU_OPS))
Packit Service 20376f
	    token->type = OP_WORD;
Packit Service 20376f
	  break;
Packit Service 20376f
	case 'W':
Packit Service 20376f
	  if (!(syntax & RE_NO_GNU_OPS))
Packit Service 20376f
	    token->type = OP_NOTWORD;
Packit Service 20376f
	  break;
Packit Service 20376f
	case 's':
Packit Service 20376f
	  if (!(syntax & RE_NO_GNU_OPS))
Packit Service 20376f
	    token->type = OP_SPACE;
Packit Service 20376f
	  break;
Packit Service 20376f
	case 'S':
Packit Service 20376f
	  if (!(syntax & RE_NO_GNU_OPS))
Packit Service 20376f
	    token->type = OP_NOTSPACE;
Packit Service 20376f
	  break;
Packit Service 20376f
	case '`':
Packit Service 20376f
	  if (!(syntax & RE_NO_GNU_OPS))
Packit Service 20376f
	    {
Packit Service 20376f
	      token->type = ANCHOR;
Packit Service 20376f
	      token->opr.ctx_type = BUF_FIRST;
Packit Service 20376f
	    }
Packit Service 20376f
	  break;
Packit Service 20376f
	case '\'':
Packit Service 20376f
	  if (!(syntax & RE_NO_GNU_OPS))
Packit Service 20376f
	    {
Packit Service 20376f
	      token->type = ANCHOR;
Packit Service 20376f
	      token->opr.ctx_type = BUF_LAST;
Packit Service 20376f
	    }
Packit Service 20376f
	  break;
Packit Service 20376f
	case '(':
Packit Service 20376f
	  if (!(syntax & RE_NO_BK_PARENS))
Packit Service 20376f
	    token->type = OP_OPEN_SUBEXP;
Packit Service 20376f
	  break;
Packit Service 20376f
	case ')':
Packit Service 20376f
	  if (!(syntax & RE_NO_BK_PARENS))
Packit Service 20376f
	    token->type = OP_CLOSE_SUBEXP;
Packit Service 20376f
	  break;
Packit Service 20376f
	case '+':
Packit Service 20376f
	  if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))
Packit Service 20376f
	    token->type = OP_DUP_PLUS;
Packit Service 20376f
	  break;
Packit Service 20376f
	case '?':
Packit Service 20376f
	  if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))
Packit Service 20376f
	    token->type = OP_DUP_QUESTION;
Packit Service 20376f
	  break;
Packit Service 20376f
	case '{':
Packit Service 20376f
	  if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))
Packit Service 20376f
	    token->type = OP_OPEN_DUP_NUM;
Packit Service 20376f
	  break;
Packit Service 20376f
	case '}':
Packit Service 20376f
	  if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))
Packit Service 20376f
	    token->type = OP_CLOSE_DUP_NUM;
Packit Service 20376f
	  break;
Packit Service 20376f
	default:
Packit Service 20376f
	  break;
Packit Service 20376f
	}
Packit Service 20376f
      return 2;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  token->type = CHARACTER;
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  if (input->mb_cur_max > 1)
Packit Service 20376f
    {
Packit Service 20376f
      wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input));
Packit Service 20376f
      token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
#endif
Packit Service 20376f
    token->word_char = IS_WORD_CHAR (token->opr.c);
Packit Service 20376f
Packit Service 20376f
  switch (c)
Packit Service 20376f
    {
Packit Service 20376f
    case '\n':
Packit Service 20376f
      if (syntax & RE_NEWLINE_ALT)
Packit Service 20376f
	token->type = OP_ALT;
Packit Service 20376f
      break;
Packit Service 20376f
    case '|':
Packit Service 20376f
      if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR))
Packit Service 20376f
	token->type = OP_ALT;
Packit Service 20376f
      break;
Packit Service 20376f
    case '*':
Packit Service 20376f
      token->type = OP_DUP_ASTERISK;
Packit Service 20376f
      break;
Packit Service 20376f
    case '+':
Packit Service 20376f
      if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))
Packit Service 20376f
	token->type = OP_DUP_PLUS;
Packit Service 20376f
      break;
Packit Service 20376f
    case '?':
Packit Service 20376f
      if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))
Packit Service 20376f
	token->type = OP_DUP_QUESTION;
Packit Service 20376f
      break;
Packit Service 20376f
    case '{':
Packit Service 20376f
      if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
Packit Service 20376f
	token->type = OP_OPEN_DUP_NUM;
Packit Service 20376f
      break;
Packit Service 20376f
    case '}':
Packit Service 20376f
      if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
Packit Service 20376f
	token->type = OP_CLOSE_DUP_NUM;
Packit Service 20376f
      break;
Packit Service 20376f
    case '(':
Packit Service 20376f
      if (syntax & RE_NO_BK_PARENS)
Packit Service 20376f
	token->type = OP_OPEN_SUBEXP;
Packit Service 20376f
      break;
Packit Service 20376f
    case ')':
Packit Service 20376f
      if (syntax & RE_NO_BK_PARENS)
Packit Service 20376f
	token->type = OP_CLOSE_SUBEXP;
Packit Service 20376f
      break;
Packit Service 20376f
    case '[':
Packit Service 20376f
      token->type = OP_OPEN_BRACKET;
Packit Service 20376f
      break;
Packit Service 20376f
    case '.':
Packit Service 20376f
      token->type = OP_PERIOD;
Packit Service 20376f
      break;
Packit Service 20376f
    case '^':
Packit Service 20376f
      if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) &&
Packit Service 20376f
	  re_string_cur_idx (input) != 0)
Packit Service 20376f
	{
Packit Service 20376f
	  char prev = re_string_peek_byte (input, -1);
Packit Service 20376f
	  if (!(syntax & RE_NEWLINE_ALT) || prev != '\n')
Packit Service 20376f
	    break;
Packit Service 20376f
	}
Packit Service 20376f
      token->type = ANCHOR;
Packit Service 20376f
      token->opr.ctx_type = LINE_FIRST;
Packit Service 20376f
      break;
Packit Service 20376f
    case '$':
Packit Service 20376f
      if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) &&
Packit Service 20376f
	  re_string_cur_idx (input) + 1 != re_string_length (input))
Packit Service 20376f
	{
Packit Service 20376f
	  re_token_t next;
Packit Service 20376f
	  re_string_skip_bytes (input, 1);
Packit Service 20376f
	  peek_token (&next, input, syntax);
Packit Service 20376f
	  re_string_skip_bytes (input, -1);
Packit Service 20376f
	  if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP)
Packit Service 20376f
	    break;
Packit Service 20376f
	}
Packit Service 20376f
      token->type = ANCHOR;
Packit Service 20376f
      token->opr.ctx_type = LINE_LAST;
Packit Service 20376f
      break;
Packit Service 20376f
    default:
Packit Service 20376f
      break;
Packit Service 20376f
    }
Packit Service 20376f
  return 1;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Peek a token from INPUT, and return the length of the token.
Packit Service 20376f
   We must not use this function out of bracket expressions.  */
Packit Service 20376f
Packit Service 20376f
static int
Packit Service 20376f
internal_function
Packit Service 20376f
peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
Packit Service 20376f
{
Packit Service 20376f
  unsigned char c;
Packit Service 20376f
  if (re_string_eoi (input))
Packit Service 20376f
    {
Packit Service 20376f
      token->type = END_OF_RE;
Packit Service 20376f
      return 0;
Packit Service 20376f
    }
Packit Service 20376f
  c = re_string_peek_byte (input, 0);
Packit Service 20376f
  token->opr.c = c;
Packit Service 20376f
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  if (input->mb_cur_max > 1 &&
Packit Service 20376f
      !re_string_first_byte (input, re_string_cur_idx (input)))
Packit Service 20376f
    {
Packit Service 20376f
      token->type = CHARACTER;
Packit Service 20376f
      return 1;
Packit Service 20376f
    }
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
Packit Service 20376f
  if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS)
Packit Service 20376f
      && re_string_cur_idx (input) + 1 < re_string_length (input))
Packit Service 20376f
    {
Packit Service 20376f
      /* In this case, '\' escape a character.  */
Packit Service 20376f
      unsigned char c2;
Packit Service 20376f
      re_string_skip_bytes (input, 1);
Packit Service 20376f
      c2 = re_string_peek_byte (input, 0);
Packit Service 20376f
      token->opr.c = c2;
Packit Service 20376f
      token->type = CHARACTER;
Packit Service 20376f
      return 1;
Packit Service 20376f
    }
Packit Service 20376f
  if (c == '[') /* '[' is a special char in a bracket exps.  */
Packit Service 20376f
    {
Packit Service 20376f
      unsigned char c2;
Packit Service 20376f
      int token_len;
Packit Service 20376f
      if (re_string_cur_idx (input) + 1 < re_string_length (input))
Packit Service 20376f
	c2 = re_string_peek_byte (input, 1);
Packit Service 20376f
      else
Packit Service 20376f
	c2 = 0;
Packit Service 20376f
      token->opr.c = c2;
Packit Service 20376f
      token_len = 2;
Packit Service 20376f
      switch (c2)
Packit Service 20376f
	{
Packit Service 20376f
	case '.':
Packit Service 20376f
	  token->type = OP_OPEN_COLL_ELEM;
Packit Service 20376f
	  break;
Packit Service 20376f
	case '=':
Packit Service 20376f
	  token->type = OP_OPEN_EQUIV_CLASS;
Packit Service 20376f
	  break;
Packit Service 20376f
	case ':':
Packit Service 20376f
	  if (syntax & RE_CHAR_CLASSES)
Packit Service 20376f
	    {
Packit Service 20376f
	      token->type = OP_OPEN_CHAR_CLASS;
Packit Service 20376f
	      break;
Packit Service 20376f
	    }
Packit Service 20376f
	  /* else fall through.  */
Packit Service 20376f
	default:
Packit Service 20376f
	  token->type = CHARACTER;
Packit Service 20376f
	  token->opr.c = c;
Packit Service 20376f
	  token_len = 1;
Packit Service 20376f
	  break;
Packit Service 20376f
	}
Packit Service 20376f
      return token_len;
Packit Service 20376f
    }
Packit Service 20376f
  switch (c)
Packit Service 20376f
    {
Packit Service 20376f
    case '-':
Packit Service 20376f
      token->type = OP_CHARSET_RANGE;
Packit Service 20376f
      break;
Packit Service 20376f
    case ']':
Packit Service 20376f
      token->type = OP_CLOSE_BRACKET;
Packit Service 20376f
      break;
Packit Service 20376f
    case '^':
Packit Service 20376f
      token->type = OP_NON_MATCH_LIST;
Packit Service 20376f
      break;
Packit Service 20376f
    default:
Packit Service 20376f
      token->type = CHARACTER;
Packit Service 20376f
    }
Packit Service 20376f
  return 1;
Packit Service 20376f
}
Packit Service 20376f

Packit Service 20376f
/* Functions for parser.  */
Packit Service 20376f
Packit Service 20376f
/* Entry point of the parser.
Packit Service 20376f
   Parse the regular expression REGEXP and return the structure tree.
Packit Service 20376f
   If an error is occured, ERR is set by error code, and return NULL.
Packit Service 20376f
   This function build the following tree, from regular expression <reg_exp>:
Packit Service 20376f
	   CAT
Packit Service 20376f
	   / \
Packit Service 20376f
	  /   \
Packit Service 20376f
   <reg_exp>  EOR
Packit Service 20376f
Packit Service 20376f
   CAT means concatenation.
Packit Service 20376f
   EOR means end of regular expression.  */
Packit Service 20376f
Packit Service 20376f
static bin_tree_t *
Packit Service 20376f
parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax,
Packit Service 20376f
       reg_errcode_t *err)
Packit Service 20376f
{
Packit Service 20376f
  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
Packit Service 20376f
  bin_tree_t *tree, *eor, *root;
Packit Service 20376f
  re_token_t current_token;
Packit Service 20376f
  dfa->syntax = syntax;
Packit Service 20376f
  fetch_token (&current_token, regexp, syntax | RE_CARET_ANCHORS_HERE);
Packit Service 20376f
  tree = parse_reg_exp (regexp, preg, &current_token, syntax, 0, err);
Packit Service 20376f
  if (BE (*err != REG_NOERROR && tree == NULL, 0))
Packit Service 20376f
    return NULL;
Packit Service 20376f
  eor = create_tree (dfa, NULL, NULL, END_OF_RE);
Packit Service 20376f
  if (tree != NULL)
Packit Service 20376f
    root = create_tree (dfa, tree, eor, CONCAT);
Packit Service 20376f
  else
Packit Service 20376f
    root = eor;
Packit Service 20376f
  if (BE (eor == NULL || root == NULL, 0))
Packit Service 20376f
    {
Packit Service 20376f
      *err = REG_ESPACE;
Packit Service 20376f
      return NULL;
Packit Service 20376f
    }
Packit Service 20376f
  return root;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* This function build the following tree, from regular expression
Packit Service 20376f
   <branch1>|<branch2>:
Packit Service 20376f
	   ALT
Packit Service 20376f
	   / \
Packit Service 20376f
	  /   \
Packit Service 20376f
   <branch1> <branch2>
Packit Service 20376f
Packit Service 20376f
   ALT means alternative, which represents the operator `|'.  */
Packit Service 20376f
Packit Service 20376f
static bin_tree_t *
Packit Service 20376f
parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
Packit Service 20376f
	       reg_syntax_t syntax, int nest, reg_errcode_t *err)
Packit Service 20376f
{
Packit Service 20376f
  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
Packit Service 20376f
  bin_tree_t *tree, *branch = NULL;
Packit Service 20376f
  tree = parse_branch (regexp, preg, token, syntax, nest, err);
Packit Service 20376f
  if (BE (*err != REG_NOERROR && tree == NULL, 0))
Packit Service 20376f
    return NULL;
Packit Service 20376f
Packit Service 20376f
  while (token->type == OP_ALT)
Packit Service 20376f
    {
Packit Service 20376f
      fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE);
Packit Service 20376f
      if (token->type != OP_ALT && token->type != END_OF_RE
Packit Service 20376f
	  && (nest == 0 || token->type != OP_CLOSE_SUBEXP))
Packit Service 20376f
	{
Packit Service 20376f
	  branch = parse_branch (regexp, preg, token, syntax, nest, err);
Packit Service 20376f
	  if (BE (*err != REG_NOERROR && branch == NULL, 0))
Packit Service 20376f
	    return NULL;
Packit Service 20376f
	}
Packit Service 20376f
      else
Packit Service 20376f
	branch = NULL;
Packit Service 20376f
      tree = create_tree (dfa, tree, branch, OP_ALT);
Packit Service 20376f
      if (BE (tree == NULL, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  *err = REG_ESPACE;
Packit Service 20376f
	  return NULL;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  return tree;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* This function build the following tree, from regular expression
Packit Service 20376f
   <exp1><exp2>:
Packit Service 20376f
	CAT
Packit Service 20376f
	/ \
Packit Service 20376f
       /   \
Packit Service 20376f
   <exp1> <exp2>
Packit Service 20376f
Packit Service 20376f
   CAT means concatenation.  */
Packit Service 20376f
Packit Service 20376f
static bin_tree_t *
Packit Service 20376f
parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token,
Packit Service 20376f
	      reg_syntax_t syntax, int nest, reg_errcode_t *err)
Packit Service 20376f
{
Packit Service 20376f
  bin_tree_t *tree, *exp;
Packit Service 20376f
  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
Packit Service 20376f
  tree = parse_expression (regexp, preg, token, syntax, nest, err);
Packit Service 20376f
  if (BE (*err != REG_NOERROR && tree == NULL, 0))
Packit Service 20376f
    return NULL;
Packit Service 20376f
Packit Service 20376f
  while (token->type != OP_ALT && token->type != END_OF_RE
Packit Service 20376f
	 && (nest == 0 || token->type != OP_CLOSE_SUBEXP))
Packit Service 20376f
    {
Packit Service 20376f
      exp = parse_expression (regexp, preg, token, syntax, nest, err);
Packit Service 20376f
      if (BE (*err != REG_NOERROR && exp == NULL, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  return NULL;
Packit Service 20376f
	}
Packit Service 20376f
      if (tree != NULL && exp != NULL)
Packit Service 20376f
	{
Packit Service 20376f
	  tree = create_tree (dfa, tree, exp, CONCAT);
Packit Service 20376f
	  if (tree == NULL)
Packit Service 20376f
	    {
Packit Service 20376f
	      *err = REG_ESPACE;
Packit Service 20376f
	      return NULL;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
      else if (tree == NULL)
Packit Service 20376f
	tree = exp;
Packit Service 20376f
      /* Otherwise exp == NULL, we don't need to create new tree.  */
Packit Service 20376f
    }
Packit Service 20376f
  return tree;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* This function build the following tree, from regular expression a*:
Packit Service 20376f
	 *
Packit Service 20376f
	 |
Packit Service 20376f
	 a
Packit Service 20376f
*/
Packit Service 20376f
Packit Service 20376f
static bin_tree_t *
Packit Service 20376f
parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
Packit Service 20376f
		  reg_syntax_t syntax, int nest, reg_errcode_t *err)
Packit Service 20376f
{
Packit Service 20376f
  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
Packit Service 20376f
  bin_tree_t *tree;
Packit Service 20376f
  switch (token->type)
Packit Service 20376f
    {
Packit Service 20376f
    case CHARACTER:
Packit Service 20376f
      tree = create_token_tree (dfa, NULL, NULL, token);
Packit Service 20376f
      if (BE (tree == NULL, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  *err = REG_ESPACE;
Packit Service 20376f
	  return NULL;
Packit Service 20376f
	}
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
      if (dfa->mb_cur_max > 1)
Packit Service 20376f
	{
Packit Service 20376f
	  while (!re_string_eoi (regexp)
Packit Service 20376f
		 && !re_string_first_byte (regexp, re_string_cur_idx (regexp)))
Packit Service 20376f
	    {
Packit Service 20376f
	      bin_tree_t *mbc_remain;
Packit Service 20376f
	      fetch_token (token, regexp, syntax);
Packit Service 20376f
	      mbc_remain = create_token_tree (dfa, NULL, NULL, token);
Packit Service 20376f
	      tree = create_tree (dfa, tree, mbc_remain, CONCAT);
Packit Service 20376f
	      if (BE (mbc_remain == NULL || tree == NULL, 0))
Packit Service 20376f
		{
Packit Service 20376f
		  *err = REG_ESPACE;
Packit Service 20376f
		  return NULL;
Packit Service 20376f
		}
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
#endif
Packit Service 20376f
      break;
Packit Service 20376f
    case OP_OPEN_SUBEXP:
Packit Service 20376f
      tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err);
Packit Service 20376f
      if (BE (*err != REG_NOERROR && tree == NULL, 0))
Packit Service 20376f
	return NULL;
Packit Service 20376f
      break;
Packit Service 20376f
    case OP_OPEN_BRACKET:
Packit Service 20376f
      tree = parse_bracket_exp (regexp, dfa, token, syntax, err);
Packit Service 20376f
      if (BE (*err != REG_NOERROR && tree == NULL, 0))
Packit Service 20376f
	return NULL;
Packit Service 20376f
      break;
Packit Service 20376f
    case OP_BACK_REF:
Packit Service 20376f
      if (!BE (dfa->completed_bkref_map & (1 << token->opr.idx), 1))
Packit Service 20376f
	{
Packit Service 20376f
	  *err = REG_ESUBREG;
Packit Service 20376f
	  return NULL;
Packit Service 20376f
	}
Packit Service 20376f
      dfa->used_bkref_map |= 1 << token->opr.idx;
Packit Service 20376f
      tree = create_token_tree (dfa, NULL, NULL, token);
Packit Service 20376f
      if (BE (tree == NULL, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  *err = REG_ESPACE;
Packit Service 20376f
	  return NULL;
Packit Service 20376f
	}
Packit Service 20376f
      ++dfa->nbackref;
Packit Service 20376f
      dfa->has_mb_node = 1;
Packit Service 20376f
      break;
Packit Service 20376f
    case OP_OPEN_DUP_NUM:
Packit Service 20376f
      if (syntax & RE_CONTEXT_INVALID_DUP)
Packit Service 20376f
	{
Packit Service 20376f
	  *err = REG_BADRPT;
Packit Service 20376f
	  return NULL;
Packit Service 20376f
	}
Packit Service 20376f
      /* FALLTHROUGH */
Packit Service 20376f
    case OP_DUP_ASTERISK:
Packit Service 20376f
    case OP_DUP_PLUS:
Packit Service 20376f
    case OP_DUP_QUESTION:
Packit Service 20376f
      if (syntax & RE_CONTEXT_INVALID_OPS)
Packit Service 20376f
	{
Packit Service 20376f
	  *err = REG_BADRPT;
Packit Service 20376f
	  return NULL;
Packit Service 20376f
	}
Packit Service 20376f
      else if (syntax & RE_CONTEXT_INDEP_OPS)
Packit Service 20376f
	{
Packit Service 20376f
	  fetch_token (token, regexp, syntax);
Packit Service 20376f
	  return parse_expression (regexp, preg, token, syntax, nest, err);
Packit Service 20376f
	}
Packit Service 20376f
      /* else fall through  */
Packit Service 20376f
    case OP_CLOSE_SUBEXP:
Packit Service 20376f
      if ((token->type == OP_CLOSE_SUBEXP) &&
Packit Service 20376f
	  !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD))
Packit Service 20376f
	{
Packit Service 20376f
	  *err = REG_ERPAREN;
Packit Service 20376f
	  return NULL;
Packit Service 20376f
	}
Packit Service 20376f
      /* else fall through  */
Packit Service 20376f
    case OP_CLOSE_DUP_NUM:
Packit Service 20376f
      /* We treat it as a normal character.  */
Packit Service 20376f
Packit Service 20376f
      /* Then we can these characters as normal characters.  */
Packit Service 20376f
      token->type = CHARACTER;
Packit Service 20376f
      /* mb_partial and word_char bits should be initialized already
Packit Service 20376f
	 by peek_token.  */
Packit Service 20376f
      tree = create_token_tree (dfa, NULL, NULL, token);
Packit Service 20376f
      if (BE (tree == NULL, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  *err = REG_ESPACE;
Packit Service 20376f
	  return NULL;
Packit Service 20376f
	}
Packit Service 20376f
      break;
Packit Service 20376f
    case ANCHOR:
Packit Service 20376f
      if ((token->opr.ctx_type
Packit Service 20376f
	   & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST))
Packit Service 20376f
	  && dfa->word_ops_used == 0)
Packit Service 20376f
	init_word_char (dfa);
Packit Service 20376f
      if (token->opr.ctx_type == WORD_DELIM
Packit Service 20376f
	  || token->opr.ctx_type == NOT_WORD_DELIM)
Packit Service 20376f
	{
Packit Service 20376f
	  bin_tree_t *tree_first, *tree_last;
Packit Service 20376f
	  if (token->opr.ctx_type == WORD_DELIM)
Packit Service 20376f
	    {
Packit Service 20376f
	      token->opr.ctx_type = WORD_FIRST;
Packit Service 20376f
	      tree_first = create_token_tree (dfa, NULL, NULL, token);
Packit Service 20376f
	      token->opr.ctx_type = WORD_LAST;
Packit Service 20376f
	    }
Packit Service 20376f
	  else
Packit Service 20376f
	    {
Packit Service 20376f
	      token->opr.ctx_type = INSIDE_WORD;
Packit Service 20376f
	      tree_first = create_token_tree (dfa, NULL, NULL, token);
Packit Service 20376f
	      token->opr.ctx_type = INSIDE_NOTWORD;
Packit Service 20376f
	    }
Packit Service 20376f
	  tree_last = create_token_tree (dfa, NULL, NULL, token);
Packit Service 20376f
	  tree = create_tree (dfa, tree_first, tree_last, OP_ALT);
Packit Service 20376f
	  if (BE (tree_first == NULL || tree_last == NULL || tree == NULL, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      *err = REG_ESPACE;
Packit Service 20376f
	      return NULL;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
      else
Packit Service 20376f
	{
Packit Service 20376f
	  tree = create_token_tree (dfa, NULL, NULL, token);
Packit Service 20376f
	  if (BE (tree == NULL, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      *err = REG_ESPACE;
Packit Service 20376f
	      return NULL;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
      /* We must return here, since ANCHORs can't be followed
Packit Service 20376f
	 by repetition operators.
Packit Service 20376f
	 eg. RE"^*" is invalid or "<ANCHOR(^)><CHAR(*)>",
Packit Service 20376f
	     it must not be "<ANCHOR(^)><REPEAT(*)>".  */
Packit Service 20376f
      fetch_token (token, regexp, syntax);
Packit Service 20376f
      return tree;
Packit Service 20376f
    case OP_PERIOD:
Packit Service 20376f
      tree = create_token_tree (dfa, NULL, NULL, token);
Packit Service 20376f
      if (BE (tree == NULL, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  *err = REG_ESPACE;
Packit Service 20376f
	  return NULL;
Packit Service 20376f
	}
Packit Service 20376f
      if (dfa->mb_cur_max > 1)
Packit Service 20376f
	dfa->has_mb_node = 1;
Packit Service 20376f
      break;
Packit Service 20376f
    case OP_WORD:
Packit Service 20376f
    case OP_NOTWORD:
Packit Service 20376f
      tree = build_charclass_op (dfa, regexp->trans,
Packit Service 20376f
				 "alnum",
Packit Service 20376f
				 "_",
Packit Service 20376f
				 token->type == OP_NOTWORD, err);
Packit Service 20376f
      if (BE (*err != REG_NOERROR && tree == NULL, 0))
Packit Service 20376f
	return NULL;
Packit Service 20376f
      break;
Packit Service 20376f
    case OP_SPACE:
Packit Service 20376f
    case OP_NOTSPACE:
Packit Service 20376f
      tree = build_charclass_op (dfa, regexp->trans,
Packit Service 20376f
				 "space",
Packit Service 20376f
				 "",
Packit Service 20376f
				 token->type == OP_NOTSPACE, err);
Packit Service 20376f
      if (BE (*err != REG_NOERROR && tree == NULL, 0))
Packit Service 20376f
	return NULL;
Packit Service 20376f
      break;
Packit Service 20376f
    case OP_ALT:
Packit Service 20376f
    case END_OF_RE:
Packit Service 20376f
      return NULL;
Packit Service 20376f
    case BACK_SLASH:
Packit Service 20376f
      *err = REG_EESCAPE;
Packit Service 20376f
      return NULL;
Packit Service 20376f
    default:
Packit Service 20376f
      /* Must not happen?  */
Packit Service 20376f
#ifdef DEBUG
Packit Service 20376f
      assert (0);
Packit Service 20376f
#endif
Packit Service 20376f
      return NULL;
Packit Service 20376f
    }
Packit Service 20376f
  fetch_token (token, regexp, syntax);
Packit Service 20376f
Packit Service 20376f
  while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS
Packit Service 20376f
	 || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM)
Packit Service 20376f
    {
Packit Service 20376f
      tree = parse_dup_op (tree, regexp, dfa, token, syntax, err);
Packit Service 20376f
      if (BE (*err != REG_NOERROR && tree == NULL, 0))
Packit Service 20376f
	return NULL;
Packit Service 20376f
      /* In BRE consecutive duplications are not allowed.  */
Packit Service 20376f
      if ((syntax & RE_CONTEXT_INVALID_DUP)
Packit Service 20376f
	  && (token->type == OP_DUP_ASTERISK
Packit Service 20376f
	      || token->type == OP_OPEN_DUP_NUM))
Packit Service 20376f
	{
Packit Service 20376f
	  *err = REG_BADRPT;
Packit Service 20376f
	  return NULL;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  return tree;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* This function build the following tree, from regular expression
Packit Service 20376f
   (<reg_exp>):
Packit Service 20376f
	 SUBEXP
Packit Service 20376f
	    |
Packit Service 20376f
	<reg_exp>
Packit Service 20376f
*/
Packit Service 20376f
Packit Service 20376f
static bin_tree_t *
Packit Service 20376f
parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
Packit Service 20376f
	       reg_syntax_t syntax, int nest, reg_errcode_t *err)
Packit Service 20376f
{
Packit Service 20376f
  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;
Packit Service 20376f
  bin_tree_t *tree;
Packit Service 20376f
  size_t cur_nsub;
Packit Service 20376f
  cur_nsub = preg->re_nsub++;
Packit Service 20376f
Packit Service 20376f
  fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE);
Packit Service 20376f
Packit Service 20376f
  /* The subexpression may be a null string.  */
Packit Service 20376f
  if (token->type == OP_CLOSE_SUBEXP)
Packit Service 20376f
    tree = NULL;
Packit Service 20376f
  else
Packit Service 20376f
    {
Packit Service 20376f
      tree = parse_reg_exp (regexp, preg, token, syntax, nest, err);
Packit Service 20376f
      if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0))
Packit Service 20376f
	*err = REG_EPAREN;
Packit Service 20376f
      if (BE (*err != REG_NOERROR, 0))
Packit Service 20376f
	return NULL;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  if (cur_nsub <= '9' - '1')
Packit Service 20376f
    dfa->completed_bkref_map |= 1 << cur_nsub;
Packit Service 20376f
Packit Service 20376f
  tree = create_tree (dfa, tree, NULL, SUBEXP);
Packit Service 20376f
  if (BE (tree == NULL, 0))
Packit Service 20376f
    {
Packit Service 20376f
      *err = REG_ESPACE;
Packit Service 20376f
      return NULL;
Packit Service 20376f
    }
Packit Service 20376f
  tree->token.opr.idx = cur_nsub;
Packit Service 20376f
  return tree;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* This function parse repetition operators like "*", "+", "{1,3}" etc.  */
Packit Service 20376f
Packit Service 20376f
static bin_tree_t *
Packit Service 20376f
parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa,
Packit Service 20376f
	      re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err)
Packit Service 20376f
{
Packit Service 20376f
  bin_tree_t *tree = NULL, *old_tree = NULL;
Packit Service 20376f
  int i, start, end, start_idx = re_string_cur_idx (regexp);
Packit Service 20376f
#ifndef RE_TOKEN_INIT_BUG
Packit Service 20376f
  re_token_t start_token = *token;
Packit Service 20376f
#else
Packit Service 20376f
  re_token_t start_token;
Packit Service 20376f
Packit Service 20376f
  memcpy ((void *) &start_token, (void *) token, sizeof start_token);
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
  if (token->type == OP_OPEN_DUP_NUM)
Packit Service 20376f
    {
Packit Service 20376f
      end = 0;
Packit Service 20376f
      start = fetch_number (regexp, token, syntax);
Packit Service 20376f
      if (start == -1)
Packit Service 20376f
	{
Packit Service 20376f
	  if (token->type == CHARACTER && token->opr.c == ',')
Packit Service 20376f
	    start = 0; /* We treat "{,m}" as "{0,m}".  */
Packit Service 20376f
	  else
Packit Service 20376f
	    {
Packit Service 20376f
	      *err = REG_BADBR; /* <re>{} is invalid.  */
Packit Service 20376f
	      return NULL;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
      if (BE (start != -2, 1))
Packit Service 20376f
	{
Packit Service 20376f
	  /* We treat "{n}" as "{n,n}".  */
Packit Service 20376f
	  end = ((token->type == OP_CLOSE_DUP_NUM) ? start
Packit Service 20376f
		 : ((token->type == CHARACTER && token->opr.c == ',')
Packit Service 20376f
		    ? fetch_number (regexp, token, syntax) : -2));
Packit Service 20376f
	}
Packit Service 20376f
      if (BE (start == -2 || end == -2, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  /* Invalid sequence.  */
Packit Service 20376f
	  if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      if (token->type == END_OF_RE)
Packit Service 20376f
		*err = REG_EBRACE;
Packit Service 20376f
	      else
Packit Service 20376f
		*err = REG_BADBR;
Packit Service 20376f
Packit Service 20376f
	      return NULL;
Packit Service 20376f
	    }
Packit Service 20376f
Packit Service 20376f
	  /* If the syntax bit is set, rollback.  */
Packit Service 20376f
	  re_string_set_index (regexp, start_idx);
Packit Service 20376f
	  *token = start_token;
Packit Service 20376f
	  token->type = CHARACTER;
Packit Service 20376f
	  /* mb_partial and word_char bits should be already initialized by
Packit Service 20376f
	     peek_token.  */
Packit Service 20376f
	  return elem;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      if (BE ((end != -1 && start > end) || token->type != OP_CLOSE_DUP_NUM, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  /* First number greater than second.  */
Packit Service 20376f
	  *err = REG_BADBR;
Packit Service 20376f
	  return NULL;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
    {
Packit Service 20376f
      start = (token->type == OP_DUP_PLUS) ? 1 : 0;
Packit Service 20376f
      end = (token->type == OP_DUP_QUESTION) ? 1 : -1;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  fetch_token (token, regexp, syntax);
Packit Service 20376f
Packit Service 20376f
  if (BE (elem == NULL, 0))
Packit Service 20376f
    return NULL;
Packit Service 20376f
  if (BE (start == 0 && end == 0, 0))
Packit Service 20376f
    {
Packit Service 20376f
      postorder (elem, free_tree, NULL);
Packit Service 20376f
      return NULL;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  /* Extract "<re>{n,m}" to "<re><re>...<re><re>{0,<m-n>}".  */
Packit Service 20376f
  if (BE (start > 0, 0))
Packit Service 20376f
    {
Packit Service 20376f
      tree = elem;
Packit Service 20376f
      for (i = 2; i <= start; ++i)
Packit Service 20376f
	{
Packit Service 20376f
	  elem = duplicate_tree (elem, dfa);
Packit Service 20376f
	  tree = create_tree (dfa, tree, elem, CONCAT);
Packit Service 20376f
	  if (BE (elem == NULL || tree == NULL, 0))
Packit Service 20376f
	    goto parse_dup_op_espace;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      if (start == end)
Packit Service 20376f
	return tree;
Packit Service 20376f
Packit Service 20376f
      /* Duplicate ELEM before it is marked optional.  */
Packit Service 20376f
      elem = duplicate_tree (elem, dfa);
Packit Service 20376f
      old_tree = tree;
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
    old_tree = NULL;
Packit Service 20376f
Packit Service 20376f
  if (elem->token.type == SUBEXP)
Packit Service 20376f
    postorder (elem, mark_opt_subexp, (void *) (long) elem->token.opr.idx);
Packit Service 20376f
Packit Service 20376f
  tree = create_tree (dfa, elem, NULL, (end == -1 ? OP_DUP_ASTERISK : OP_ALT));
Packit Service 20376f
  if (BE (tree == NULL, 0))
Packit Service 20376f
    goto parse_dup_op_espace;
Packit Service 20376f
Packit Service 20376f
  /* This loop is actually executed only when end != -1,
Packit Service 20376f
     to rewrite <re>{0,n} as (<re>(<re>...<re>?)?)?...  We have
Packit Service 20376f
     already created the start+1-th copy.  */
Packit Service 20376f
  for (i = start + 2; i <= end; ++i)
Packit Service 20376f
    {
Packit Service 20376f
      elem = duplicate_tree (elem, dfa);
Packit Service 20376f
      tree = create_tree (dfa, tree, elem, CONCAT);
Packit Service 20376f
      if (BE (elem == NULL || tree == NULL, 0))
Packit Service 20376f
	goto parse_dup_op_espace;
Packit Service 20376f
Packit Service 20376f
      tree = create_tree (dfa, tree, NULL, OP_ALT);
Packit Service 20376f
      if (BE (tree == NULL, 0))
Packit Service 20376f
	goto parse_dup_op_espace;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  if (old_tree)
Packit Service 20376f
    tree = create_tree (dfa, old_tree, tree, CONCAT);
Packit Service 20376f
Packit Service 20376f
  return tree;
Packit Service 20376f
Packit Service 20376f
 parse_dup_op_espace:
Packit Service 20376f
  *err = REG_ESPACE;
Packit Service 20376f
  return NULL;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Size of the names for collating symbol/equivalence_class/character_class.
Packit Service 20376f
   I'm not sure, but maybe enough.  */
Packit Service 20376f
#define BRACKET_NAME_BUF_SIZE 32
Packit Service 20376f
Packit Service 20376f
#ifndef _LIBC
Packit Service 20376f
  /* Local function for parse_bracket_exp only used in case of NOT _LIBC.
Packit Service 20376f
     Build the range expression which starts from START_ELEM, and ends
Packit Service 20376f
     at END_ELEM.  The result are written to MBCSET and SBCSET.
Packit Service 20376f
     RANGE_ALLOC is the allocated size of mbcset->range_starts, and
Packit Service 20376f
     mbcset->range_ends, is a pointer argument sinse we may
Packit Service 20376f
     update it.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
# ifdef RE_ENABLE_I18N
Packit Service 20376f
build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc,
Packit Service 20376f
		 bracket_elem_t *start_elem, bracket_elem_t *end_elem)
Packit Service 20376f
# else /* not RE_ENABLE_I18N */
Packit Service 20376f
build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem,
Packit Service 20376f
		 bracket_elem_t *end_elem)
Packit Service 20376f
# endif /* not RE_ENABLE_I18N */
Packit Service 20376f
{
Packit Service 20376f
  unsigned int start_ch, end_ch;
Packit Service 20376f
  /* Equivalence Classes and Character Classes can't be a range start/end.  */
Packit Service 20376f
  if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS
Packit Service 20376f
	  || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS,
Packit Service 20376f
	  0))
Packit Service 20376f
    return REG_ERANGE;
Packit Service 20376f
Packit Service 20376f
  /* We can handle no multi character collating elements without libc
Packit Service 20376f
     support.  */
Packit Service 20376f
  if (BE ((start_elem->type == COLL_SYM
Packit Service 20376f
	   && strlen ((char *) start_elem->opr.name) > 1)
Packit Service 20376f
	  || (end_elem->type == COLL_SYM
Packit Service 20376f
	      && strlen ((char *) end_elem->opr.name) > 1), 0))
Packit Service 20376f
    return REG_ECOLLATE;
Packit Service 20376f
Packit Service 20376f
# ifdef RE_ENABLE_I18N
Packit Service 20376f
  {
Packit Service 20376f
    wchar_t wc;
Packit Service 20376f
    wint_t start_wc;
Packit Service 20376f
    wint_t end_wc;
Packit Service 20376f
    wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'};
Packit Service 20376f
Packit Service 20376f
    start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch
Packit Service 20376f
		: ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
Packit Service 20376f
		   : 0));
Packit Service 20376f
    end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch
Packit Service 20376f
	      : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
Packit Service 20376f
		 : 0));
Packit Service 20376f
#ifdef GAWK
Packit Service 20376f
    /*
Packit Service 20376f
     * Fedora Core 2, maybe others, have broken `btowc' that returns -1
Packit Service 20376f
     * for any value > 127. Sigh. Note that `start_ch' and `end_ch' are
Packit Service 20376f
     * unsigned, so we don't have sign extension problems.
Packit Service 20376f
     */
Packit Service 20376f
    start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM)
Packit Service 20376f
		? start_ch : start_elem->opr.wch);
Packit Service 20376f
    end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM)
Packit Service 20376f
	      ? end_ch : end_elem->opr.wch);
Packit Service 20376f
#else
Packit Service 20376f
    start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM)
Packit Service 20376f
		? __btowc (start_ch) : start_elem->opr.wch);
Packit Service 20376f
    end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM)
Packit Service 20376f
	      ? __btowc (end_ch) : end_elem->opr.wch);
Packit Service 20376f
#endif
Packit Service 20376f
    if (start_wc == WEOF || end_wc == WEOF)
Packit Service 20376f
      return REG_ECOLLATE;
Packit Service 20376f
    cmp_buf[0] = start_wc;
Packit Service 20376f
    cmp_buf[4] = end_wc;
Packit Service 20376f
    if (wcscoll (cmp_buf, cmp_buf + 4) > 0)
Packit Service 20376f
      return REG_ERANGE;
Packit Service 20376f
Packit Service 20376f
    /* Got valid collation sequence values, add them as a new entry.
Packit Service 20376f
       However, for !_LIBC we have no collation elements: if the
Packit Service 20376f
       character set is single byte, the single byte character set
Packit Service 20376f
       that we build below suffices.  parse_bracket_exp passes
Packit Service 20376f
       no MBCSET if dfa->mb_cur_max == 1.  */
Packit Service 20376f
    if (mbcset)
Packit Service 20376f
      {
Packit Service 20376f
	/* Check the space of the arrays.  */
Packit Service 20376f
	if (BE (*range_alloc == mbcset->nranges, 0))
Packit Service 20376f
	  {
Packit Service 20376f
	    /* There is not enough space, need realloc.  */
Packit Service 20376f
	    wchar_t *new_array_start, *new_array_end;
Packit Service 20376f
	    int new_nranges;
Packit Service 20376f
Packit Service 20376f
	    /* +1 in case of mbcset->nranges is 0.  */
Packit Service 20376f
	    new_nranges = 2 * mbcset->nranges + 1;
Packit Service 20376f
	    /* Use realloc since mbcset->range_starts and mbcset->range_ends
Packit Service 20376f
	       are NULL if *range_alloc == 0.  */
Packit Service 20376f
	    new_array_start = re_realloc (mbcset->range_starts, wchar_t,
Packit Service 20376f
					  new_nranges);
Packit Service 20376f
	    new_array_end = re_realloc (mbcset->range_ends, wchar_t,
Packit Service 20376f
					new_nranges);
Packit Service 20376f
Packit Service 20376f
	    if (BE (new_array_start == NULL || new_array_end == NULL, 0))
Packit Service 20376f
	      return REG_ESPACE;
Packit Service 20376f
Packit Service 20376f
	    mbcset->range_starts = new_array_start;
Packit Service 20376f
	    mbcset->range_ends = new_array_end;
Packit Service 20376f
	    *range_alloc = new_nranges;
Packit Service 20376f
	  }
Packit Service 20376f
Packit Service 20376f
	mbcset->range_starts[mbcset->nranges] = start_wc;
Packit Service 20376f
	mbcset->range_ends[mbcset->nranges++] = end_wc;
Packit Service 20376f
      }
Packit Service 20376f
Packit Service 20376f
    /* Build the table for single byte characters.  */
Packit Service 20376f
    for (wc = 0; wc < SBC_MAX; ++wc)
Packit Service 20376f
      {
Packit Service 20376f
	cmp_buf[2] = wc;
Packit Service 20376f
	if (wcscoll (cmp_buf, cmp_buf + 2) <= 0
Packit Service 20376f
	    && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0)
Packit Service 20376f
	  bitset_set (sbcset, wc);
Packit Service 20376f
      }
Packit Service 20376f
  }
Packit Service 20376f
# else /* not RE_ENABLE_I18N */
Packit Service 20376f
  {
Packit Service 20376f
    unsigned int ch;
Packit Service 20376f
    start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch
Packit Service 20376f
		: ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
Packit Service 20376f
		   : 0));
Packit Service 20376f
    end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch
Packit Service 20376f
	      : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
Packit Service 20376f
		 : 0));
Packit Service 20376f
    if (start_ch > end_ch)
Packit Service 20376f
      return REG_ERANGE;
Packit Service 20376f
    /* Build the table for single byte characters.  */
Packit Service 20376f
    for (ch = 0; ch < SBC_MAX; ++ch)
Packit Service 20376f
      if (start_ch <= ch  && ch <= end_ch)
Packit Service 20376f
	bitset_set (sbcset, ch);
Packit Service 20376f
  }
Packit Service 20376f
# endif /* not RE_ENABLE_I18N */
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
#endif /* not _LIBC */
Packit Service 20376f
Packit Service 20376f
#ifndef _LIBC
Packit Service 20376f
/* Helper function for parse_bracket_exp only used in case of NOT _LIBC..
Packit Service 20376f
   Build the collating element which is represented by NAME.
Packit Service 20376f
   The result are written to MBCSET and SBCSET.
Packit Service 20376f
   COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
Packit Service 20376f
   pointer argument since we may update it.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
internal_function
Packit Service 20376f
# ifdef RE_ENABLE_I18N
Packit Service 20376f
build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset,
Packit Service 20376f
			int *coll_sym_alloc, const unsigned char *name)
Packit Service 20376f
# else /* not RE_ENABLE_I18N */
Packit Service 20376f
build_collating_symbol (bitset_t sbcset, const unsigned char *name)
Packit Service 20376f
# endif /* not RE_ENABLE_I18N */
Packit Service 20376f
{
Packit Service 20376f
  size_t name_len = strlen ((const char *) name);
Packit Service 20376f
  if (BE (name_len != 1, 0))
Packit Service 20376f
    return REG_ECOLLATE;
Packit Service 20376f
  else
Packit Service 20376f
    {
Packit Service 20376f
      bitset_set (sbcset, name[0]);
Packit Service 20376f
      return REG_NOERROR;
Packit Service 20376f
    }
Packit Service 20376f
}
Packit Service 20376f
#endif /* not _LIBC */
Packit Service 20376f
Packit Service 20376f
/* This function parse bracket expression like "[abc]", "[a-c]",
Packit Service 20376f
   "[[.a-a.]]" etc.  */
Packit Service 20376f
Packit Service 20376f
static bin_tree_t *
Packit Service 20376f
parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
Packit Service 20376f
		   reg_syntax_t syntax, reg_errcode_t *err)
Packit Service 20376f
{
Packit Service 20376f
#ifdef _LIBC
Packit Service 20376f
  const unsigned char *collseqmb;
Packit Service 20376f
  const char *collseqwc;
Packit Service 20376f
  uint32_t nrules;
Packit Service 20376f
  int32_t table_size;
Packit Service 20376f
  const int32_t *symb_table;
Packit Service 20376f
  const unsigned char *extra;
Packit Service 20376f
Packit Service 20376f
  /* Local function for parse_bracket_exp used in _LIBC environement.
Packit Service 20376f
     Seek the collating symbol entry correspondings to NAME.
Packit Service 20376f
     Return the index of the symbol in the SYMB_TABLE.  */
Packit Service 20376f
Packit Service 20376f
  auto inline int32_t
Packit Service 20376f
  __attribute ((always_inline))
Packit Service 20376f
  seek_collating_symbol_entry (name, name_len)
Packit Service 20376f
	 const unsigned char *name;
Packit Service 20376f
	 size_t name_len;
Packit Service 20376f
    {
Packit Service 20376f
      int32_t hash = elem_hash ((const char *) name, name_len);
Packit Service 20376f
      int32_t elem = hash % table_size;
Packit Service 20376f
      if (symb_table[2 * elem] != 0)
Packit Service 20376f
	{
Packit Service 20376f
	  int32_t second = hash % (table_size - 2) + 1;
Packit Service 20376f
Packit Service 20376f
	  do
Packit Service 20376f
	    {
Packit Service 20376f
	      /* First compare the hashing value.  */
Packit Service 20376f
	      if (symb_table[2 * elem] == hash
Packit Service 20376f
		  /* Compare the length of the name.  */
Packit Service 20376f
		  && name_len == extra[symb_table[2 * elem + 1]]
Packit Service 20376f
		  /* Compare the name.  */
Packit Service 20376f
		  && memcmp (name, &extra[symb_table[2 * elem + 1] + 1],
Packit Service 20376f
			     name_len) == 0)
Packit Service 20376f
		{
Packit Service 20376f
		  /* Yep, this is the entry.  */
Packit Service 20376f
		  break;
Packit Service 20376f
		}
Packit Service 20376f
Packit Service 20376f
	      /* Next entry.  */
Packit Service 20376f
	      elem += second;
Packit Service 20376f
	    }
Packit Service 20376f
	  while (symb_table[2 * elem] != 0);
Packit Service 20376f
	}
Packit Service 20376f
      return elem;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  /* Local function for parse_bracket_exp used in _LIBC environment.
Packit Service 20376f
     Look up the collation sequence value of BR_ELEM.
Packit Service 20376f
     Return the value if succeeded, UINT_MAX otherwise.  */
Packit Service 20376f
Packit Service 20376f
  auto inline unsigned int
Packit Service 20376f
  __attribute ((always_inline))
Packit Service 20376f
  lookup_collation_sequence_value (br_elem)
Packit Service 20376f
	 bracket_elem_t *br_elem;
Packit Service 20376f
    {
Packit Service 20376f
      if (br_elem->type == SB_CHAR)
Packit Service 20376f
	{
Packit Service 20376f
	  /*
Packit Service 20376f
	  if (MB_CUR_MAX == 1)
Packit Service 20376f
	  */
Packit Service 20376f
	  if (nrules == 0)
Packit Service 20376f
	    return collseqmb[br_elem->opr.ch];
Packit Service 20376f
	  else
Packit Service 20376f
	    {
Packit Service 20376f
	      wint_t wc = __btowc (br_elem->opr.ch);
Packit Service 20376f
	      return __collseq_table_lookup (collseqwc, wc);
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
      else if (br_elem->type == MB_CHAR)
Packit Service 20376f
	{
Packit Service 20376f
	  if (nrules != 0)
Packit Service 20376f
	    return __collseq_table_lookup (collseqwc, br_elem->opr.wch);
Packit Service 20376f
	}
Packit Service 20376f
      else if (br_elem->type == COLL_SYM)
Packit Service 20376f
	{
Packit Service 20376f
	  size_t sym_name_len = strlen ((char *) br_elem->opr.name);
Packit Service 20376f
	  if (nrules != 0)
Packit Service 20376f
	    {
Packit Service 20376f
	      int32_t elem, idx;
Packit Service 20376f
	      elem = seek_collating_symbol_entry (br_elem->opr.name,
Packit Service 20376f
						  sym_name_len);
Packit Service 20376f
	      if (symb_table[2 * elem] != 0)
Packit Service 20376f
		{
Packit Service 20376f
		  /* We found the entry.  */
Packit Service 20376f
		  idx = symb_table[2 * elem + 1];
Packit Service 20376f
		  /* Skip the name of collating element name.  */
Packit Service 20376f
		  idx += 1 + extra[idx];
Packit Service 20376f
		  /* Skip the byte sequence of the collating element.  */
Packit Service 20376f
		  idx += 1 + extra[idx];
Packit Service 20376f
		  /* Adjust for the alignment.  */
Packit Service 20376f
		  idx = (idx + 3) & ~3;
Packit Service 20376f
		  /* Skip the multibyte collation sequence value.  */
Packit Service 20376f
		  idx += sizeof (unsigned int);
Packit Service 20376f
		  /* Skip the wide char sequence of the collating element.  */
Packit Service 20376f
		  idx += sizeof (unsigned int) *
Packit Service 20376f
		    (1 + *(unsigned int *) (extra + idx));
Packit Service 20376f
		  /* Return the collation sequence value.  */
Packit Service 20376f
		  return *(unsigned int *) (extra + idx);
Packit Service 20376f
		}
Packit Service 20376f
	      else if (symb_table[2 * elem] == 0 && sym_name_len == 1)
Packit Service 20376f
		{
Packit Service 20376f
		  /* No valid character.  Match it as a single byte
Packit Service 20376f
		     character.  */
Packit Service 20376f
		  return collseqmb[br_elem->opr.name[0]];
Packit Service 20376f
		}
Packit Service 20376f
	    }
Packit Service 20376f
	  else if (sym_name_len == 1)
Packit Service 20376f
	    return collseqmb[br_elem->opr.name[0]];
Packit Service 20376f
	}
Packit Service 20376f
      return UINT_MAX;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  /* Local function for parse_bracket_exp used in _LIBC environement.
Packit Service 20376f
     Build the range expression which starts from START_ELEM, and ends
Packit Service 20376f
     at END_ELEM.  The result are written to MBCSET and SBCSET.
Packit Service 20376f
     RANGE_ALLOC is the allocated size of mbcset->range_starts, and
Packit Service 20376f
     mbcset->range_ends, is a pointer argument sinse we may
Packit Service 20376f
     update it.  */
Packit Service 20376f
Packit Service 20376f
  auto inline reg_errcode_t
Packit Service 20376f
  __attribute ((always_inline))
Packit Service 20376f
  build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem)
Packit Service 20376f
	 re_charset_t *mbcset;
Packit Service 20376f
	 int *range_alloc;
Packit Service 20376f
	 bitset_t sbcset;
Packit Service 20376f
	 bracket_elem_t *start_elem, *end_elem;
Packit Service 20376f
    {
Packit Service 20376f
      unsigned int ch;
Packit Service 20376f
      uint32_t start_collseq;
Packit Service 20376f
      uint32_t end_collseq;
Packit Service 20376f
Packit Service 20376f
      /* Equivalence Classes and Character Classes can't be a range
Packit Service 20376f
	 start/end.  */
Packit Service 20376f
      if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS
Packit Service 20376f
	      || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS,
Packit Service 20376f
	      0))
Packit Service 20376f
	return REG_ERANGE;
Packit Service 20376f
Packit Service 20376f
      start_collseq = lookup_collation_sequence_value (start_elem);
Packit Service 20376f
      end_collseq = lookup_collation_sequence_value (end_elem);
Packit Service 20376f
      /* Check start/end collation sequence values.  */
Packit Service 20376f
      if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0))
Packit Service 20376f
	return REG_ECOLLATE;
Packit Service 20376f
      if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0))
Packit Service 20376f
	return REG_ERANGE;
Packit Service 20376f
Packit Service 20376f
      /* Got valid collation sequence values, add them as a new entry.
Packit Service 20376f
	 However, if we have no collation elements, and the character set
Packit Service 20376f
	 is single byte, the single byte character set that we
Packit Service 20376f
	 build below suffices. */
Packit Service 20376f
      if (nrules > 0 || dfa->mb_cur_max > 1)
Packit Service 20376f
	{
Packit Service 20376f
	  /* Check the space of the arrays.  */
Packit Service 20376f
	  if (BE (*range_alloc == mbcset->nranges, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      /* There is not enough space, need realloc.  */
Packit Service 20376f
	      uint32_t *new_array_start;
Packit Service 20376f
	      uint32_t *new_array_end;
Packit Service 20376f
	      int new_nranges;
Packit Service 20376f
Packit Service 20376f
	      /* +1 in case of mbcset->nranges is 0.  */
Packit Service 20376f
	      new_nranges = 2 * mbcset->nranges + 1;
Packit Service 20376f
	      new_array_start = re_realloc (mbcset->range_starts, uint32_t,
Packit Service 20376f
					    new_nranges);
Packit Service 20376f
	      new_array_end = re_realloc (mbcset->range_ends, uint32_t,
Packit Service 20376f
					  new_nranges);
Packit Service 20376f
Packit Service 20376f
	      if (BE (new_array_start == NULL || new_array_end == NULL, 0))
Packit Service 20376f
		return REG_ESPACE;
Packit Service 20376f
Packit Service 20376f
	      mbcset->range_starts = new_array_start;
Packit Service 20376f
	      mbcset->range_ends = new_array_end;
Packit Service 20376f
	      *range_alloc = new_nranges;
Packit Service 20376f
	    }
Packit Service 20376f
Packit Service 20376f
	  mbcset->range_starts[mbcset->nranges] = start_collseq;
Packit Service 20376f
	  mbcset->range_ends[mbcset->nranges++] = end_collseq;
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      /* Build the table for single byte characters.  */
Packit Service 20376f
      for (ch = 0; ch < SBC_MAX; ch++)
Packit Service 20376f
	{
Packit Service 20376f
	  uint32_t ch_collseq;
Packit Service 20376f
	  /*
Packit Service 20376f
	  if (MB_CUR_MAX == 1)
Packit Service 20376f
	  */
Packit Service 20376f
	  if (nrules == 0)
Packit Service 20376f
	    ch_collseq = collseqmb[ch];
Packit Service 20376f
	  else
Packit Service 20376f
	    ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch));
Packit Service 20376f
	  if (start_collseq <= ch_collseq && ch_collseq <= end_collseq)
Packit Service 20376f
	    bitset_set (sbcset, ch);
Packit Service 20376f
	}
Packit Service 20376f
      return REG_NOERROR;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  /* Local function for parse_bracket_exp used in _LIBC environement.
Packit Service 20376f
     Build the collating element which is represented by NAME.
Packit Service 20376f
     The result are written to MBCSET and SBCSET.
Packit Service 20376f
     COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
Packit Service 20376f
     pointer argument sinse we may update it.  */
Packit Service 20376f
Packit Service 20376f
  auto inline reg_errcode_t
Packit Service 20376f
  __attribute ((always_inline))
Packit Service 20376f
  build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name)
Packit Service 20376f
	 re_charset_t *mbcset;
Packit Service 20376f
	 int *coll_sym_alloc;
Packit Service 20376f
	 bitset_t sbcset;
Packit Service 20376f
	 const unsigned char *name;
Packit Service 20376f
    {
Packit Service 20376f
      int32_t elem, idx;
Packit Service 20376f
      size_t name_len = strlen ((const char *) name);
Packit Service 20376f
      if (nrules != 0)
Packit Service 20376f
	{
Packit Service 20376f
	  elem = seek_collating_symbol_entry (name, name_len);
Packit Service 20376f
	  if (symb_table[2 * elem] != 0)
Packit Service 20376f
	    {
Packit Service 20376f
	      /* We found the entry.  */
Packit Service 20376f
	      idx = symb_table[2 * elem + 1];
Packit Service 20376f
	      /* Skip the name of collating element name.  */
Packit Service 20376f
	      idx += 1 + extra[idx];
Packit Service 20376f
	    }
Packit Service 20376f
	  else if (symb_table[2 * elem] == 0 && name_len == 1)
Packit Service 20376f
	    {
Packit Service 20376f
	      /* No valid character, treat it as a normal
Packit Service 20376f
		 character.  */
Packit Service 20376f
	      bitset_set (sbcset, name[0]);
Packit Service 20376f
	      return REG_NOERROR;
Packit Service 20376f
	    }
Packit Service 20376f
	  else
Packit Service 20376f
	    return REG_ECOLLATE;
Packit Service 20376f
Packit Service 20376f
	  /* Got valid collation sequence, add it as a new entry.  */
Packit Service 20376f
	  /* Check the space of the arrays.  */
Packit Service 20376f
	  if (BE (*coll_sym_alloc == mbcset->ncoll_syms, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      /* Not enough, realloc it.  */
Packit Service 20376f
	      /* +1 in case of mbcset->ncoll_syms is 0.  */
Packit Service 20376f
	      int new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1;
Packit Service 20376f
	      /* Use realloc since mbcset->coll_syms is NULL
Packit Service 20376f
		 if *alloc == 0.  */
Packit Service 20376f
	      int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t,
Packit Service 20376f
						   new_coll_sym_alloc);
Packit Service 20376f
	      if (BE (new_coll_syms == NULL, 0))
Packit Service 20376f
		return REG_ESPACE;
Packit Service 20376f
	      mbcset->coll_syms = new_coll_syms;
Packit Service 20376f
	      *coll_sym_alloc = new_coll_sym_alloc;
Packit Service 20376f
	    }
Packit Service 20376f
	  mbcset->coll_syms[mbcset->ncoll_syms++] = idx;
Packit Service 20376f
	  return REG_NOERROR;
Packit Service 20376f
	}
Packit Service 20376f
      else
Packit Service 20376f
	{
Packit Service 20376f
	  if (BE (name_len != 1, 0))
Packit Service 20376f
	    return REG_ECOLLATE;
Packit Service 20376f
	  else
Packit Service 20376f
	    {
Packit Service 20376f
	      bitset_set (sbcset, name[0]);
Packit Service 20376f
	      return REG_NOERROR;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
  re_token_t br_token;
Packit Service 20376f
  re_bitset_ptr_t sbcset;
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  re_charset_t *mbcset;
Packit Service 20376f
  int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0;
Packit Service 20376f
  int equiv_class_alloc = 0, char_class_alloc = 0;
Packit Service 20376f
#endif /* not RE_ENABLE_I18N */
Packit Service 20376f
  int non_match = 0;
Packit Service 20376f
  bin_tree_t *work_tree;
Packit Service 20376f
  int token_len;
Packit Service 20376f
  int first_round = 1;
Packit Service 20376f
#ifdef _LIBC
Packit Service 20376f
  collseqmb = (const unsigned char *)
Packit Service 20376f
    _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
Packit Service 20376f
  nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
Packit Service 20376f
  if (nrules)
Packit Service 20376f
    {
Packit Service 20376f
      /*
Packit Service 20376f
      if (MB_CUR_MAX > 1)
Packit Service 20376f
      */
Packit Service 20376f
      collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);
Packit Service 20376f
      table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB);
Packit Service 20376f
      symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE,
Packit Service 20376f
						  _NL_COLLATE_SYMB_TABLEMB);
Packit Service 20376f
      extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
Packit Service 20376f
						   _NL_COLLATE_SYMB_EXTRAMB);
Packit Service 20376f
    }
Packit Service 20376f
#endif
Packit Service 20376f
  sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  if (BE (sbcset == NULL || mbcset == NULL, 0))
Packit Service 20376f
#else
Packit Service 20376f
  if (BE (sbcset == NULL, 0))
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
    {
Packit Service 20376f
      *err = REG_ESPACE;
Packit Service 20376f
      return NULL;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  token_len = peek_token_bracket (token, regexp, syntax);
Packit Service 20376f
  if (BE (token->type == END_OF_RE, 0))
Packit Service 20376f
    {
Packit Service 20376f
      *err = REG_BADPAT;
Packit Service 20376f
      goto parse_bracket_exp_free_return;
Packit Service 20376f
    }
Packit Service 20376f
  if (token->type == OP_NON_MATCH_LIST)
Packit Service 20376f
    {
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
      mbcset->non_match = 1;
Packit Service 20376f
#endif /* not RE_ENABLE_I18N */
Packit Service 20376f
      non_match = 1;
Packit Service 20376f
      if (syntax & RE_HAT_LISTS_NOT_NEWLINE)
Packit Service 20376f
	bitset_set (sbcset, '\n');
Packit Service 20376f
      re_string_skip_bytes (regexp, token_len); /* Skip a token.  */
Packit Service 20376f
      token_len = peek_token_bracket (token, regexp, syntax);
Packit Service 20376f
      if (BE (token->type == END_OF_RE, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  *err = REG_BADPAT;
Packit Service 20376f
	  goto parse_bracket_exp_free_return;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  /* We treat the first ']' as a normal character.  */
Packit Service 20376f
  if (token->type == OP_CLOSE_BRACKET)
Packit Service 20376f
    token->type = CHARACTER;
Packit Service 20376f
Packit Service 20376f
  while (1)
Packit Service 20376f
    {
Packit Service 20376f
      bracket_elem_t start_elem, end_elem;
Packit Service 20376f
      unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE];
Packit Service 20376f
      unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE];
Packit Service 20376f
      reg_errcode_t ret;
Packit Service 20376f
      int token_len2 = 0, is_range_exp = 0;
Packit Service 20376f
      re_token_t token2;
Packit Service 20376f
Packit Service 20376f
      start_elem.opr.name = start_name_buf;
Packit Service 20376f
      ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa,
Packit Service 20376f
				   syntax, first_round);
Packit Service 20376f
      if (BE (ret != REG_NOERROR, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  *err = ret;
Packit Service 20376f
	  goto parse_bracket_exp_free_return;
Packit Service 20376f
	}
Packit Service 20376f
      first_round = 0;
Packit Service 20376f
Packit Service 20376f
      /* Get information about the next token.  We need it in any case.  */
Packit Service 20376f
      token_len = peek_token_bracket (token, regexp, syntax);
Packit Service 20376f
Packit Service 20376f
      /* Do not check for ranges if we know they are not allowed.  */
Packit Service 20376f
      if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS)
Packit Service 20376f
	{
Packit Service 20376f
	  if (BE (token->type == END_OF_RE, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      *err = REG_EBRACK;
Packit Service 20376f
	      goto parse_bracket_exp_free_return;
Packit Service 20376f
	    }
Packit Service 20376f
	  if (token->type == OP_CHARSET_RANGE)
Packit Service 20376f
	    {
Packit Service 20376f
	      re_string_skip_bytes (regexp, token_len); /* Skip '-'.  */
Packit Service 20376f
	      token_len2 = peek_token_bracket (&token2, regexp, syntax);
Packit Service 20376f
	      if (BE (token2.type == END_OF_RE, 0))
Packit Service 20376f
		{
Packit Service 20376f
		  *err = REG_EBRACK;
Packit Service 20376f
		  goto parse_bracket_exp_free_return;
Packit Service 20376f
		}
Packit Service 20376f
	      if (token2.type == OP_CLOSE_BRACKET)
Packit Service 20376f
		{
Packit Service 20376f
		  /* We treat the last '-' as a normal character.  */
Packit Service 20376f
		  re_string_skip_bytes (regexp, -token_len);
Packit Service 20376f
		  token->type = CHARACTER;
Packit Service 20376f
		}
Packit Service 20376f
	      else
Packit Service 20376f
		is_range_exp = 1;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
Packit Service 20376f
      if (is_range_exp == 1)
Packit Service 20376f
	{
Packit Service 20376f
	  end_elem.opr.name = end_name_buf;
Packit Service 20376f
	  ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2,
Packit Service 20376f
				       dfa, syntax, 1);
Packit Service 20376f
	  if (BE (ret != REG_NOERROR, 0))
Packit Service 20376f
	    {
Packit Service 20376f
	      *err = ret;
Packit Service 20376f
	      goto parse_bracket_exp_free_return;
Packit Service 20376f
	    }
Packit Service 20376f
Packit Service 20376f
	  token_len = peek_token_bracket (token, regexp, syntax);
Packit Service 20376f
Packit Service 20376f
#ifdef _LIBC
Packit Service 20376f
	  *err = build_range_exp (sbcset, mbcset, &range_alloc,
Packit Service 20376f
				  &start_elem, &end_elem);
Packit Service 20376f
#else
Packit Service 20376f
# ifdef RE_ENABLE_I18N
Packit Service 20376f
	  *err = build_range_exp (sbcset,
Packit Service 20376f
				  dfa->mb_cur_max > 1 ? mbcset : NULL,
Packit Service 20376f
				  &range_alloc, &start_elem, &end_elem);
Packit Service 20376f
# else
Packit Service 20376f
	  *err = build_range_exp (sbcset, &start_elem, &end_elem);
Packit Service 20376f
# endif
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
	  if (BE (*err != REG_NOERROR, 0))
Packit Service 20376f
	    goto parse_bracket_exp_free_return;
Packit Service 20376f
	}
Packit Service 20376f
      else
Packit Service 20376f
	{
Packit Service 20376f
	  switch (start_elem.type)
Packit Service 20376f
	    {
Packit Service 20376f
	    case SB_CHAR:
Packit Service 20376f
	      bitset_set (sbcset, start_elem.opr.ch);
Packit Service 20376f
	      break;
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
	    case MB_CHAR:
Packit Service 20376f
	      /* Check whether the array has enough space.  */
Packit Service 20376f
	      if (BE (mbchar_alloc == mbcset->nmbchars, 0))
Packit Service 20376f
		{
Packit Service 20376f
		  wchar_t *new_mbchars;
Packit Service 20376f
		  /* Not enough, realloc it.  */
Packit Service 20376f
		  /* +1 in case of mbcset->nmbchars is 0.  */
Packit Service 20376f
		  mbchar_alloc = 2 * mbcset->nmbchars + 1;
Packit Service 20376f
		  /* Use realloc since array is NULL if *alloc == 0.  */
Packit Service 20376f
		  new_mbchars = re_realloc (mbcset->mbchars, wchar_t,
Packit Service 20376f
					    mbchar_alloc);
Packit Service 20376f
		  if (BE (new_mbchars == NULL, 0))
Packit Service 20376f
		    goto parse_bracket_exp_espace;
Packit Service 20376f
		  mbcset->mbchars = new_mbchars;
Packit Service 20376f
		}
Packit Service 20376f
	      mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch;
Packit Service 20376f
	      break;
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
	    case EQUIV_CLASS:
Packit Service 20376f
	      *err = build_equiv_class (sbcset,
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
					mbcset, &equiv_class_alloc,
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
					start_elem.opr.name);
Packit Service 20376f
	      if (BE (*err != REG_NOERROR, 0))
Packit Service 20376f
		goto parse_bracket_exp_free_return;
Packit Service 20376f
	      break;
Packit Service 20376f
	    case COLL_SYM:
Packit Service 20376f
	      *err = build_collating_symbol (sbcset,
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
					     mbcset, &coll_sym_alloc,
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
					     start_elem.opr.name);
Packit Service 20376f
	      if (BE (*err != REG_NOERROR, 0))
Packit Service 20376f
		goto parse_bracket_exp_free_return;
Packit Service 20376f
	      break;
Packit Service 20376f
	    case CHAR_CLASS:
Packit Service 20376f
	      *err = build_charclass (regexp->trans, sbcset,
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
				      mbcset, &char_class_alloc,
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
				      (const char *) start_elem.opr.name, syntax);
Packit Service 20376f
	      if (BE (*err != REG_NOERROR, 0))
Packit Service 20376f
	       goto parse_bracket_exp_free_return;
Packit Service 20376f
	      break;
Packit Service 20376f
	    default:
Packit Service 20376f
	      assert (0);
Packit Service 20376f
	      break;
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
      if (BE (token->type == END_OF_RE, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  *err = REG_EBRACK;
Packit Service 20376f
	  goto parse_bracket_exp_free_return;
Packit Service 20376f
	}
Packit Service 20376f
      if (token->type == OP_CLOSE_BRACKET)
Packit Service 20376f
	break;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  re_string_skip_bytes (regexp, token_len); /* Skip a token.  */
Packit Service 20376f
Packit Service 20376f
  /* If it is non-matching list.  */
Packit Service 20376f
  if (non_match)
Packit Service 20376f
    bitset_not (sbcset);
Packit Service 20376f
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  /* Ensure only single byte characters are set.  */
Packit Service 20376f
  if (dfa->mb_cur_max > 1)
Packit Service 20376f
    bitset_mask (sbcset, dfa->sb_char);
Packit Service 20376f
Packit Service 20376f
  if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes
Packit Service 20376f
      || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes
Packit Service 20376f
						     || mbcset->non_match)))
Packit Service 20376f
    {
Packit Service 20376f
      bin_tree_t *mbc_tree;
Packit Service 20376f
      int sbc_idx;
Packit Service 20376f
      /* Build a tree for complex bracket.  */
Packit Service 20376f
      dfa->has_mb_node = 1;
Packit Service 20376f
      br_token.type = COMPLEX_BRACKET;
Packit Service 20376f
      br_token.opr.mbcset = mbcset;
Packit Service 20376f
      mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);
Packit Service 20376f
      if (BE (mbc_tree == NULL, 0))
Packit Service 20376f
	goto parse_bracket_exp_espace;
Packit Service 20376f
      for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx)
Packit Service 20376f
	if (sbcset[sbc_idx])
Packit Service 20376f
	  break;
Packit Service 20376f
      /* If there are no bits set in sbcset, there is no point
Packit Service 20376f
	 of having both SIMPLE_BRACKET and COMPLEX_BRACKET.  */
Packit Service 20376f
      if (sbc_idx < BITSET_WORDS)
Packit Service 20376f
	{
Packit Service 20376f
	  /* Build a tree for simple bracket.  */
Packit Service 20376f
	  br_token.type = SIMPLE_BRACKET;
Packit Service 20376f
	  br_token.opr.sbcset = sbcset;
Packit Service 20376f
	  work_tree = create_token_tree (dfa, NULL, NULL, &br_token);
Packit Service 20376f
	  if (BE (work_tree == NULL, 0))
Packit Service 20376f
	    goto parse_bracket_exp_espace;
Packit Service 20376f
Packit Service 20376f
	  /* Then join them by ALT node.  */
Packit Service 20376f
	  work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT);
Packit Service 20376f
	  if (BE (work_tree == NULL, 0))
Packit Service 20376f
	    goto parse_bracket_exp_espace;
Packit Service 20376f
	}
Packit Service 20376f
      else
Packit Service 20376f
	{
Packit Service 20376f
	  re_free (sbcset);
Packit Service 20376f
	  work_tree = mbc_tree;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
#endif /* not RE_ENABLE_I18N */
Packit Service 20376f
    {
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
      free_charset (mbcset);
Packit Service 20376f
#endif
Packit Service 20376f
      /* Build a tree for simple bracket.  */
Packit Service 20376f
      br_token.type = SIMPLE_BRACKET;
Packit Service 20376f
      br_token.opr.sbcset = sbcset;
Packit Service 20376f
      work_tree = create_token_tree (dfa, NULL, NULL, &br_token);
Packit Service 20376f
      if (BE (work_tree == NULL, 0))
Packit Service 20376f
	goto parse_bracket_exp_espace;
Packit Service 20376f
    }
Packit Service 20376f
  return work_tree;
Packit Service 20376f
Packit Service 20376f
 parse_bracket_exp_espace:
Packit Service 20376f
  *err = REG_ESPACE;
Packit Service 20376f
 parse_bracket_exp_free_return:
Packit Service 20376f
  re_free (sbcset);
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  free_charset (mbcset);
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
  return NULL;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Parse an element in the bracket expression.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp,
Packit Service 20376f
		       re_token_t *token, int token_len, UNUSED re_dfa_t *dfa,
Packit Service 20376f
		       reg_syntax_t syntax, int accept_hyphen)
Packit Service 20376f
{
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  int cur_char_size;
Packit Service 20376f
  cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp));
Packit Service 20376f
  if (cur_char_size > 1)
Packit Service 20376f
    {
Packit Service 20376f
      elem->type = MB_CHAR;
Packit Service 20376f
      elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp));
Packit Service 20376f
      re_string_skip_bytes (regexp, cur_char_size);
Packit Service 20376f
      return REG_NOERROR;
Packit Service 20376f
    }
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
  re_string_skip_bytes (regexp, token_len); /* Skip a token.  */
Packit Service 20376f
  if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS
Packit Service 20376f
      || token->type == OP_OPEN_EQUIV_CLASS)
Packit Service 20376f
    return parse_bracket_symbol (elem, regexp, token);
Packit Service 20376f
  if (BE (token->type == OP_CHARSET_RANGE, 0) && !accept_hyphen)
Packit Service 20376f
    {
Packit Service 20376f
      /* A '-' must only appear as anything but a range indicator before
Packit Service 20376f
	 the closing bracket.  Everything else is an error.  */
Packit Service 20376f
      re_token_t token2;
Packit Service 20376f
      (void) peek_token_bracket (&token2, regexp, syntax);
Packit Service 20376f
      if (token2.type != OP_CLOSE_BRACKET)
Packit Service 20376f
	/* The actual error value is not standardized since this whole
Packit Service 20376f
	   case is undefined.  But ERANGE makes good sense.  */
Packit Service 20376f
	return REG_ERANGE;
Packit Service 20376f
    }
Packit Service 20376f
  elem->type = SB_CHAR;
Packit Service 20376f
  elem->opr.ch = token->opr.c;
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Parse a bracket symbol in the bracket expression.  Bracket symbols are
Packit Service 20376f
   such as [:<character_class>:], [.<collating_element>.], and
Packit Service 20376f
   [=<equivalent_class>=].  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp,
Packit Service 20376f
		      re_token_t *token)
Packit Service 20376f
{
Packit Service 20376f
  unsigned char ch, delim = token->opr.c;
Packit Service 20376f
  int i = 0;
Packit Service 20376f
  if (re_string_eoi(regexp))
Packit Service 20376f
    return REG_EBRACK;
Packit Service 20376f
  for (;; ++i)
Packit Service 20376f
    {
Packit Service 20376f
      if (i >= BRACKET_NAME_BUF_SIZE)
Packit Service 20376f
	return REG_EBRACK;
Packit Service 20376f
      if (token->type == OP_OPEN_CHAR_CLASS)
Packit Service 20376f
	ch = re_string_fetch_byte_case (regexp);
Packit Service 20376f
      else
Packit Service 20376f
	ch = re_string_fetch_byte (regexp);
Packit Service 20376f
      if (re_string_eoi(regexp))
Packit Service 20376f
	return REG_EBRACK;
Packit Service 20376f
      if (ch == delim && re_string_peek_byte (regexp, 0) == ']')
Packit Service 20376f
	break;
Packit Service 20376f
      elem->opr.name[i] = ch;
Packit Service 20376f
    }
Packit Service 20376f
  re_string_skip_bytes (regexp, 1);
Packit Service 20376f
  elem->opr.name[i] = '\0';
Packit Service 20376f
  switch (token->type)
Packit Service 20376f
    {
Packit Service 20376f
    case OP_OPEN_COLL_ELEM:
Packit Service 20376f
      elem->type = COLL_SYM;
Packit Service 20376f
      break;
Packit Service 20376f
    case OP_OPEN_EQUIV_CLASS:
Packit Service 20376f
      elem->type = EQUIV_CLASS;
Packit Service 20376f
      break;
Packit Service 20376f
    case OP_OPEN_CHAR_CLASS:
Packit Service 20376f
      elem->type = CHAR_CLASS;
Packit Service 20376f
      break;
Packit Service 20376f
    default:
Packit Service 20376f
      break;
Packit Service 20376f
    }
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
  /* Helper function for parse_bracket_exp.
Packit Service 20376f
     Build the equivalence class which is represented by NAME.
Packit Service 20376f
     The result are written to MBCSET and SBCSET.
Packit Service 20376f
     EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes,
Packit Service 20376f
     is a pointer argument sinse we may update it.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
build_equiv_class (bitset_t sbcset, re_charset_t *mbcset,
Packit Service 20376f
		   int *equiv_class_alloc, const unsigned char *name)
Packit Service 20376f
#else /* not RE_ENABLE_I18N */
Packit Service 20376f
build_equiv_class (bitset_t sbcset, const unsigned char *name)
Packit Service 20376f
#endif /* not RE_ENABLE_I18N */
Packit Service 20376f
{
Packit Service 20376f
#ifdef _LIBC
Packit Service 20376f
  uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
Packit Service 20376f
  if (nrules != 0)
Packit Service 20376f
    {
Packit Service 20376f
      const int32_t *table, *indirect;
Packit Service 20376f
      const unsigned char *weights, *extra, *cp;
Packit Service 20376f
      unsigned char char_buf[2];
Packit Service 20376f
      int32_t idx1, idx2;
Packit Service 20376f
      unsigned int ch;
Packit Service 20376f
      size_t len;
Packit Service 20376f
      /* This #include defines a local function!  */
Packit Service 20376f
# include <locale/weight.h>
Packit Service 20376f
      /* Calculate the index for equivalence class.  */
Packit Service 20376f
      cp = name;
Packit Service 20376f
      table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
Packit Service 20376f
      weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
Packit Service 20376f
					       _NL_COLLATE_WEIGHTMB);
Packit Service 20376f
      extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
Packit Service 20376f
						   _NL_COLLATE_EXTRAMB);
Packit Service 20376f
      indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
Packit Service 20376f
						_NL_COLLATE_INDIRECTMB);
Packit Service 20376f
      idx1 = findidx (&cp;;
Packit Service 20376f
      if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0))
Packit Service 20376f
	/* This isn't a valid character.  */
Packit Service 20376f
	return REG_ECOLLATE;
Packit Service 20376f
Packit Service 20376f
      /* Build single byte matcing table for this equivalence class.  */
Packit Service 20376f
      char_buf[1] = (unsigned char) '\0';
Packit Service 20376f
      len = weights[idx1 & 0xffffff];
Packit Service 20376f
      for (ch = 0; ch < SBC_MAX; ++ch)
Packit Service 20376f
	{
Packit Service 20376f
	  char_buf[0] = ch;
Packit Service 20376f
	  cp = char_buf;
Packit Service 20376f
	  idx2 = findidx (&cp;;
Packit Service 20376f
/*
Packit Service 20376f
	  idx2 = table[ch];
Packit Service 20376f
*/
Packit Service 20376f
	  if (idx2 == 0)
Packit Service 20376f
	    /* This isn't a valid character.  */
Packit Service 20376f
	    continue;
Packit Service 20376f
	  /* Compare only if the length matches and the collation rule
Packit Service 20376f
	     index is the same.  */
Packit Service 20376f
	  if (len == weights[idx2 & 0xffffff] && (idx1 >> 24) == (idx2 >> 24))
Packit Service 20376f
	    {
Packit Service 20376f
	      int cnt = 0;
Packit Service 20376f
Packit Service 20376f
	      while (cnt <= len &&
Packit Service 20376f
		     weights[(idx1 & 0xffffff) + 1 + cnt]
Packit Service 20376f
		     == weights[(idx2 & 0xffffff) + 1 + cnt])
Packit Service 20376f
		++cnt;
Packit Service 20376f
Packit Service 20376f
	      if (cnt > len)
Packit Service 20376f
		bitset_set (sbcset, ch);
Packit Service 20376f
	    }
Packit Service 20376f
	}
Packit Service 20376f
      /* Check whether the array has enough space.  */
Packit Service 20376f
      if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0))
Packit Service 20376f
	{
Packit Service 20376f
	  /* Not enough, realloc it.  */
Packit Service 20376f
	  /* +1 in case of mbcset->nequiv_classes is 0.  */
Packit Service 20376f
	  int new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1;
Packit Service 20376f
	  /* Use realloc since the array is NULL if *alloc == 0.  */
Packit Service 20376f
	  int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes,
Packit Service 20376f
						   int32_t,
Packit Service 20376f
						   new_equiv_class_alloc);
Packit Service 20376f
	  if (BE (new_equiv_classes == NULL, 0))
Packit Service 20376f
	    return REG_ESPACE;
Packit Service 20376f
	  mbcset->equiv_classes = new_equiv_classes;
Packit Service 20376f
	  *equiv_class_alloc = new_equiv_class_alloc;
Packit Service 20376f
	}
Packit Service 20376f
      mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1;
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
#endif /* _LIBC */
Packit Service 20376f
    {
Packit Service 20376f
      if (BE (strlen ((const char *) name) != 1, 0))
Packit Service 20376f
	return REG_ECOLLATE;
Packit Service 20376f
      bitset_set (sbcset, *name);
Packit Service 20376f
    }
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
  /* Helper function for parse_bracket_exp.
Packit Service 20376f
     Build the character class which is represented by NAME.
Packit Service 20376f
     The result are written to MBCSET and SBCSET.
Packit Service 20376f
     CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes,
Packit Service 20376f
     is a pointer argument sinse we may update it.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
Packit Service 20376f
		 re_charset_t *mbcset, int *char_class_alloc,
Packit Service 20376f
		 const char *class_name, reg_syntax_t syntax)
Packit Service 20376f
#else /* not RE_ENABLE_I18N */
Packit Service 20376f
build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
Packit Service 20376f
		 const char *class_name, reg_syntax_t syntax)
Packit Service 20376f
#endif /* not RE_ENABLE_I18N */
Packit Service 20376f
{
Packit Service 20376f
  int i;
Packit Service 20376f
Packit Service 20376f
  /* In case of REG_ICASE "upper" and "lower" match the both of
Packit Service 20376f
     upper and lower cases.  */
Packit Service 20376f
  if ((syntax & RE_ICASE)
Packit Service 20376f
      && (strcmp (class_name, "upper") == 0 || strcmp (class_name, "lower") == 0))
Packit Service 20376f
    class_name = "alpha";
Packit Service 20376f
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  /* Check the space of the arrays.  */
Packit Service 20376f
  if (BE (*char_class_alloc == mbcset->nchar_classes, 0))
Packit Service 20376f
    {
Packit Service 20376f
      /* Not enough, realloc it.  */
Packit Service 20376f
      /* +1 in case of mbcset->nchar_classes is 0.  */
Packit Service 20376f
      int new_char_class_alloc = 2 * mbcset->nchar_classes + 1;
Packit Service 20376f
      /* Use realloc since array is NULL if *alloc == 0.  */
Packit Service 20376f
      wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t,
Packit Service 20376f
					       new_char_class_alloc);
Packit Service 20376f
      if (BE (new_char_classes == NULL, 0))
Packit Service 20376f
	return REG_ESPACE;
Packit Service 20376f
      mbcset->char_classes = new_char_classes;
Packit Service 20376f
      *char_class_alloc = new_char_class_alloc;
Packit Service 20376f
    }
Packit Service 20376f
  mbcset->char_classes[mbcset->nchar_classes++] = __wctype (class_name);
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
Packit Service 20376f
#define BUILD_CHARCLASS_LOOP(ctype_func)	\
Packit Service 20376f
  do {						\
Packit Service 20376f
    if (BE (trans != NULL, 0))			\
Packit Service 20376f
      {						\
Packit Service 20376f
	for (i = 0; i < SBC_MAX; ++i)		\
Packit Service 20376f
  	  if (ctype_func (i))			\
Packit Service 20376f
	    bitset_set (sbcset, trans[i]);	\
Packit Service 20376f
      }						\
Packit Service 20376f
    else					\
Packit Service 20376f
      {						\
Packit Service 20376f
	for (i = 0; i < SBC_MAX; ++i)		\
Packit Service 20376f
  	  if (ctype_func (i))			\
Packit Service 20376f
	    bitset_set (sbcset, i);		\
Packit Service 20376f
      }						\
Packit Service 20376f
  } while (0)
Packit Service 20376f
Packit Service 20376f
  if (strcmp (class_name, "alnum") == 0)
Packit Service 20376f
    BUILD_CHARCLASS_LOOP (isalnum);
Packit Service 20376f
  else if (strcmp (class_name, "cntrl") == 0)
Packit Service 20376f
    BUILD_CHARCLASS_LOOP (iscntrl);
Packit Service 20376f
  else if (strcmp (class_name, "lower") == 0)
Packit Service 20376f
    BUILD_CHARCLASS_LOOP (islower);
Packit Service 20376f
  else if (strcmp (class_name, "space") == 0)
Packit Service 20376f
    BUILD_CHARCLASS_LOOP (isspace);
Packit Service 20376f
  else if (strcmp (class_name, "alpha") == 0)
Packit Service 20376f
    BUILD_CHARCLASS_LOOP (isalpha);
Packit Service 20376f
  else if (strcmp (class_name, "digit") == 0)
Packit Service 20376f
    BUILD_CHARCLASS_LOOP (isdigit);
Packit Service 20376f
  else if (strcmp (class_name, "print") == 0)
Packit Service 20376f
    BUILD_CHARCLASS_LOOP (isprint);
Packit Service 20376f
  else if (strcmp (class_name, "upper") == 0)
Packit Service 20376f
    BUILD_CHARCLASS_LOOP (isupper);
Packit Service 20376f
  else if (strcmp (class_name, "blank") == 0)
Packit Service 20376f
#ifndef GAWK
Packit Service 20376f
    BUILD_CHARCLASS_LOOP (isblank);
Packit Service 20376f
#else
Packit Service 20376f
    /* see comments above */
Packit Service 20376f
    BUILD_CHARCLASS_LOOP (is_blank);
Packit Service 20376f
#endif
Packit Service 20376f
  else if (strcmp (class_name, "graph") == 0)
Packit Service 20376f
    BUILD_CHARCLASS_LOOP (isgraph);
Packit Service 20376f
  else if (strcmp (class_name, "punct") == 0)
Packit Service 20376f
    BUILD_CHARCLASS_LOOP (ispunct);
Packit Service 20376f
  else if (strcmp (class_name, "xdigit") == 0)
Packit Service 20376f
    BUILD_CHARCLASS_LOOP (isxdigit);
Packit Service 20376f
  else
Packit Service 20376f
    return REG_ECTYPE;
Packit Service 20376f
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static bin_tree_t *
Packit Service 20376f
build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
Packit Service 20376f
		    const char *class_name,
Packit Service 20376f
		    const char *extra, int non_match,
Packit Service 20376f
		    reg_errcode_t *err)
Packit Service 20376f
{
Packit Service 20376f
  re_bitset_ptr_t sbcset;
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  re_charset_t *mbcset;
Packit Service 20376f
  int alloc = 0;
Packit Service 20376f
#endif /* not RE_ENABLE_I18N */
Packit Service 20376f
  reg_errcode_t ret;
Packit Service 20376f
  re_token_t br_token;
Packit Service 20376f
  bin_tree_t *tree;
Packit Service 20376f
Packit Service 20376f
  sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  if (BE (sbcset == NULL || mbcset == NULL, 0))
Packit Service 20376f
#else /* not RE_ENABLE_I18N */
Packit Service 20376f
  if (BE (sbcset == NULL, 0))
Packit Service 20376f
#endif /* not RE_ENABLE_I18N */
Packit Service 20376f
    {
Packit Service 20376f
      *err = REG_ESPACE;
Packit Service 20376f
      return NULL;
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  if (non_match)
Packit Service 20376f
    {
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
      mbcset->non_match = 1;
Packit Service 20376f
#endif /* not RE_ENABLE_I18N */
Packit Service 20376f
    }
Packit Service 20376f
Packit Service 20376f
  /* We don't care the syntax in this case.  */
Packit Service 20376f
  ret = build_charclass (trans, sbcset,
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
			 mbcset, &alloc,
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
			 class_name, 0);
Packit Service 20376f
Packit Service 20376f
  if (BE (ret != REG_NOERROR, 0))
Packit Service 20376f
    {
Packit Service 20376f
      re_free (sbcset);
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
      free_charset (mbcset);
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
      *err = ret;
Packit Service 20376f
      return NULL;
Packit Service 20376f
    }
Packit Service 20376f
  /* \w match '_' also.  */
Packit Service 20376f
  for (; *extra; extra++)
Packit Service 20376f
    bitset_set (sbcset, *extra);
Packit Service 20376f
Packit Service 20376f
  /* If it is non-matching list.  */
Packit Service 20376f
  if (non_match)
Packit Service 20376f
    bitset_not (sbcset);
Packit Service 20376f
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  /* Ensure only single byte characters are set.  */
Packit Service 20376f
  if (dfa->mb_cur_max > 1)
Packit Service 20376f
    bitset_mask (sbcset, dfa->sb_char);
Packit Service 20376f
#endif
Packit Service 20376f
Packit Service 20376f
  /* Build a tree for simple bracket.  */
Packit Service 20376f
  br_token.type = SIMPLE_BRACKET;
Packit Service 20376f
  br_token.opr.sbcset = sbcset;
Packit Service 20376f
  tree = create_token_tree (dfa, NULL, NULL, &br_token);
Packit Service 20376f
  if (BE (tree == NULL, 0))
Packit Service 20376f
    goto build_word_op_espace;
Packit Service 20376f
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  if (dfa->mb_cur_max > 1)
Packit Service 20376f
    {
Packit Service 20376f
      bin_tree_t *mbc_tree;
Packit Service 20376f
      /* Build a tree for complex bracket.  */
Packit Service 20376f
      br_token.type = COMPLEX_BRACKET;
Packit Service 20376f
      br_token.opr.mbcset = mbcset;
Packit Service 20376f
      dfa->has_mb_node = 1;
Packit Service 20376f
      mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);
Packit Service 20376f
      if (BE (mbc_tree == NULL, 0))
Packit Service 20376f
	goto build_word_op_espace;
Packit Service 20376f
      /* Then join them by ALT node.  */
Packit Service 20376f
      tree = create_tree (dfa, tree, mbc_tree, OP_ALT);
Packit Service 20376f
      if (BE (mbc_tree != NULL, 1))
Packit Service 20376f
	return tree;
Packit Service 20376f
    }
Packit Service 20376f
  else
Packit Service 20376f
    {
Packit Service 20376f
      free_charset (mbcset);
Packit Service 20376f
      return tree;
Packit Service 20376f
    }
Packit Service 20376f
#else /* not RE_ENABLE_I18N */
Packit Service 20376f
  return tree;
Packit Service 20376f
#endif /* not RE_ENABLE_I18N */
Packit Service 20376f
Packit Service 20376f
 build_word_op_espace:
Packit Service 20376f
  re_free (sbcset);
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  free_charset (mbcset);
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
  *err = REG_ESPACE;
Packit Service 20376f
  return NULL;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* This is intended for the expressions like "a{1,3}".
Packit Service 20376f
   Fetch a number from `input', and return the number.
Packit Service 20376f
   Return -1, if the number field is empty like "{,1}".
Packit Service 20376f
   Return -2, If an error is occured.  */
Packit Service 20376f
Packit Service 20376f
static int
Packit Service 20376f
fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax)
Packit Service 20376f
{
Packit Service 20376f
  int num = -1;
Packit Service 20376f
  unsigned char c;
Packit Service 20376f
  while (1)
Packit Service 20376f
    {
Packit Service 20376f
      fetch_token (token, input, syntax);
Packit Service 20376f
      c = token->opr.c;
Packit Service 20376f
      if (BE (token->type == END_OF_RE, 0))
Packit Service 20376f
	return -2;
Packit Service 20376f
      if (token->type == OP_CLOSE_DUP_NUM || c == ',')
Packit Service 20376f
	break;
Packit Service 20376f
      num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2)
Packit Service 20376f
	     ? -2 : ((num == -1) ? c - '0' : num * 10 + c - '0'));
Packit Service 20376f
      num = (num > RE_DUP_MAX) ? -2 : num;
Packit Service 20376f
    }
Packit Service 20376f
  return num;
Packit Service 20376f
}
Packit Service 20376f

Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
static void
Packit Service 20376f
free_charset (re_charset_t *cset)
Packit Service 20376f
{
Packit Service 20376f
  re_free (cset->mbchars);
Packit Service 20376f
# ifdef _LIBC
Packit Service 20376f
  re_free (cset->coll_syms);
Packit Service 20376f
  re_free (cset->equiv_classes);
Packit Service 20376f
  re_free (cset->range_starts);
Packit Service 20376f
  re_free (cset->range_ends);
Packit Service 20376f
# endif
Packit Service 20376f
  re_free (cset->char_classes);
Packit Service 20376f
  re_free (cset);
Packit Service 20376f
}
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f

Packit Service 20376f
/* Functions for binary tree operation.  */
Packit Service 20376f
Packit Service 20376f
/* Create a tree node.  */
Packit Service 20376f
Packit Service 20376f
static bin_tree_t *
Packit Service 20376f
create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
Packit Service 20376f
	     re_token_type_t type)
Packit Service 20376f
{
Packit Service 20376f
  re_token_t t;
Packit Service 20376f
  t.type = type;
Packit Service 20376f
  return create_token_tree (dfa, left, right, &t);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
static bin_tree_t *
Packit Service 20376f
create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
Packit Service 20376f
		   const re_token_t *token)
Packit Service 20376f
{
Packit Service 20376f
  bin_tree_t *tree;
Packit Service 20376f
  if (BE (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE, 0))
Packit Service 20376f
    {
Packit Service 20376f
      bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1);
Packit Service 20376f
Packit Service 20376f
      if (storage == NULL)
Packit Service 20376f
	return NULL;
Packit Service 20376f
      storage->next = dfa->str_tree_storage;
Packit Service 20376f
      dfa->str_tree_storage = storage;
Packit Service 20376f
      dfa->str_tree_storage_idx = 0;
Packit Service 20376f
    }
Packit Service 20376f
  tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++];
Packit Service 20376f
Packit Service 20376f
  tree->parent = NULL;
Packit Service 20376f
  tree->left = left;
Packit Service 20376f
  tree->right = right;
Packit Service 20376f
  tree->token = *token;
Packit Service 20376f
  tree->token.duplicated = 0;
Packit Service 20376f
  tree->token.opt_subexp = 0;
Packit Service 20376f
  tree->first = NULL;
Packit Service 20376f
  tree->next = NULL;
Packit Service 20376f
  tree->node_idx = -1;
Packit Service 20376f
Packit Service 20376f
  if (left != NULL)
Packit Service 20376f
    left->parent = tree;
Packit Service 20376f
  if (right != NULL)
Packit Service 20376f
    right->parent = tree;
Packit Service 20376f
  return tree;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Mark the tree SRC as an optional subexpression.
Packit Service 20376f
   To be called from preorder or postorder.  */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
mark_opt_subexp (void *extra, bin_tree_t *node)
Packit Service 20376f
{
Packit Service 20376f
  int idx = (int) (long) extra;
Packit Service 20376f
  if (node->token.type == SUBEXP && node->token.opr.idx == idx)
Packit Service 20376f
    node->token.opt_subexp = 1;
Packit Service 20376f
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Free the allocated memory inside NODE. */
Packit Service 20376f
Packit Service 20376f
static void
Packit Service 20376f
free_token (re_token_t *node)
Packit Service 20376f
{
Packit Service 20376f
#ifdef RE_ENABLE_I18N
Packit Service 20376f
  if (node->type == COMPLEX_BRACKET && node->duplicated == 0)
Packit Service 20376f
    free_charset (node->opr.mbcset);
Packit Service 20376f
  else
Packit Service 20376f
#endif /* RE_ENABLE_I18N */
Packit Service 20376f
    if (node->type == SIMPLE_BRACKET && node->duplicated == 0)
Packit Service 20376f
      re_free (node->opr.sbcset);
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
/* Worker function for tree walking.  Free the allocated memory inside NODE
Packit Service 20376f
   and its children. */
Packit Service 20376f
Packit Service 20376f
static reg_errcode_t
Packit Service 20376f
free_tree (UNUSED void *extra, bin_tree_t *node)
Packit Service 20376f
{
Packit Service 20376f
  free_token (&node->token);
Packit Service 20376f
  return REG_NOERROR;
Packit Service 20376f
}
Packit Service 20376f
Packit Service 20376f
Packit Service 20376f
/* Duplicate the node SRC, and return new node.  This is a preorder
Packit Service 20376f
   visit similar to the one implemented by the generic visitor, but
Packit Service 20376f
   we need more infrastructure to maintain two parallel trees --- so,
Packit Service 20376f
   it's easier to duplicate.  */
Packit Service 20376f
Packit Service 20376f
static bin_tree_t *
Packit Service 20376f
duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa)
Packit Service 20376f
{
Packit Service 20376f
  const bin_tree_t *node;
Packit Service 20376f
  bin_tree_t *dup_root;
Packit Service 20376f
  bin_tree_t **p_new = &dup_root, *dup_node = root->parent;
Packit Service 20376f
Packit Service 20376f
  for (node = root; ; )
Packit Service 20376f
    {
Packit Service 20376f
      /* Create a new tree and link it back to the current parent.  */
Packit Service 20376f
      *p_new = create_token_tree (dfa, NULL, NULL, &node->token);
Packit Service 20376f
      if (*p_new == NULL)
Packit Service 20376f
	return NULL;
Packit Service 20376f
      (*p_new)->parent = dup_node;
Packit Service 20376f
      (*p_new)->token.duplicated = 1;
Packit Service 20376f
      dup_node = *p_new;
Packit Service 20376f
Packit Service 20376f
      /* Go to the left node, or up and to the right.  */
Packit Service 20376f
      if (node->left)
Packit Service 20376f
	{
Packit Service 20376f
	  node = node->left;
Packit Service 20376f
	  p_new = &dup_node->left;
Packit Service 20376f
	}
Packit Service 20376f
      else
Packit Service 20376f
	{
Packit Service 20376f
	  const bin_tree_t *prev = NULL;
Packit Service 20376f
	  while (node->right == prev || node->right == NULL)
Packit Service 20376f
	    {
Packit Service 20376f
	      prev = node;
Packit Service 20376f
	      node = node->parent;
Packit Service 20376f
	      dup_node = dup_node->parent;
Packit Service 20376f
	      if (!node)
Packit Service 20376f
		return dup_root;
Packit Service 20376f
	    }
Packit Service 20376f
	  node = node->right;
Packit Service 20376f
	  p_new = &dup_node->right;
Packit Service 20376f
	}
Packit Service 20376f
    }
Packit Service 20376f
}