Blame support/regex_internal.c

Packit Service f629e6
/* Extended regular expression matching and search library.
Packit Service f629e6
   Copyright (C) 2002-2017 Free Software Foundation, Inc.
Packit Service f629e6
   This file is part of the GNU C Library.
Packit Service f629e6
   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
Packit Service f629e6
Packit Service f629e6
   The GNU C Library is free software; you can redistribute it and/or
Packit Service f629e6
   modify it under the terms of the GNU Lesser General Public
Packit Service f629e6
   License as published by the Free Software Foundation; either
Packit Service f629e6
   version 2.1 of the License, or (at your option) any later version.
Packit Service f629e6
Packit Service f629e6
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service f629e6
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service f629e6
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service f629e6
   Lesser General Public License for more details.
Packit Service f629e6
Packit Service f629e6
   You should have received a copy of the GNU Lesser General Public
Packit Service f629e6
   License along with the GNU C Library; if not, see
Packit Service f629e6
   <http://www.gnu.org/licenses/>.  */
Packit Service f629e6
Packit Service f629e6
static void re_string_construct_common (const char *str, int len,
Packit Service f629e6
					re_string_t *pstr,
Packit Service f629e6
					RE_TRANSLATE_TYPE trans, int icase,
Packit Service f629e6
					const re_dfa_t *dfa);
Packit Service f629e6
static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa,
Packit Service f629e6
					  const re_node_set *nodes,
Packit Service f629e6
					  unsigned int hash);
Packit Service f629e6
static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa,
Packit Service f629e6
					  const re_node_set *nodes,
Packit Service f629e6
					  unsigned int context,
Packit Service f629e6
					  unsigned int hash);
Packit Service f629e6
Packit Service f629e6
#ifdef GAWK
Packit Service f629e6
#undef MAX	/* safety */
Packit Service f629e6
static int
Packit Service f629e6
MAX(size_t a, size_t b)
Packit Service f629e6
{
Packit Service f629e6
	return (a > b ? a : b);
Packit Service f629e6
}
Packit Service f629e6
#endif
Packit Service f629e6

Packit Service f629e6
/* Functions for string operation.  */
Packit Service f629e6
Packit Service f629e6
/* This function allocate the buffers.  It is necessary to call
Packit Service f629e6
   re_string_reconstruct before using the object.  */
Packit Service f629e6
Packit Service f629e6
static reg_errcode_t
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len,
Packit Service f629e6
		    RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa)
Packit Service f629e6
{
Packit Service f629e6
  reg_errcode_t ret;
Packit Service f629e6
  int init_buf_len;
Packit Service f629e6
Packit Service f629e6
  /* Ensure at least one character fits into the buffers.  */
Packit Service f629e6
  if (init_len < dfa->mb_cur_max)
Packit Service f629e6
    init_len = dfa->mb_cur_max;
Packit Service f629e6
  init_buf_len = (len + 1 < init_len) ? len + 1: init_len;
Packit Service f629e6
  re_string_construct_common (str, len, pstr, trans, icase, dfa);
Packit Service f629e6
Packit Service f629e6
  ret = re_string_realloc_buffers (pstr, init_buf_len);
Packit Service f629e6
  if (BE (ret != REG_NOERROR, 0))
Packit Service f629e6
    return ret;
Packit Service f629e6
Packit Service f629e6
  pstr->word_char = dfa->word_char;
Packit Service f629e6
  pstr->word_ops_used = dfa->word_ops_used;
Packit Service f629e6
  pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
Packit Service f629e6
  pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len;
Packit Service f629e6
  pstr->valid_raw_len = pstr->valid_len;
Packit Service f629e6
  return REG_NOERROR;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* This function allocate the buffers, and initialize them.  */
Packit Service f629e6
Packit Service f629e6
static reg_errcode_t
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
re_string_construct (re_string_t *pstr, const char *str, int len,
Packit Service f629e6
		     RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa)
Packit Service f629e6
{
Packit Service f629e6
  reg_errcode_t ret;
Packit Service f629e6
  memset (pstr, '\0', sizeof (re_string_t));
Packit Service f629e6
  re_string_construct_common (str, len, pstr, trans, icase, dfa);
Packit Service f629e6
Packit Service f629e6
  if (len > 0)
Packit Service f629e6
    {
Packit Service f629e6
      ret = re_string_realloc_buffers (pstr, len + 1);
Packit Service f629e6
      if (BE (ret != REG_NOERROR, 0))
Packit Service f629e6
	return ret;
Packit Service f629e6
    }
Packit Service f629e6
  pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;
Packit Service f629e6
Packit Service f629e6
  if (icase)
Packit Service f629e6
    {
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
      if (dfa->mb_cur_max > 1)
Packit Service f629e6
	{
Packit Service f629e6
	  while (1)
Packit Service f629e6
	    {
Packit Service f629e6
	      ret = build_wcs_upper_buffer (pstr);
Packit Service f629e6
	      if (BE (ret != REG_NOERROR, 0))
Packit Service f629e6
		return ret;
Packit Service f629e6
	      if (pstr->valid_raw_len >= len)
Packit Service f629e6
		break;
Packit Service f629e6
	      if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max)
Packit Service f629e6
		break;
Packit Service f629e6
	      ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);
Packit Service f629e6
	      if (BE (ret != REG_NOERROR, 0))
Packit Service f629e6
		return ret;
Packit Service f629e6
	    }
Packit Service f629e6
	}
Packit Service f629e6
      else
Packit Service f629e6
#endif /* RE_ENABLE_I18N  */
Packit Service f629e6
	build_upper_buffer (pstr);
Packit Service f629e6
    }
Packit Service f629e6
  else
Packit Service f629e6
    {
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
      if (dfa->mb_cur_max > 1)
Packit Service f629e6
	build_wcs_buffer (pstr);
Packit Service f629e6
      else
Packit Service f629e6
#endif /* RE_ENABLE_I18N  */
Packit Service f629e6
	{
Packit Service f629e6
	  if (trans != NULL)
Packit Service f629e6
	    re_string_translate_buffer (pstr);
Packit Service f629e6
	  else
Packit Service f629e6
	    {
Packit Service f629e6
	      pstr->valid_len = pstr->bufs_len;
Packit Service f629e6
	      pstr->valid_raw_len = pstr->bufs_len;
Packit Service f629e6
	    }
Packit Service f629e6
	}
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  return REG_NOERROR;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Helper functions for re_string_allocate, and re_string_construct.  */
Packit Service f629e6
Packit Service f629e6
static reg_errcode_t
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
re_string_realloc_buffers (re_string_t *pstr, int new_buf_len)
Packit Service f629e6
{
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
  if (pstr->mb_cur_max > 1)
Packit Service f629e6
    {
Packit Service f629e6
      wint_t *new_wcs;
Packit Service f629e6
Packit Service f629e6
      /* Avoid overflow in realloc.  */
Packit Service f629e6
      const size_t max_object_size = MAX (sizeof (wint_t), sizeof (int));
Packit Service f629e6
      if (BE (SIZE_MAX / max_object_size < new_buf_len, 0))
Packit Service f629e6
	return REG_ESPACE;
Packit Service f629e6
Packit Service f629e6
      new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len);
Packit Service f629e6
      if (BE (new_wcs == NULL, 0))
Packit Service f629e6
	return REG_ESPACE;
Packit Service f629e6
      pstr->wcs = new_wcs;
Packit Service f629e6
      if (pstr->offsets != NULL)
Packit Service f629e6
	{
Packit Service f629e6
	  int *new_offsets = re_realloc (pstr->offsets, int, new_buf_len);
Packit Service f629e6
	  if (BE (new_offsets == NULL, 0))
Packit Service f629e6
	    return REG_ESPACE;
Packit Service f629e6
	  pstr->offsets = new_offsets;
Packit Service f629e6
	}
Packit Service f629e6
    }
Packit Service f629e6
#endif /* RE_ENABLE_I18N  */
Packit Service f629e6
  if (pstr->mbs_allocated)
Packit Service f629e6
    {
Packit Service f629e6
      unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char,
Packit Service f629e6
					   new_buf_len);
Packit Service f629e6
      if (BE (new_mbs == NULL, 0))
Packit Service f629e6
	return REG_ESPACE;
Packit Service f629e6
      pstr->mbs = new_mbs;
Packit Service f629e6
    }
Packit Service f629e6
  pstr->bufs_len = new_buf_len;
Packit Service f629e6
  return REG_NOERROR;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
re_string_construct_common (const char *str, int len, re_string_t *pstr,
Packit Service f629e6
			    RE_TRANSLATE_TYPE trans, int icase,
Packit Service f629e6
			    const re_dfa_t *dfa)
Packit Service f629e6
{
Packit Service f629e6
  pstr->raw_mbs = (const unsigned char *) str;
Packit Service f629e6
  pstr->len = len;
Packit Service f629e6
  pstr->raw_len = len;
Packit Service f629e6
  pstr->trans = trans;
Packit Service f629e6
  pstr->icase = icase ? 1 : 0;
Packit Service f629e6
  pstr->mbs_allocated = (trans != NULL || icase);
Packit Service f629e6
  pstr->mb_cur_max = dfa->mb_cur_max;
Packit Service f629e6
  pstr->is_utf8 = dfa->is_utf8;
Packit Service f629e6
  pstr->map_notascii = dfa->map_notascii;
Packit Service f629e6
  pstr->stop = pstr->len;
Packit Service f629e6
  pstr->raw_stop = pstr->stop;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
Packit Service f629e6
/* Build wide character buffer PSTR->WCS.
Packit Service f629e6
   If the byte sequence of the string are:
Packit Service f629e6
     <mb1>(0), <mb1>(1), <mb2>(0), <mb2>(1), <sb3>
Packit Service f629e6
   Then wide character buffer will be:
Packit Service f629e6
     <wc1>   , WEOF    , <wc2>   , WEOF    , <wc3>
Packit Service f629e6
   We use WEOF for padding, they indicate that the position isn't
Packit Service f629e6
   a first byte of a multibyte character.
Packit Service f629e6
Packit Service f629e6
   Note that this function assumes PSTR->VALID_LEN elements are already
Packit Service f629e6
   built and starts from PSTR->VALID_LEN.  */
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
build_wcs_buffer (re_string_t *pstr)
Packit Service f629e6
{
Packit Service f629e6
#ifdef _LIBC
Packit Service f629e6
  unsigned char buf[MB_LEN_MAX];
Packit Service f629e6
  assert (MB_LEN_MAX >= pstr->mb_cur_max);
Packit Service f629e6
#else
Packit Service f629e6
  unsigned char buf[64];
Packit Service f629e6
#endif
Packit Service f629e6
  mbstate_t prev_st;
Packit Service f629e6
  int byte_idx, end_idx, remain_len;
Packit Service f629e6
  size_t mbclen;
Packit Service f629e6
Packit Service f629e6
  /* Build the buffers from pstr->valid_len to either pstr->len or
Packit Service f629e6
     pstr->bufs_len.  */
Packit Service f629e6
  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
Packit Service f629e6
  for (byte_idx = pstr->valid_len; byte_idx < end_idx;)
Packit Service f629e6
    {
Packit Service f629e6
      wchar_t wc;
Packit Service f629e6
      const char *p;
Packit Service f629e6
Packit Service f629e6
      remain_len = end_idx - byte_idx;
Packit Service f629e6
      prev_st = pstr->cur_state;
Packit Service f629e6
      /* Apply the translation if we need.  */
Packit Service f629e6
      if (BE (pstr->trans != NULL, 0))
Packit Service f629e6
	{
Packit Service f629e6
	  int i, ch;
Packit Service f629e6
Packit Service f629e6
	  for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
Packit Service f629e6
	    {
Packit Service f629e6
	      ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i];
Packit Service f629e6
	      buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch];
Packit Service f629e6
	    }
Packit Service f629e6
	  p = (const char *) buf;
Packit Service f629e6
	}
Packit Service f629e6
      else
Packit Service f629e6
	p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx;
Packit Service f629e6
      mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state);
Packit Service f629e6
      if (BE (mbclen == (size_t) -1 || mbclen == 0
Packit Service f629e6
	      || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len), 0))
Packit Service f629e6
	{
Packit Service f629e6
	  /* We treat these cases as a singlebyte character.  */
Packit Service f629e6
	  mbclen = 1;
Packit Service f629e6
	  wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
Packit Service f629e6
	  if (BE (pstr->trans != NULL, 0))
Packit Service f629e6
	    wc = pstr->trans[wc];
Packit Service f629e6
	  pstr->cur_state = prev_st;
Packit Service f629e6
	}
Packit Service f629e6
      else if (BE (mbclen == (size_t) -2, 0))
Packit Service f629e6
	{
Packit Service f629e6
	  /* The buffer doesn't have enough space, finish to build.  */
Packit Service f629e6
	  pstr->cur_state = prev_st;
Packit Service f629e6
	  break;
Packit Service f629e6
	}
Packit Service f629e6
Packit Service f629e6
      /* Write wide character and padding.  */
Packit Service f629e6
      pstr->wcs[byte_idx++] = wc;
Packit Service f629e6
      /* Write paddings.  */
Packit Service f629e6
      for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
Packit Service f629e6
	pstr->wcs[byte_idx++] = WEOF;
Packit Service f629e6
    }
Packit Service f629e6
  pstr->valid_len = byte_idx;
Packit Service f629e6
  pstr->valid_raw_len = byte_idx;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Build wide character buffer PSTR->WCS like build_wcs_buffer,
Packit Service f629e6
   but for REG_ICASE.  */
Packit Service f629e6
Packit Service f629e6
static reg_errcode_t
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
build_wcs_upper_buffer (re_string_t *pstr)
Packit Service f629e6
{
Packit Service f629e6
  mbstate_t prev_st;
Packit Service f629e6
  int src_idx, byte_idx, end_idx, remain_len;
Packit Service f629e6
  size_t mbclen;
Packit Service f629e6
#ifdef _LIBC
Packit Service f629e6
  char buf[MB_LEN_MAX];
Packit Service f629e6
  assert (MB_LEN_MAX >= pstr->mb_cur_max);
Packit Service f629e6
#else
Packit Service f629e6
  char buf[64];
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
  byte_idx = pstr->valid_len;
Packit Service f629e6
  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
Packit Service f629e6
Packit Service f629e6
  /* The following optimization assumes that ASCII characters can be
Packit Service f629e6
     mapped to wide characters with a simple cast.  */
Packit Service f629e6
  if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed)
Packit Service f629e6
    {
Packit Service f629e6
      while (byte_idx < end_idx)
Packit Service f629e6
	{
Packit Service f629e6
	  wchar_t wc;
Packit Service f629e6
Packit Service f629e6
	  if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx])
Packit Service f629e6
	      && mbsinit (&pstr->cur_state))
Packit Service f629e6
	    {
Packit Service f629e6
	      /* In case of a singlebyte character.  */
Packit Service f629e6
	      pstr->mbs[byte_idx]
Packit Service f629e6
		= toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]);
Packit Service f629e6
	      /* The next step uses the assumption that wchar_t is encoded
Packit Service f629e6
		 ASCII-safe: all ASCII values can be converted like this.  */
Packit Service f629e6
	      pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx];
Packit Service f629e6
	      ++byte_idx;
Packit Service f629e6
	      continue;
Packit Service f629e6
	    }
Packit Service f629e6
Packit Service f629e6
	  remain_len = end_idx - byte_idx;
Packit Service f629e6
	  prev_st = pstr->cur_state;
Packit Service f629e6
	  mbclen = __mbrtowc (&wc,
Packit Service f629e6
			      ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx
Packit Service f629e6
			       + byte_idx), remain_len, &pstr->cur_state);
Packit Service f629e6
	  if (BE (mbclen + 2 > 2, 1))
Packit Service f629e6
	    {
Packit Service f629e6
	      wchar_t wcu = wc;
Packit Service f629e6
	      if (iswlower (wc))
Packit Service f629e6
		{
Packit Service f629e6
		  size_t mbcdlen;
Packit Service f629e6
Packit Service f629e6
		  wcu = towupper (wc);
Packit Service f629e6
		  mbcdlen = __wcrtomb (buf, wcu, &prev_st);
Packit Service f629e6
		  if (BE (mbclen == mbcdlen, 1))
Packit Service f629e6
		    memcpy (pstr->mbs + byte_idx, buf, mbclen);
Packit Service f629e6
		  else
Packit Service f629e6
		    {
Packit Service f629e6
		      src_idx = byte_idx;
Packit Service f629e6
		      goto offsets_needed;
Packit Service f629e6
		    }
Packit Service f629e6
		}
Packit Service f629e6
	      else
Packit Service f629e6
		memcpy (pstr->mbs + byte_idx,
Packit Service f629e6
			pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen);
Packit Service f629e6
	      pstr->wcs[byte_idx++] = wcu;
Packit Service f629e6
	      /* Write paddings.  */
Packit Service f629e6
	      for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
Packit Service f629e6
		pstr->wcs[byte_idx++] = WEOF;
Packit Service f629e6
	    }
Packit Service f629e6
	  else if (mbclen == (size_t) -1 || mbclen == 0
Packit Service f629e6
		   || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len))
Packit Service f629e6
	    {
Packit Service f629e6
	      /* It is an invalid character, an incomplete character
Packit Service f629e6
		 at the end of the string, or '\0'.  Just use the byte.  */
Packit Service f629e6
	      int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];
Packit Service f629e6
	      pstr->mbs[byte_idx] = ch;
Packit Service f629e6
	      /* And also cast it to wide char.  */
Packit Service f629e6
	      pstr->wcs[byte_idx++] = (wchar_t) ch;
Packit Service f629e6
	      if (BE (mbclen == (size_t) -1, 0))
Packit Service f629e6
		pstr->cur_state = prev_st;
Packit Service f629e6
	    }
Packit Service f629e6
	  else
Packit Service f629e6
	    {
Packit Service f629e6
	      /* The buffer doesn't have enough space, finish to build.  */
Packit Service f629e6
	      pstr->cur_state = prev_st;
Packit Service f629e6
	      break;
Packit Service f629e6
	    }
Packit Service f629e6
	}
Packit Service f629e6
      pstr->valid_len = byte_idx;
Packit Service f629e6
      pstr->valid_raw_len = byte_idx;
Packit Service f629e6
      return REG_NOERROR;
Packit Service f629e6
    }
Packit Service f629e6
  else
Packit Service f629e6
    for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;)
Packit Service f629e6
      {
Packit Service f629e6
	wchar_t wc;
Packit Service f629e6
	const char *p;
Packit Service f629e6
      offsets_needed:
Packit Service f629e6
	remain_len = end_idx - byte_idx;
Packit Service f629e6
	prev_st = pstr->cur_state;
Packit Service f629e6
	if (BE (pstr->trans != NULL, 0))
Packit Service f629e6
	  {
Packit Service f629e6
	    int i, ch;
Packit Service f629e6
Packit Service f629e6
	    for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)
Packit Service f629e6
	      {
Packit Service f629e6
		ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i];
Packit Service f629e6
		buf[i] = pstr->trans[ch];
Packit Service f629e6
	      }
Packit Service f629e6
	    p = (const char *) buf;
Packit Service f629e6
	  }
Packit Service f629e6
	else
Packit Service f629e6
	  p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx;
Packit Service f629e6
	mbclen = __mbrtowc (&wc, p, remain_len, &pstr->cur_state);
Packit Service f629e6
	if (BE (mbclen + 2 > 2, 1))
Packit Service f629e6
	  {
Packit Service f629e6
	    wchar_t wcu = wc;
Packit Service f629e6
	    if (iswlower (wc))
Packit Service f629e6
	      {
Packit Service f629e6
		size_t mbcdlen;
Packit Service f629e6
Packit Service f629e6
		wcu = towupper (wc);
Packit Service f629e6
		mbcdlen = wcrtomb ((char *) buf, wcu, &prev_st);
Packit Service f629e6
		if (BE (mbclen == mbcdlen, 1))
Packit Service f629e6
		  memcpy (pstr->mbs + byte_idx, buf, mbclen);
Packit Service f629e6
		else if (mbcdlen != (size_t) -1)
Packit Service f629e6
		  {
Packit Service f629e6
		    size_t i;
Packit Service f629e6
Packit Service f629e6
		    if (byte_idx + mbcdlen > pstr->bufs_len)
Packit Service f629e6
		      {
Packit Service f629e6
			pstr->cur_state = prev_st;
Packit Service f629e6
			break;
Packit Service f629e6
		      }
Packit Service f629e6
Packit Service f629e6
		    if (pstr->offsets == NULL)
Packit Service f629e6
		      {
Packit Service f629e6
			pstr->offsets = re_malloc (int, pstr->bufs_len);
Packit Service f629e6
Packit Service f629e6
			if (pstr->offsets == NULL)
Packit Service f629e6
			  return REG_ESPACE;
Packit Service f629e6
		      }
Packit Service f629e6
		    if (!pstr->offsets_needed)
Packit Service f629e6
		      {
Packit Service f629e6
			for (i = 0; i < (size_t) byte_idx; ++i)
Packit Service f629e6
			  pstr->offsets[i] = i;
Packit Service f629e6
			pstr->offsets_needed = 1;
Packit Service f629e6
		      }
Packit Service f629e6
Packit Service f629e6
		    memcpy (pstr->mbs + byte_idx, buf, mbcdlen);
Packit Service f629e6
		    pstr->wcs[byte_idx] = wcu;
Packit Service f629e6
		    pstr->offsets[byte_idx] = src_idx;
Packit Service f629e6
		    for (i = 1; i < mbcdlen; ++i)
Packit Service f629e6
		      {
Packit Service f629e6
			pstr->offsets[byte_idx + i]
Packit Service f629e6
			  = src_idx + (i < mbclen ? i : mbclen - 1);
Packit Service f629e6
			pstr->wcs[byte_idx + i] = WEOF;
Packit Service f629e6
		      }
Packit Service f629e6
		    pstr->len += mbcdlen - mbclen;
Packit Service f629e6
		    if (pstr->raw_stop > src_idx)
Packit Service f629e6
		      pstr->stop += mbcdlen - mbclen;
Packit Service f629e6
		    end_idx = (pstr->bufs_len > pstr->len)
Packit Service f629e6
			      ? pstr->len : pstr->bufs_len;
Packit Service f629e6
		    byte_idx += mbcdlen;
Packit Service f629e6
		    src_idx += mbclen;
Packit Service f629e6
		    continue;
Packit Service f629e6
		  }
Packit Service f629e6
		else
Packit Service f629e6
		  memcpy (pstr->mbs + byte_idx, p, mbclen);
Packit Service f629e6
	      }
Packit Service f629e6
	    else
Packit Service f629e6
	      memcpy (pstr->mbs + byte_idx, p, mbclen);
Packit Service f629e6
Packit Service f629e6
	    if (BE (pstr->offsets_needed != 0, 0))
Packit Service f629e6
	      {
Packit Service f629e6
		size_t i;
Packit Service f629e6
		for (i = 0; i < mbclen; ++i)
Packit Service f629e6
		  pstr->offsets[byte_idx + i] = src_idx + i;
Packit Service f629e6
	      }
Packit Service f629e6
	    src_idx += mbclen;
Packit Service f629e6
Packit Service f629e6
	    pstr->wcs[byte_idx++] = wcu;
Packit Service f629e6
	    /* Write paddings.  */
Packit Service f629e6
	    for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)
Packit Service f629e6
	      pstr->wcs[byte_idx++] = WEOF;
Packit Service f629e6
	  }
Packit Service f629e6
	else if (mbclen == (size_t) -1 || mbclen == 0
Packit Service f629e6
		 || (mbclen == (size_t) -2 && pstr->bufs_len >= pstr->len))
Packit Service f629e6
	  {
Packit Service f629e6
	    /* It is an invalid character or '\0'.  Just use the byte.  */
Packit Service f629e6
	    int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx];
Packit Service f629e6
Packit Service f629e6
	    if (BE (pstr->trans != NULL, 0))
Packit Service f629e6
	      ch = pstr->trans [ch];
Packit Service f629e6
	    pstr->mbs[byte_idx] = ch;
Packit Service f629e6
Packit Service f629e6
	    if (BE (pstr->offsets_needed != 0, 0))
Packit Service f629e6
	      pstr->offsets[byte_idx] = src_idx;
Packit Service f629e6
	    ++src_idx;
Packit Service f629e6
Packit Service f629e6
	    /* And also cast it to wide char.  */
Packit Service f629e6
	    pstr->wcs[byte_idx++] = (wchar_t) ch;
Packit Service f629e6
	    if (BE (mbclen == (size_t) -1, 0))
Packit Service f629e6
	      pstr->cur_state = prev_st;
Packit Service f629e6
	  }
Packit Service f629e6
	else
Packit Service f629e6
	  {
Packit Service f629e6
	    /* The buffer doesn't have enough space, finish to build.  */
Packit Service f629e6
	    pstr->cur_state = prev_st;
Packit Service f629e6
	    break;
Packit Service f629e6
	  }
Packit Service f629e6
      }
Packit Service f629e6
  pstr->valid_len = byte_idx;
Packit Service f629e6
  pstr->valid_raw_len = src_idx;
Packit Service f629e6
  return REG_NOERROR;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Skip characters until the index becomes greater than NEW_RAW_IDX.
Packit Service f629e6
   Return the index.  */
Packit Service f629e6
Packit Service f629e6
static int
Packit Service f629e6
re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc)
Packit Service f629e6
{
Packit Service f629e6
  mbstate_t prev_st;
Packit Service f629e6
  int rawbuf_idx;
Packit Service f629e6
  size_t mbclen;
Packit Service f629e6
  wint_t wc = WEOF;
Packit Service f629e6
Packit Service f629e6
  /* Skip the characters which are not necessary to check.  */
Packit Service f629e6
  for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len;
Packit Service f629e6
       rawbuf_idx < new_raw_idx;)
Packit Service f629e6
    {
Packit Service f629e6
      wchar_t wc2;
Packit Service f629e6
      int remain_len = pstr->raw_len - rawbuf_idx;
Packit Service f629e6
      prev_st = pstr->cur_state;
Packit Service f629e6
      mbclen = __mbrtowc (&wc2, (const char *) pstr->raw_mbs + rawbuf_idx,
Packit Service f629e6
			  remain_len, &pstr->cur_state);
Packit Service f629e6
      if (BE ((ssize_t) mbclen <= 0, 0))
Packit Service f629e6
	{
Packit Service f629e6
	  /* We treat these cases as a single byte character.  */
Packit Service f629e6
	  if (mbclen == 0 || remain_len == 0)
Packit Service f629e6
	    wc = L'\0';
Packit Service f629e6
	  else
Packit Service f629e6
	    wc = *(unsigned char *) (pstr->raw_mbs + rawbuf_idx);
Packit Service f629e6
	  mbclen = 1;
Packit Service f629e6
	  pstr->cur_state = prev_st;
Packit Service f629e6
	}
Packit Service f629e6
      else
Packit Service f629e6
	wc = (wint_t) wc2;
Packit Service f629e6
      /* Then proceed the next character.  */
Packit Service f629e6
      rawbuf_idx += mbclen;
Packit Service f629e6
    }
Packit Service f629e6
  *last_wc = (wint_t) wc;
Packit Service f629e6
  return rawbuf_idx;
Packit Service f629e6
}
Packit Service f629e6
#endif /* RE_ENABLE_I18N  */
Packit Service f629e6
Packit Service f629e6
/* Build the buffer PSTR->MBS, and apply the translation if we need.
Packit Service f629e6
   This function is used in case of REG_ICASE.  */
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
build_upper_buffer (re_string_t *pstr)
Packit Service f629e6
{
Packit Service f629e6
  int char_idx, end_idx;
Packit Service f629e6
  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
Packit Service f629e6
Packit Service f629e6
  for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx)
Packit Service f629e6
    {
Packit Service f629e6
      int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx];
Packit Service f629e6
      if (BE (pstr->trans != NULL, 0))
Packit Service f629e6
	ch = pstr->trans[ch];
Packit Service f629e6
      if (islower (ch))
Packit Service f629e6
	pstr->mbs[char_idx] = toupper (ch);
Packit Service f629e6
      else
Packit Service f629e6
	pstr->mbs[char_idx] = ch;
Packit Service f629e6
    }
Packit Service f629e6
  pstr->valid_len = char_idx;
Packit Service f629e6
  pstr->valid_raw_len = char_idx;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Apply TRANS to the buffer in PSTR.  */
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
re_string_translate_buffer (re_string_t *pstr)
Packit Service f629e6
{
Packit Service f629e6
  int buf_idx, end_idx;
Packit Service f629e6
  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;
Packit Service f629e6
Packit Service f629e6
  for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx)
Packit Service f629e6
    {
Packit Service f629e6
      int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx];
Packit Service f629e6
      pstr->mbs[buf_idx] = pstr->trans[ch];
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  pstr->valid_len = buf_idx;
Packit Service f629e6
  pstr->valid_raw_len = buf_idx;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* This function re-construct the buffers.
Packit Service f629e6
   Concretely, convert to wide character in case of pstr->mb_cur_max > 1,
Packit Service f629e6
   convert to upper case in case of REG_ICASE, apply translation.  */
Packit Service f629e6
Packit Service f629e6
static reg_errcode_t
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
re_string_reconstruct (re_string_t *pstr, int idx, int eflags)
Packit Service f629e6
{
Packit Service f629e6
  int offset = idx - pstr->raw_mbs_idx;
Packit Service f629e6
  if (BE (offset < 0, 0))
Packit Service f629e6
    {
Packit Service f629e6
      /* Reset buffer.  */
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
      if (pstr->mb_cur_max > 1)
Packit Service f629e6
	memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
Packit Service f629e6
#endif /* RE_ENABLE_I18N */
Packit Service f629e6
      pstr->len = pstr->raw_len;
Packit Service f629e6
      pstr->stop = pstr->raw_stop;
Packit Service f629e6
      pstr->valid_len = 0;
Packit Service f629e6
      pstr->raw_mbs_idx = 0;
Packit Service f629e6
      pstr->valid_raw_len = 0;
Packit Service f629e6
      pstr->offsets_needed = 0;
Packit Service f629e6
      pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF
Packit Service f629e6
			   : CONTEXT_NEWLINE | CONTEXT_BEGBUF);
Packit Service f629e6
      if (!pstr->mbs_allocated)
Packit Service f629e6
	pstr->mbs = (unsigned char *) pstr->raw_mbs;
Packit Service f629e6
      offset = idx;
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  if (BE (offset != 0, 1))
Packit Service f629e6
    {
Packit Service f629e6
      /* Should the already checked characters be kept?  */
Packit Service f629e6
      if (BE (offset < pstr->valid_raw_len, 1))
Packit Service f629e6
	{
Packit Service f629e6
	  /* Yes, move them to the front of the buffer.  */
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
	  if (BE (pstr->offsets_needed, 0))
Packit Service f629e6
	    {
Packit Service f629e6
	      int low = 0, high = pstr->valid_len, mid;
Packit Service f629e6
	      do
Packit Service f629e6
		{
Packit Service f629e6
		  mid = (high + low) / 2;
Packit Service f629e6
		  if (pstr->offsets[mid] > offset)
Packit Service f629e6
		    high = mid;
Packit Service f629e6
		  else if (pstr->offsets[mid] < offset)
Packit Service f629e6
		    low = mid + 1;
Packit Service f629e6
		  else
Packit Service f629e6
		    break;
Packit Service f629e6
		}
Packit Service f629e6
	      while (low < high);
Packit Service f629e6
	      if (pstr->offsets[mid] < offset)
Packit Service f629e6
		++mid;
Packit Service f629e6
	      pstr->tip_context = re_string_context_at (pstr, mid - 1,
Packit Service f629e6
							eflags);
Packit Service f629e6
	      /* This can be quite complicated, so handle specially
Packit Service f629e6
		 only the common and easy case where the character with
Packit Service f629e6
		 different length representation of lower and upper
Packit Service f629e6
		 case is present at or after offset.  */
Packit Service f629e6
	      if (pstr->valid_len > offset
Packit Service f629e6
		  && mid == offset && pstr->offsets[mid] == offset)
Packit Service f629e6
		{
Packit Service f629e6
		  memmove (pstr->wcs, pstr->wcs + offset,
Packit Service f629e6
			   (pstr->valid_len - offset) * sizeof (wint_t));
Packit Service f629e6
		  memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset);
Packit Service f629e6
		  pstr->valid_len -= offset;
Packit Service f629e6
		  pstr->valid_raw_len -= offset;
Packit Service f629e6
		  for (low = 0; low < pstr->valid_len; low++)
Packit Service f629e6
		    pstr->offsets[low] = pstr->offsets[low + offset] - offset;
Packit Service f629e6
		}
Packit Service f629e6
	      else
Packit Service f629e6
		{
Packit Service f629e6
		  /* Otherwise, just find out how long the partial multibyte
Packit Service f629e6
		     character at offset is and fill it with WEOF/255.  */
Packit Service f629e6
		  pstr->len = pstr->raw_len - idx + offset;
Packit Service f629e6
		  pstr->stop = pstr->raw_stop - idx + offset;
Packit Service f629e6
		  pstr->offsets_needed = 0;
Packit Service f629e6
		  while (mid > 0 && pstr->offsets[mid - 1] == offset)
Packit Service f629e6
		    --mid;
Packit Service f629e6
		  while (mid < pstr->valid_len)
Packit Service f629e6
		    if (pstr->wcs[mid] != WEOF)
Packit Service f629e6
		      break;
Packit Service f629e6
		    else
Packit Service f629e6
		      ++mid;
Packit Service f629e6
		  if (mid == pstr->valid_len)
Packit Service f629e6
		    pstr->valid_len = 0;
Packit Service f629e6
		  else
Packit Service f629e6
		    {
Packit Service f629e6
		      pstr->valid_len = pstr->offsets[mid] - offset;
Packit Service f629e6
		      if (pstr->valid_len)
Packit Service f629e6
			{
Packit Service f629e6
			  for (low = 0; low < pstr->valid_len; ++low)
Packit Service f629e6
			    pstr->wcs[low] = WEOF;
Packit Service f629e6
			  memset (pstr->mbs, 255, pstr->valid_len);
Packit Service f629e6
			}
Packit Service f629e6
		    }
Packit Service f629e6
		  pstr->valid_raw_len = pstr->valid_len;
Packit Service f629e6
		}
Packit Service f629e6
	    }
Packit Service f629e6
	  else
Packit Service f629e6
#endif
Packit Service f629e6
	    {
Packit Service f629e6
	      pstr->tip_context = re_string_context_at (pstr, offset - 1,
Packit Service f629e6
							eflags);
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
	      if (pstr->mb_cur_max > 1)
Packit Service f629e6
		memmove (pstr->wcs, pstr->wcs + offset,
Packit Service f629e6
			 (pstr->valid_len - offset) * sizeof (wint_t));
Packit Service f629e6
#endif /* RE_ENABLE_I18N */
Packit Service f629e6
	      if (BE (pstr->mbs_allocated, 0))
Packit Service f629e6
		memmove (pstr->mbs, pstr->mbs + offset,
Packit Service f629e6
			 pstr->valid_len - offset);
Packit Service f629e6
	      pstr->valid_len -= offset;
Packit Service f629e6
	      pstr->valid_raw_len -= offset;
Packit Service f629e6
#if defined DEBUG && DEBUG
Packit Service f629e6
	      assert (pstr->valid_len > 0);
Packit Service f629e6
#endif
Packit Service f629e6
	    }
Packit Service f629e6
	}
Packit Service f629e6
      else
Packit Service f629e6
	{
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
	  /* No, skip all characters until IDX.  */
Packit Service f629e6
	  int prev_valid_len = pstr->valid_len;
Packit Service f629e6
Packit Service f629e6
	  if (BE (pstr->offsets_needed, 0))
Packit Service f629e6
	    {
Packit Service f629e6
	      pstr->len = pstr->raw_len - idx + offset;
Packit Service f629e6
	      pstr->stop = pstr->raw_stop - idx + offset;
Packit Service f629e6
	      pstr->offsets_needed = 0;
Packit Service f629e6
	    }
Packit Service f629e6
#endif
Packit Service f629e6
	  pstr->valid_len = 0;
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
	  if (pstr->mb_cur_max > 1)
Packit Service f629e6
	    {
Packit Service f629e6
	      int wcs_idx;
Packit Service f629e6
	      wint_t wc = WEOF;
Packit Service f629e6
Packit Service f629e6
	      if (pstr->is_utf8)
Packit Service f629e6
		{
Packit Service f629e6
		  const unsigned char *raw, *p, *end;
Packit Service f629e6
Packit Service f629e6
		  /* Special case UTF-8.  Multi-byte chars start with any
Packit Service f629e6
		     byte other than 0x80 - 0xbf.  */
Packit Service f629e6
		  raw = pstr->raw_mbs + pstr->raw_mbs_idx;
Packit Service f629e6
		  end = raw + (offset - pstr->mb_cur_max);
Packit Service f629e6
		  if (end < pstr->raw_mbs)
Packit Service f629e6
		    end = pstr->raw_mbs;
Packit Service f629e6
		  p = raw + offset - 1;
Packit Service f629e6
#ifdef _LIBC
Packit Service f629e6
		  /* We know the wchar_t encoding is UCS4, so for the simple
Packit Service f629e6
		     case, ASCII characters, skip the conversion step.  */
Packit Service f629e6
		  if (isascii (*p) && BE (pstr->trans == NULL, 1))
Packit Service f629e6
		    {
Packit Service f629e6
		      memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
Packit Service f629e6
		      /* pstr->valid_len = 0; */
Packit Service f629e6
		      wc = (wchar_t) *p;
Packit Service f629e6
		    }
Packit Service f629e6
		  else
Packit Service f629e6
#endif
Packit Service f629e6
		    for (; p >= end; --p)
Packit Service f629e6
		      if ((*p & 0xc0) != 0x80)
Packit Service f629e6
			{
Packit Service f629e6
			  mbstate_t cur_state;
Packit Service f629e6
			  wchar_t wc2;
Packit Service f629e6
			  int mlen = raw + pstr->len - p;
Packit Service f629e6
			  unsigned char buf[6];
Packit Service f629e6
			  size_t mbclen;
Packit Service f629e6
Packit Service f629e6
			  const unsigned char *pp = p;
Packit Service f629e6
			  if (BE (pstr->trans != NULL, 0))
Packit Service f629e6
			    {
Packit Service f629e6
			      int i = mlen < 6 ? mlen : 6;
Packit Service f629e6
			      while (--i >= 0)
Packit Service f629e6
				buf[i] = pstr->trans[p[i]];
Packit Service f629e6
			      pp = buf;
Packit Service f629e6
			    }
Packit Service f629e6
			  /* XXX Don't use mbrtowc, we know which conversion
Packit Service f629e6
			     to use (UTF-8 -> UCS4).  */
Packit Service f629e6
			  memset (&cur_state, 0, sizeof (cur_state));
Packit Service f629e6
			  mbclen = __mbrtowc (&wc2, (const char *) pp, mlen,
Packit Service f629e6
					      &cur_state);
Packit Service f629e6
			  if (raw + offset - p <= mbclen
Packit Service f629e6
			      && mbclen < (size_t) -2)
Packit Service f629e6
			    {
Packit Service f629e6
			      memset (&pstr->cur_state, '\0',
Packit Service f629e6
				      sizeof (mbstate_t));
Packit Service f629e6
			      pstr->valid_len = mbclen - (raw + offset - p);
Packit Service f629e6
			      wc = wc2;
Packit Service f629e6
			    }
Packit Service f629e6
			  break;
Packit Service f629e6
			}
Packit Service f629e6
		}
Packit Service f629e6
Packit Service f629e6
	      if (wc == WEOF)
Packit Service f629e6
		pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx;
Packit Service f629e6
	      if (wc == WEOF)
Packit Service f629e6
		pstr->tip_context
Packit Service f629e6
		  = re_string_context_at (pstr, prev_valid_len - 1, eflags);
Packit Service f629e6
	      else
Packit Service f629e6
		pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0)
Packit Service f629e6
				      && IS_WIDE_WORD_CHAR (wc))
Packit Service f629e6
				     ? CONTEXT_WORD
Packit Service f629e6
				     : ((IS_WIDE_NEWLINE (wc)
Packit Service f629e6
					 && pstr->newline_anchor)
Packit Service f629e6
					? CONTEXT_NEWLINE : 0));
Packit Service f629e6
	      if (BE (pstr->valid_len, 0))
Packit Service f629e6
		{
Packit Service f629e6
		  for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx)
Packit Service f629e6
		    pstr->wcs[wcs_idx] = WEOF;
Packit Service f629e6
		  if (pstr->mbs_allocated)
Packit Service f629e6
		    memset (pstr->mbs, 255, pstr->valid_len);
Packit Service f629e6
		}
Packit Service f629e6
	      pstr->valid_raw_len = pstr->valid_len;
Packit Service f629e6
	    }
Packit Service f629e6
	  else
Packit Service f629e6
#endif /* RE_ENABLE_I18N */
Packit Service f629e6
	    {
Packit Service f629e6
	      int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1];
Packit Service f629e6
	      pstr->valid_raw_len = 0;
Packit Service f629e6
	      if (pstr->trans)
Packit Service f629e6
		c = pstr->trans[c];
Packit Service f629e6
	      pstr->tip_context = (bitset_contain (pstr->word_char, c)
Packit Service f629e6
				   ? CONTEXT_WORD
Packit Service f629e6
				   : ((IS_NEWLINE (c) && pstr->newline_anchor)
Packit Service f629e6
				      ? CONTEXT_NEWLINE : 0));
Packit Service f629e6
	    }
Packit Service f629e6
	}
Packit Service f629e6
      if (!BE (pstr->mbs_allocated, 0))
Packit Service f629e6
	pstr->mbs += offset;
Packit Service f629e6
    }
Packit Service f629e6
  pstr->raw_mbs_idx = idx;
Packit Service f629e6
  pstr->len -= offset;
Packit Service f629e6
  pstr->stop -= offset;
Packit Service f629e6
Packit Service f629e6
  /* Then build the buffers.  */
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
  if (pstr->mb_cur_max > 1)
Packit Service f629e6
    {
Packit Service f629e6
      if (pstr->icase)
Packit Service f629e6
	{
Packit Service f629e6
	  reg_errcode_t ret = build_wcs_upper_buffer (pstr);
Packit Service f629e6
	  if (BE (ret != REG_NOERROR, 0))
Packit Service f629e6
	    return ret;
Packit Service f629e6
	}
Packit Service f629e6
      else
Packit Service f629e6
	build_wcs_buffer (pstr);
Packit Service f629e6
    }
Packit Service f629e6
  else
Packit Service f629e6
#endif /* RE_ENABLE_I18N */
Packit Service f629e6
    if (BE (pstr->mbs_allocated, 0))
Packit Service f629e6
      {
Packit Service f629e6
	if (pstr->icase)
Packit Service f629e6
	  build_upper_buffer (pstr);
Packit Service f629e6
	else if (pstr->trans != NULL)
Packit Service f629e6
	  re_string_translate_buffer (pstr);
Packit Service f629e6
      }
Packit Service f629e6
    else
Packit Service f629e6
      pstr->valid_len = pstr->len;
Packit Service f629e6
Packit Service f629e6
  pstr->cur_idx = 0;
Packit Service f629e6
  return REG_NOERROR;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
static unsigned char
Packit Service f629e6
__attribute ((pure))
Packit Service f629e6
re_string_peek_byte_case (const re_string_t *pstr, int idx)
Packit Service f629e6
{
Packit Service f629e6
  int ch, off;
Packit Service f629e6
Packit Service f629e6
  /* Handle the common (easiest) cases first.  */
Packit Service f629e6
  if (BE (!pstr->mbs_allocated, 1))
Packit Service f629e6
    return re_string_peek_byte (pstr, idx);
Packit Service f629e6
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
  if (pstr->mb_cur_max > 1
Packit Service f629e6
      && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx))
Packit Service f629e6
    return re_string_peek_byte (pstr, idx);
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
  off = pstr->cur_idx + idx;
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
  if (pstr->offsets_needed)
Packit Service f629e6
    off = pstr->offsets[off];
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
  ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];
Packit Service f629e6
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
  /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I
Packit Service f629e6
     this function returns CAPITAL LETTER I instead of first byte of
Packit Service f629e6
     DOTLESS SMALL LETTER I.  The latter would confuse the parser,
Packit Service f629e6
     since peek_byte_case doesn't advance cur_idx in any way.  */
Packit Service f629e6
  if (pstr->offsets_needed && !isascii (ch))
Packit Service f629e6
    return re_string_peek_byte (pstr, idx);
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
  return ch;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
static unsigned char
Packit Service f629e6
re_string_fetch_byte_case (re_string_t *pstr)
Packit Service f629e6
{
Packit Service f629e6
  if (BE (!pstr->mbs_allocated, 1))
Packit Service f629e6
    return re_string_fetch_byte (pstr);
Packit Service f629e6
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
  if (pstr->offsets_needed)
Packit Service f629e6
    {
Packit Service f629e6
      int off, ch;
Packit Service f629e6
Packit Service f629e6
      /* For tr_TR.UTF-8 [[:islower:]] there is
Packit Service f629e6
	 [[: CAPITAL LETTER I WITH DOT lower:]] in mbs.  Skip
Packit Service f629e6
	 in that case the whole multi-byte character and return
Packit Service f629e6
	 the original letter.  On the other side, with
Packit Service f629e6
	 [[: DOTLESS SMALL LETTER I return [[:I, as doing
Packit Service f629e6
	 anything else would complicate things too much.  */
Packit Service f629e6
Packit Service f629e6
      if (!re_string_first_byte (pstr, pstr->cur_idx))
Packit Service f629e6
	return re_string_fetch_byte (pstr);
Packit Service f629e6
Packit Service f629e6
      off = pstr->offsets[pstr->cur_idx];
Packit Service f629e6
      ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];
Packit Service f629e6
Packit Service f629e6
      if (! isascii (ch))
Packit Service f629e6
	return re_string_fetch_byte (pstr);
Packit Service f629e6
Packit Service f629e6
      re_string_skip_bytes (pstr,
Packit Service f629e6
			    re_string_char_size_at (pstr, pstr->cur_idx));
Packit Service f629e6
      return ch;
Packit Service f629e6
    }
Packit Service f629e6
#endif
Packit Service f629e6
Packit Service f629e6
  return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++];
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
re_string_destruct (re_string_t *pstr)
Packit Service f629e6
{
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
  re_free (pstr->wcs);
Packit Service f629e6
  re_free (pstr->offsets);
Packit Service f629e6
#endif /* RE_ENABLE_I18N  */
Packit Service f629e6
  if (pstr->mbs_allocated)
Packit Service f629e6
    re_free (pstr->mbs);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Return the context at IDX in INPUT.  */
Packit Service f629e6
Packit Service f629e6
static unsigned int
Packit Service f629e6
re_string_context_at (const re_string_t *input, int idx, int eflags)
Packit Service f629e6
{
Packit Service f629e6
  int c;
Packit Service f629e6
  if (BE (idx < 0, 0))
Packit Service f629e6
    /* In this case, we use the value stored in input->tip_context,
Packit Service f629e6
       since we can't know the character in input->mbs[-1] here.  */
Packit Service f629e6
    return input->tip_context;
Packit Service f629e6
  if (BE (idx == input->len, 0))
Packit Service f629e6
    return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF
Packit Service f629e6
	    : CONTEXT_NEWLINE | CONTEXT_ENDBUF);
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
  if (input->mb_cur_max > 1)
Packit Service f629e6
    {
Packit Service f629e6
      wint_t wc;
Packit Service f629e6
      int wc_idx = idx;
Packit Service f629e6
      while(input->wcs[wc_idx] == WEOF)
Packit Service f629e6
	{
Packit Service f629e6
#if defined DEBUG && DEBUG
Packit Service f629e6
	  /* It must not happen.  */
Packit Service f629e6
	  assert (wc_idx >= 0);
Packit Service f629e6
#endif
Packit Service f629e6
	  --wc_idx;
Packit Service f629e6
	  if (wc_idx < 0)
Packit Service f629e6
	    return input->tip_context;
Packit Service f629e6
	}
Packit Service f629e6
      wc = input->wcs[wc_idx];
Packit Service f629e6
      if (BE (input->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc))
Packit Service f629e6
	return CONTEXT_WORD;
Packit Service f629e6
      return (IS_WIDE_NEWLINE (wc) && input->newline_anchor
Packit Service f629e6
	      ? CONTEXT_NEWLINE : 0);
Packit Service f629e6
    }
Packit Service f629e6
  else
Packit Service f629e6
#endif
Packit Service f629e6
    {
Packit Service f629e6
      c = re_string_byte_at (input, idx);
Packit Service f629e6
      if (bitset_contain (input->word_char, c))
Packit Service f629e6
	return CONTEXT_WORD;
Packit Service f629e6
      return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0;
Packit Service f629e6
    }
Packit Service f629e6
}
Packit Service f629e6

Packit Service f629e6
/* Functions for set operation.  */
Packit Service f629e6
Packit Service f629e6
static reg_errcode_t
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
re_node_set_alloc (re_node_set *set, int size)
Packit Service f629e6
{
Packit Service f629e6
  /*
Packit Service f629e6
   * ADR: valgrind says size can be 0, which then doesn't
Packit Service f629e6
   * free the block of size 0.  Harumph. This seems
Packit Service f629e6
   * to work ok, though.
Packit Service f629e6
   */
Packit Service f629e6
  if (size == 0)
Packit Service f629e6
    {
Packit Service f629e6
       memset(set, 0, sizeof(*set));
Packit Service f629e6
       return REG_NOERROR;
Packit Service f629e6
    }
Packit Service f629e6
  set->alloc = size;
Packit Service f629e6
  set->nelem = 0;
Packit Service f629e6
  set->elems = re_malloc (int, size);
Packit Service f629e6
  if (BE (set->elems == NULL, 0))
Packit Service f629e6
    return REG_ESPACE;
Packit Service f629e6
  return REG_NOERROR;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
static reg_errcode_t
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
re_node_set_init_1 (re_node_set *set, int elem)
Packit Service f629e6
{
Packit Service f629e6
  set->alloc = 1;
Packit Service f629e6
  set->nelem = 1;
Packit Service f629e6
  set->elems = re_malloc (int, 1);
Packit Service f629e6
  if (BE (set->elems == NULL, 0))
Packit Service f629e6
    {
Packit Service f629e6
      set->alloc = set->nelem = 0;
Packit Service f629e6
      return REG_ESPACE;
Packit Service f629e6
    }
Packit Service f629e6
  set->elems[0] = elem;
Packit Service f629e6
  return REG_NOERROR;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
static reg_errcode_t
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
re_node_set_init_2 (re_node_set *set, int elem1, int elem2)
Packit Service f629e6
{
Packit Service f629e6
  set->alloc = 2;
Packit Service f629e6
  set->elems = re_malloc (int, 2);
Packit Service f629e6
  if (BE (set->elems == NULL, 0))
Packit Service f629e6
    return REG_ESPACE;
Packit Service f629e6
  if (elem1 == elem2)
Packit Service f629e6
    {
Packit Service f629e6
      set->nelem = 1;
Packit Service f629e6
      set->elems[0] = elem1;
Packit Service f629e6
    }
Packit Service f629e6
  else
Packit Service f629e6
    {
Packit Service f629e6
      set->nelem = 2;
Packit Service f629e6
      if (elem1 < elem2)
Packit Service f629e6
	{
Packit Service f629e6
	  set->elems[0] = elem1;
Packit Service f629e6
	  set->elems[1] = elem2;
Packit Service f629e6
	}
Packit Service f629e6
      else
Packit Service f629e6
	{
Packit Service f629e6
	  set->elems[0] = elem2;
Packit Service f629e6
	  set->elems[1] = elem1;
Packit Service f629e6
	}
Packit Service f629e6
    }
Packit Service f629e6
  return REG_NOERROR;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
static reg_errcode_t
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
re_node_set_init_copy (re_node_set *dest, const re_node_set *src)
Packit Service f629e6
{
Packit Service f629e6
  dest->nelem = src->nelem;
Packit Service f629e6
  if (src->nelem > 0)
Packit Service f629e6
    {
Packit Service f629e6
      dest->alloc = dest->nelem;
Packit Service f629e6
      dest->elems = re_malloc (int, dest->alloc);
Packit Service f629e6
      if (BE (dest->elems == NULL, 0))
Packit Service f629e6
	{
Packit Service f629e6
	  dest->alloc = dest->nelem = 0;
Packit Service f629e6
	  return REG_ESPACE;
Packit Service f629e6
	}
Packit Service f629e6
      memcpy (dest->elems, src->elems, src->nelem * sizeof (int));
Packit Service f629e6
    }
Packit Service f629e6
  else
Packit Service f629e6
    re_node_set_init_empty (dest);
Packit Service f629e6
  return REG_NOERROR;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to
Packit Service f629e6
   DEST. Return value indicate the error code or REG_NOERROR if succeeded.
Packit Service f629e6
   Note: We assume dest->elems is NULL, when dest->alloc is 0.  */
Packit Service f629e6
Packit Service f629e6
static reg_errcode_t
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1,
Packit Service f629e6
			   const re_node_set *src2)
Packit Service f629e6
{
Packit Service f629e6
  int i1, i2, is, id, delta, sbase;
Packit Service f629e6
  if (src1->nelem == 0 || src2->nelem == 0)
Packit Service f629e6
    return REG_NOERROR;
Packit Service f629e6
Packit Service f629e6
  /* We need dest->nelem + 2 * elems_in_intersection; this is a
Packit Service f629e6
     conservative estimate.  */
Packit Service f629e6
  if (src1->nelem + src2->nelem + dest->nelem > dest->alloc)
Packit Service f629e6
    {
Packit Service f629e6
      int new_alloc = src1->nelem + src2->nelem + dest->alloc;
Packit Service f629e6
      int *new_elems = re_realloc (dest->elems, int, new_alloc);
Packit Service f629e6
      if (BE (new_elems == NULL, 0))
Packit Service f629e6
	return REG_ESPACE;
Packit Service f629e6
      dest->elems = new_elems;
Packit Service f629e6
      dest->alloc = new_alloc;
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  /* Find the items in the intersection of SRC1 and SRC2, and copy
Packit Service f629e6
     into the top of DEST those that are not already in DEST itself.  */
Packit Service f629e6
  sbase = dest->nelem + src1->nelem + src2->nelem;
Packit Service f629e6
  i1 = src1->nelem - 1;
Packit Service f629e6
  i2 = src2->nelem - 1;
Packit Service f629e6
  id = dest->nelem - 1;
Packit Service f629e6
  for (;;)
Packit Service f629e6
    {
Packit Service f629e6
      if (src1->elems[i1] == src2->elems[i2])
Packit Service f629e6
	{
Packit Service f629e6
	  /* Try to find the item in DEST.  Maybe we could binary search?  */
Packit Service f629e6
	  while (id >= 0 && dest->elems[id] > src1->elems[i1])
Packit Service f629e6
	    --id;
Packit Service f629e6
Packit Service f629e6
	  if (id < 0 || dest->elems[id] != src1->elems[i1])
Packit Service f629e6
	    dest->elems[--sbase] = src1->elems[i1];
Packit Service f629e6
Packit Service f629e6
	  if (--i1 < 0 || --i2 < 0)
Packit Service f629e6
	    break;
Packit Service f629e6
	}
Packit Service f629e6
Packit Service f629e6
      /* Lower the highest of the two items.  */
Packit Service f629e6
      else if (src1->elems[i1] < src2->elems[i2])
Packit Service f629e6
	{
Packit Service f629e6
	  if (--i2 < 0)
Packit Service f629e6
	    break;
Packit Service f629e6
	}
Packit Service f629e6
      else
Packit Service f629e6
	{
Packit Service f629e6
	  if (--i1 < 0)
Packit Service f629e6
	    break;
Packit Service f629e6
	}
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  id = dest->nelem - 1;
Packit Service f629e6
  is = dest->nelem + src1->nelem + src2->nelem - 1;
Packit Service f629e6
  delta = is - sbase + 1;
Packit Service f629e6
Packit Service f629e6
  /* Now copy.  When DELTA becomes zero, the remaining
Packit Service f629e6
     DEST elements are already in place; this is more or
Packit Service f629e6
     less the same loop that is in re_node_set_merge.  */
Packit Service f629e6
  dest->nelem += delta;
Packit Service f629e6
  if (delta > 0 && id >= 0)
Packit Service f629e6
    for (;;)
Packit Service f629e6
      {
Packit Service f629e6
	if (dest->elems[is] > dest->elems[id])
Packit Service f629e6
	  {
Packit Service f629e6
	    /* Copy from the top.  */
Packit Service f629e6
	    dest->elems[id + delta--] = dest->elems[is--];
Packit Service f629e6
	    if (delta == 0)
Packit Service f629e6
	      break;
Packit Service f629e6
	  }
Packit Service f629e6
	else
Packit Service f629e6
	  {
Packit Service f629e6
	    /* Slide from the bottom.  */
Packit Service f629e6
	    dest->elems[id + delta] = dest->elems[id];
Packit Service f629e6
	    if (--id < 0)
Packit Service f629e6
	      break;
Packit Service f629e6
	  }
Packit Service f629e6
      }
Packit Service f629e6
Packit Service f629e6
  /* Copy remaining SRC elements.  */
Packit Service f629e6
  memcpy (dest->elems, dest->elems + sbase, delta * sizeof (int));
Packit Service f629e6
Packit Service f629e6
  return REG_NOERROR;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Calculate the union set of the sets SRC1 and SRC2. And store it to
Packit Service f629e6
   DEST. Return value indicate the error code or REG_NOERROR if succeeded.  */
Packit Service f629e6
Packit Service f629e6
static reg_errcode_t
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
re_node_set_init_union (re_node_set *dest, const re_node_set *src1,
Packit Service f629e6
			const re_node_set *src2)
Packit Service f629e6
{
Packit Service f629e6
  int i1, i2, id;
Packit Service f629e6
  if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0)
Packit Service f629e6
    {
Packit Service f629e6
      dest->alloc = src1->nelem + src2->nelem;
Packit Service f629e6
      dest->elems = re_malloc (int, dest->alloc);
Packit Service f629e6
      if (BE (dest->elems == NULL, 0))
Packit Service f629e6
	return REG_ESPACE;
Packit Service f629e6
    }
Packit Service f629e6
  else
Packit Service f629e6
    {
Packit Service f629e6
      if (src1 != NULL && src1->nelem > 0)
Packit Service f629e6
	return re_node_set_init_copy (dest, src1);
Packit Service f629e6
      else if (src2 != NULL && src2->nelem > 0)
Packit Service f629e6
	return re_node_set_init_copy (dest, src2);
Packit Service f629e6
      else
Packit Service f629e6
	re_node_set_init_empty (dest);
Packit Service f629e6
      return REG_NOERROR;
Packit Service f629e6
    }
Packit Service f629e6
  for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;)
Packit Service f629e6
    {
Packit Service f629e6
      if (src1->elems[i1] > src2->elems[i2])
Packit Service f629e6
	{
Packit Service f629e6
	  dest->elems[id++] = src2->elems[i2++];
Packit Service f629e6
	  continue;
Packit Service f629e6
	}
Packit Service f629e6
      if (src1->elems[i1] == src2->elems[i2])
Packit Service f629e6
	++i2;
Packit Service f629e6
      dest->elems[id++] = src1->elems[i1++];
Packit Service f629e6
    }
Packit Service f629e6
  if (i1 < src1->nelem)
Packit Service f629e6
    {
Packit Service f629e6
      memcpy (dest->elems + id, src1->elems + i1,
Packit Service f629e6
	     (src1->nelem - i1) * sizeof (int));
Packit Service f629e6
      id += src1->nelem - i1;
Packit Service f629e6
    }
Packit Service f629e6
  else if (i2 < src2->nelem)
Packit Service f629e6
    {
Packit Service f629e6
      memcpy (dest->elems + id, src2->elems + i2,
Packit Service f629e6
	     (src2->nelem - i2) * sizeof (int));
Packit Service f629e6
      id += src2->nelem - i2;
Packit Service f629e6
    }
Packit Service f629e6
  dest->nelem = id;
Packit Service f629e6
  return REG_NOERROR;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Calculate the union set of the sets DEST and SRC. And store it to
Packit Service f629e6
   DEST. Return value indicate the error code or REG_NOERROR if succeeded.  */
Packit Service f629e6
Packit Service f629e6
static reg_errcode_t
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
re_node_set_merge (re_node_set *dest, const re_node_set *src)
Packit Service f629e6
{
Packit Service f629e6
  int is, id, sbase, delta;
Packit Service f629e6
  if (src == NULL || src->nelem == 0)
Packit Service f629e6
    return REG_NOERROR;
Packit Service f629e6
  if (dest->alloc < 2 * src->nelem + dest->nelem)
Packit Service f629e6
    {
Packit Service f629e6
      int new_alloc = 2 * (src->nelem + dest->alloc);
Packit Service f629e6
      int *new_buffer = re_realloc (dest->elems, int, new_alloc);
Packit Service f629e6
      if (BE (new_buffer == NULL, 0))
Packit Service f629e6
	return REG_ESPACE;
Packit Service f629e6
      dest->elems = new_buffer;
Packit Service f629e6
      dest->alloc = new_alloc;
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  if (BE (dest->nelem == 0, 0))
Packit Service f629e6
    {
Packit Service f629e6
      dest->nelem = src->nelem;
Packit Service f629e6
      memcpy (dest->elems, src->elems, src->nelem * sizeof (int));
Packit Service f629e6
      return REG_NOERROR;
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  /* Copy into the top of DEST the items of SRC that are not
Packit Service f629e6
     found in DEST.  Maybe we could binary search in DEST?  */
Packit Service f629e6
  for (sbase = dest->nelem + 2 * src->nelem,
Packit Service f629e6
       is = src->nelem - 1, id = dest->nelem - 1; is >= 0 && id >= 0; )
Packit Service f629e6
    {
Packit Service f629e6
      if (dest->elems[id] == src->elems[is])
Packit Service f629e6
	is--, id--;
Packit Service f629e6
      else if (dest->elems[id] < src->elems[is])
Packit Service f629e6
	dest->elems[--sbase] = src->elems[is--];
Packit Service f629e6
      else /* if (dest->elems[id] > src->elems[is]) */
Packit Service f629e6
	--id;
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  if (is >= 0)
Packit Service f629e6
    {
Packit Service f629e6
      /* If DEST is exhausted, the remaining items of SRC must be unique.  */
Packit Service f629e6
      sbase -= is + 1;
Packit Service f629e6
      memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (int));
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  id = dest->nelem - 1;
Packit Service f629e6
  is = dest->nelem + 2 * src->nelem - 1;
Packit Service f629e6
  delta = is - sbase + 1;
Packit Service f629e6
  if (delta == 0)
Packit Service f629e6
    return REG_NOERROR;
Packit Service f629e6
Packit Service f629e6
  /* Now copy.  When DELTA becomes zero, the remaining
Packit Service f629e6
     DEST elements are already in place.  */
Packit Service f629e6
  dest->nelem += delta;
Packit Service f629e6
  for (;;)
Packit Service f629e6
    {
Packit Service f629e6
      if (dest->elems[is] > dest->elems[id])
Packit Service f629e6
	{
Packit Service f629e6
	  /* Copy from the top.  */
Packit Service f629e6
	  dest->elems[id + delta--] = dest->elems[is--];
Packit Service f629e6
	  if (delta == 0)
Packit Service f629e6
	    break;
Packit Service f629e6
	}
Packit Service f629e6
      else
Packit Service f629e6
	{
Packit Service f629e6
	  /* Slide from the bottom.  */
Packit Service f629e6
	  dest->elems[id + delta] = dest->elems[id];
Packit Service f629e6
	  if (--id < 0)
Packit Service f629e6
	    {
Packit Service f629e6
	      /* Copy remaining SRC elements.  */
Packit Service f629e6
	      memcpy (dest->elems, dest->elems + sbase,
Packit Service f629e6
		      delta * sizeof (int));
Packit Service f629e6
	      break;
Packit Service f629e6
	    }
Packit Service f629e6
	}
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  return REG_NOERROR;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Insert the new element ELEM to the re_node_set* SET.
Packit Service f629e6
   SET should not already have ELEM.
Packit Service f629e6
   return -1 if an error is occured, return 1 otherwise.  */
Packit Service f629e6
Packit Service f629e6
static int
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
re_node_set_insert (re_node_set *set, int elem)
Packit Service f629e6
{
Packit Service f629e6
  int idx;
Packit Service f629e6
  /* In case the set is empty.  */
Packit Service f629e6
  if (set->alloc == 0)
Packit Service f629e6
    {
Packit Service f629e6
      if (BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1))
Packit Service f629e6
	return 1;
Packit Service f629e6
      else
Packit Service f629e6
	return -1;
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  if (BE (set->nelem, 0) == 0)
Packit Service f629e6
    {
Packit Service f629e6
      /* We already guaranteed above that set->alloc != 0.  */
Packit Service f629e6
      set->elems[0] = elem;
Packit Service f629e6
      ++set->nelem;
Packit Service f629e6
      return 1;
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  /* Realloc if we need.  */
Packit Service f629e6
  if (set->alloc == set->nelem)
Packit Service f629e6
    {
Packit Service f629e6
      int *new_elems;
Packit Service f629e6
      set->alloc = set->alloc * 2;
Packit Service f629e6
      new_elems = re_realloc (set->elems, int, set->alloc);
Packit Service f629e6
      if (BE (new_elems == NULL, 0))
Packit Service f629e6
	return -1;
Packit Service f629e6
      set->elems = new_elems;
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  /* Move the elements which follows the new element.  Test the
Packit Service f629e6
     first element separately to skip a check in the inner loop.  */
Packit Service f629e6
  if (elem < set->elems[0])
Packit Service f629e6
    {
Packit Service f629e6
      idx = 0;
Packit Service f629e6
      for (idx = set->nelem; idx > 0; idx--)
Packit Service f629e6
	set->elems[idx] = set->elems[idx - 1];
Packit Service f629e6
    }
Packit Service f629e6
  else
Packit Service f629e6
    {
Packit Service f629e6
      for (idx = set->nelem; set->elems[idx - 1] > elem; idx--)
Packit Service f629e6
	set->elems[idx] = set->elems[idx - 1];
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  /* Insert the new element.  */
Packit Service f629e6
  set->elems[idx] = elem;
Packit Service f629e6
  ++set->nelem;
Packit Service f629e6
  return 1;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Insert the new element ELEM to the re_node_set* SET.
Packit Service f629e6
   SET should not already have any element greater than or equal to ELEM.
Packit Service f629e6
   Return -1 if an error is occured, return 1 otherwise.  */
Packit Service f629e6
Packit Service f629e6
static int
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
re_node_set_insert_last (re_node_set *set, int elem)
Packit Service f629e6
{
Packit Service f629e6
  /* Realloc if we need.  */
Packit Service f629e6
  if (set->alloc == set->nelem)
Packit Service f629e6
    {
Packit Service f629e6
      int *new_elems;
Packit Service f629e6
      set->alloc = (set->alloc + 1) * 2;
Packit Service f629e6
      new_elems = re_realloc (set->elems, int, set->alloc);
Packit Service f629e6
      if (BE (new_elems == NULL, 0))
Packit Service f629e6
	return -1;
Packit Service f629e6
      set->elems = new_elems;
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  /* Insert the new element.  */
Packit Service f629e6
  set->elems[set->nelem++] = elem;
Packit Service f629e6
  return 1;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Compare two node sets SET1 and SET2.
Packit Service f629e6
   return 1 if SET1 and SET2 are equivalent, return 0 otherwise.  */
Packit Service f629e6
Packit Service f629e6
static int
Packit Service f629e6
__attribute ((pure))
Packit Service f629e6
re_node_set_compare (const re_node_set *set1, const re_node_set *set2)
Packit Service f629e6
{
Packit Service f629e6
  int i;
Packit Service f629e6
  if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem)
Packit Service f629e6
    return 0;
Packit Service f629e6
  for (i = set1->nelem ; --i >= 0 ; )
Packit Service f629e6
    if (set1->elems[i] != set2->elems[i])
Packit Service f629e6
      return 0;
Packit Service f629e6
  return 1;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise.  */
Packit Service f629e6
Packit Service f629e6
static int
Packit Service f629e6
__attribute ((pure))
Packit Service f629e6
re_node_set_contains (const re_node_set *set, int elem)
Packit Service f629e6
{
Packit Service f629e6
  unsigned int idx, right, mid;
Packit Service f629e6
  if (set->nelem <= 0)
Packit Service f629e6
    return 0;
Packit Service f629e6
Packit Service f629e6
  /* Binary search the element.  */
Packit Service f629e6
  idx = 0;
Packit Service f629e6
  right = set->nelem - 1;
Packit Service f629e6
  while (idx < right)
Packit Service f629e6
    {
Packit Service f629e6
      mid = (idx + right) / 2;
Packit Service f629e6
      if (set->elems[mid] < elem)
Packit Service f629e6
	idx = mid + 1;
Packit Service f629e6
      else
Packit Service f629e6
	right = mid;
Packit Service f629e6
    }
Packit Service f629e6
  return set->elems[idx] == elem ? idx + 1 : 0;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
re_node_set_remove_at (re_node_set *set, int idx)
Packit Service f629e6
{
Packit Service f629e6
  if (idx < 0 || idx >= set->nelem)
Packit Service f629e6
    return;
Packit Service f629e6
  --set->nelem;
Packit Service f629e6
  for (; idx < set->nelem; idx++)
Packit Service f629e6
    set->elems[idx] = set->elems[idx + 1];
Packit Service f629e6
}
Packit Service f629e6

Packit Service f629e6
Packit Service f629e6
/* Add the token TOKEN to dfa->nodes, and return the index of the token.
Packit Service f629e6
   Or return -1, if an error will be occured.  */
Packit Service f629e6
Packit Service f629e6
static int
Packit Service f629e6
re_dfa_add_node (re_dfa_t *dfa, re_token_t token)
Packit Service f629e6
{
Packit Service f629e6
  if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0))
Packit Service f629e6
    {
Packit Service f629e6
      size_t new_nodes_alloc = dfa->nodes_alloc * 2;
Packit Service f629e6
      int *new_nexts, *new_indices;
Packit Service f629e6
      re_node_set *new_edests, *new_eclosures;
Packit Service f629e6
      re_token_t *new_nodes;
Packit Service f629e6
Packit Service f629e6
      /* Avoid overflows in realloc.  */
Packit Service f629e6
      const size_t max_object_size = MAX (sizeof (re_token_t),
Packit Service f629e6
					  MAX (sizeof (re_node_set),
Packit Service f629e6
					       sizeof (int)));
Packit Service f629e6
      if (BE (SIZE_MAX / max_object_size < new_nodes_alloc, 0))
Packit Service f629e6
	return -1;
Packit Service f629e6
Packit Service f629e6
      new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc);
Packit Service f629e6
      if (BE (new_nodes == NULL, 0))
Packit Service f629e6
	return -1;
Packit Service f629e6
      dfa->nodes = new_nodes;
Packit Service f629e6
      new_nexts = re_realloc (dfa->nexts, int, new_nodes_alloc);
Packit Service f629e6
      new_indices = re_realloc (dfa->org_indices, int, new_nodes_alloc);
Packit Service f629e6
      new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc);
Packit Service f629e6
      new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc);
Packit Service f629e6
      if (BE (new_nexts == NULL || new_indices == NULL
Packit Service f629e6
	      || new_edests == NULL || new_eclosures == NULL, 0))
Packit Service f629e6
        {
Packit Service f629e6
	   /* if any are not NULL, free them, avoid leaks */
Packit Service f629e6
	   if (new_nexts != NULL)
Packit Service f629e6
              re_free(new_nexts);
Packit Service f629e6
	   if (new_indices != NULL)
Packit Service f629e6
              re_free(new_indices);
Packit Service f629e6
	   if (new_edests != NULL)
Packit Service f629e6
              re_free(new_edests);
Packit Service f629e6
	   if (new_eclosures != NULL)
Packit Service f629e6
              re_free(new_eclosures);
Packit Service f629e6
	   return -1;
Packit Service f629e6
	}
Packit Service f629e6
      dfa->nexts = new_nexts;
Packit Service f629e6
      dfa->org_indices = new_indices;
Packit Service f629e6
      dfa->edests = new_edests;
Packit Service f629e6
      dfa->eclosures = new_eclosures;
Packit Service f629e6
      dfa->nodes_alloc = new_nodes_alloc;
Packit Service f629e6
    }
Packit Service f629e6
  dfa->nodes[dfa->nodes_len] = token;
Packit Service f629e6
  dfa->nodes[dfa->nodes_len].constraint = 0;
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
  dfa->nodes[dfa->nodes_len].accept_mb =
Packit Service f629e6
    (token.type == OP_PERIOD && dfa->mb_cur_max > 1) || token.type == COMPLEX_BRACKET;
Packit Service f629e6
#endif
Packit Service f629e6
  dfa->nexts[dfa->nodes_len] = -1;
Packit Service f629e6
  re_node_set_init_empty (dfa->edests + dfa->nodes_len);
Packit Service f629e6
  re_node_set_init_empty (dfa->eclosures + dfa->nodes_len);
Packit Service f629e6
  return dfa->nodes_len++;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
static inline unsigned int
Packit Service f629e6
calc_state_hash (const re_node_set *nodes, unsigned int context)
Packit Service f629e6
{
Packit Service f629e6
  unsigned int hash = nodes->nelem + context;
Packit Service f629e6
  int i;
Packit Service f629e6
  for (i = 0 ; i < nodes->nelem ; i++)
Packit Service f629e6
    hash += nodes->elems[i];
Packit Service f629e6
  return hash;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Search for the state whose node_set is equivalent to NODES.
Packit Service f629e6
   Return the pointer to the state, if we found it in the DFA.
Packit Service f629e6
   Otherwise create the new one and return it.  In case of an error
Packit Service f629e6
   return NULL and set the error code in ERR.
Packit Service f629e6
   Note: - We assume NULL as the invalid state, then it is possible that
Packit Service f629e6
	   return value is NULL and ERR is REG_NOERROR.
Packit Service f629e6
	 - We never return non-NULL value in case of any errors, it is for
Packit Service f629e6
	   optimization.  */
Packit Service f629e6
Packit Service f629e6
static re_dfastate_t *
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa,
Packit Service f629e6
		  const re_node_set *nodes)
Packit Service f629e6
{
Packit Service f629e6
  unsigned int hash;
Packit Service f629e6
  re_dfastate_t *new_state;
Packit Service f629e6
  struct re_state_table_entry *spot;
Packit Service f629e6
  int i;
Packit Service f629e6
  if (BE (nodes->nelem == 0, 0))
Packit Service f629e6
    {
Packit Service f629e6
      *err = REG_NOERROR;
Packit Service f629e6
      return NULL;
Packit Service f629e6
    }
Packit Service f629e6
  hash = calc_state_hash (nodes, 0);
Packit Service f629e6
  spot = dfa->state_table + (hash & dfa->state_hash_mask);
Packit Service f629e6
Packit Service f629e6
  for (i = 0 ; i < spot->num ; i++)
Packit Service f629e6
    {
Packit Service f629e6
      re_dfastate_t *state = spot->array[i];
Packit Service f629e6
      if (hash != state->hash)
Packit Service f629e6
	continue;
Packit Service f629e6
      if (re_node_set_compare (&state->nodes, nodes))
Packit Service f629e6
	return state;
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  /* There are no appropriate state in the dfa, create the new one.  */
Packit Service f629e6
  new_state = create_ci_newstate (dfa, nodes, hash);
Packit Service f629e6
  if (BE (new_state == NULL, 0))
Packit Service f629e6
    *err = REG_ESPACE;
Packit Service f629e6
Packit Service f629e6
  return new_state;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Search for the state whose node_set is equivalent to NODES and
Packit Service f629e6
   whose context is equivalent to CONTEXT.
Packit Service f629e6
   Return the pointer to the state, if we found it in the DFA.
Packit Service f629e6
   Otherwise create the new one and return it.  In case of an error
Packit Service f629e6
   return NULL and set the error code in ERR.
Packit Service f629e6
   Note: - We assume NULL as the invalid state, then it is possible that
Packit Service f629e6
	   return value is NULL and ERR is REG_NOERROR.
Packit Service f629e6
	 - We never return non-NULL value in case of any errors, it is for
Packit Service f629e6
	   optimization.  */
Packit Service f629e6
Packit Service f629e6
static re_dfastate_t *
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa,
Packit Service f629e6
			  const re_node_set *nodes, unsigned int context)
Packit Service f629e6
{
Packit Service f629e6
  unsigned int hash;
Packit Service f629e6
  re_dfastate_t *new_state;
Packit Service f629e6
  struct re_state_table_entry *spot;
Packit Service f629e6
  int i;
Packit Service f629e6
  if (nodes->nelem == 0)
Packit Service f629e6
    {
Packit Service f629e6
      *err = REG_NOERROR;
Packit Service f629e6
      return NULL;
Packit Service f629e6
    }
Packit Service f629e6
  hash = calc_state_hash (nodes, context);
Packit Service f629e6
  spot = dfa->state_table + (hash & dfa->state_hash_mask);
Packit Service f629e6
Packit Service f629e6
  for (i = 0 ; i < spot->num ; i++)
Packit Service f629e6
    {
Packit Service f629e6
      re_dfastate_t *state = spot->array[i];
Packit Service f629e6
      if (state->hash == hash
Packit Service f629e6
	  && state->context == context
Packit Service f629e6
	  && re_node_set_compare (state->entrance_nodes, nodes))
Packit Service f629e6
	return state;
Packit Service f629e6
    }
Packit Service f629e6
  /* There are no appropriate state in `dfa', create the new one.  */
Packit Service f629e6
  new_state = create_cd_newstate (dfa, nodes, context, hash);
Packit Service f629e6
  if (BE (new_state == NULL, 0))
Packit Service f629e6
    *err = REG_ESPACE;
Packit Service f629e6
Packit Service f629e6
  return new_state;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Finish initialization of the new state NEWSTATE, and using its hash value
Packit Service f629e6
   HASH put in the appropriate bucket of DFA's state table.  Return value
Packit Service f629e6
   indicates the error code if failed.  */
Packit Service f629e6
Packit Service f629e6
static reg_errcode_t
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
register_state (const re_dfa_t *dfa, re_dfastate_t *newstate,
Packit Service f629e6
		unsigned int hash)
Packit Service f629e6
{
Packit Service f629e6
  struct re_state_table_entry *spot;
Packit Service f629e6
  reg_errcode_t err;
Packit Service f629e6
  int i;
Packit Service f629e6
Packit Service f629e6
  newstate->hash = hash;
Packit Service f629e6
  err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem);
Packit Service f629e6
  if (BE (err != REG_NOERROR, 0))
Packit Service f629e6
    return REG_ESPACE;
Packit Service f629e6
  for (i = 0; i < newstate->nodes.nelem; i++)
Packit Service f629e6
    {
Packit Service f629e6
      int elem = newstate->nodes.elems[i];
Packit Service f629e6
      if (!IS_EPSILON_NODE (dfa->nodes[elem].type))
Packit Service f629e6
	if (re_node_set_insert_last (&newstate->non_eps_nodes, elem) < 0)
Packit Service f629e6
	  return REG_ESPACE;
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  spot = dfa->state_table + (hash & dfa->state_hash_mask);
Packit Service f629e6
  if (BE (spot->alloc <= spot->num, 0))
Packit Service f629e6
    {
Packit Service f629e6
      int new_alloc = 2 * spot->num + 2;
Packit Service f629e6
      re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *,
Packit Service f629e6
					      new_alloc);
Packit Service f629e6
      if (BE (new_array == NULL, 0))
Packit Service f629e6
	return REG_ESPACE;
Packit Service f629e6
      spot->array = new_array;
Packit Service f629e6
      spot->alloc = new_alloc;
Packit Service f629e6
    }
Packit Service f629e6
  spot->array[spot->num++] = newstate;
Packit Service f629e6
  return REG_NOERROR;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
static void
Packit Service f629e6
free_state (re_dfastate_t *state)
Packit Service f629e6
{
Packit Service f629e6
  re_node_set_free (&state->non_eps_nodes);
Packit Service f629e6
  re_node_set_free (&state->inveclosure);
Packit Service f629e6
  if (state->entrance_nodes != &state->nodes)
Packit Service f629e6
    {
Packit Service f629e6
      re_node_set_free (state->entrance_nodes);
Packit Service f629e6
      re_free (state->entrance_nodes);
Packit Service f629e6
    }
Packit Service f629e6
  re_node_set_free (&state->nodes);
Packit Service f629e6
  re_free (state->word_trtable);
Packit Service f629e6
  re_free (state->trtable);
Packit Service f629e6
  re_free (state);
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Create the new state which is independent of contexts.
Packit Service f629e6
   Return the new state if succeeded, otherwise return NULL.  */
Packit Service f629e6
Packit Service f629e6
static re_dfastate_t *
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
Packit Service f629e6
		    unsigned int hash)
Packit Service f629e6
{
Packit Service f629e6
  int i;
Packit Service f629e6
  reg_errcode_t err;
Packit Service f629e6
  re_dfastate_t *newstate;
Packit Service f629e6
Packit Service f629e6
  newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
Packit Service f629e6
  if (BE (newstate == NULL, 0))
Packit Service f629e6
    return NULL;
Packit Service f629e6
  err = re_node_set_init_copy (&newstate->nodes, nodes);
Packit Service f629e6
  if (BE (err != REG_NOERROR, 0))
Packit Service f629e6
    {
Packit Service f629e6
      re_free (newstate);
Packit Service f629e6
      return NULL;
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  newstate->entrance_nodes = &newstate->nodes;
Packit Service f629e6
  for (i = 0 ; i < nodes->nelem ; i++)
Packit Service f629e6
    {
Packit Service f629e6
      re_token_t *node = dfa->nodes + nodes->elems[i];
Packit Service f629e6
      re_token_type_t type = node->type;
Packit Service f629e6
      if (type == CHARACTER && !node->constraint)
Packit Service f629e6
	continue;
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
      newstate->accept_mb |= node->accept_mb;
Packit Service f629e6
#endif /* RE_ENABLE_I18N */
Packit Service f629e6
Packit Service f629e6
      /* If the state has the halt node, the state is a halt state.  */
Packit Service f629e6
      if (type == END_OF_RE)
Packit Service f629e6
	newstate->halt = 1;
Packit Service f629e6
      else if (type == OP_BACK_REF)
Packit Service f629e6
	newstate->has_backref = 1;
Packit Service f629e6
      else if (type == ANCHOR || node->constraint)
Packit Service f629e6
	newstate->has_constraint = 1;
Packit Service f629e6
    }
Packit Service f629e6
  err = register_state (dfa, newstate, hash);
Packit Service f629e6
  if (BE (err != REG_NOERROR, 0))
Packit Service f629e6
    {
Packit Service f629e6
      free_state (newstate);
Packit Service f629e6
      newstate = NULL;
Packit Service f629e6
    }
Packit Service f629e6
  return newstate;
Packit Service f629e6
}
Packit Service f629e6
Packit Service f629e6
/* Create the new state which is depend on the context CONTEXT.
Packit Service f629e6
   Return the new state if succeeded, otherwise return NULL.  */
Packit Service f629e6
Packit Service f629e6
static re_dfastate_t *
Packit Service f629e6
__attribute_warn_unused_result__
Packit Service f629e6
create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes,
Packit Service f629e6
		    unsigned int context, unsigned int hash)
Packit Service f629e6
{
Packit Service f629e6
  int i, nctx_nodes = 0;
Packit Service f629e6
  reg_errcode_t err;
Packit Service f629e6
  re_dfastate_t *newstate;
Packit Service f629e6
Packit Service f629e6
  newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);
Packit Service f629e6
  if (BE (newstate == NULL, 0))
Packit Service f629e6
    return NULL;
Packit Service f629e6
  err = re_node_set_init_copy (&newstate->nodes, nodes);
Packit Service f629e6
  if (BE (err != REG_NOERROR, 0))
Packit Service f629e6
    {
Packit Service f629e6
      re_free (newstate);
Packit Service f629e6
      return NULL;
Packit Service f629e6
    }
Packit Service f629e6
Packit Service f629e6
  newstate->context = context;
Packit Service f629e6
  newstate->entrance_nodes = &newstate->nodes;
Packit Service f629e6
Packit Service f629e6
  for (i = 0 ; i < nodes->nelem ; i++)
Packit Service f629e6
    {
Packit Service f629e6
      re_token_t *node = dfa->nodes + nodes->elems[i];
Packit Service f629e6
      re_token_type_t type = node->type;
Packit Service f629e6
      unsigned int constraint = node->constraint;
Packit Service f629e6
Packit Service f629e6
      if (type == CHARACTER && !constraint)
Packit Service f629e6
	continue;
Packit Service f629e6
#ifdef RE_ENABLE_I18N
Packit Service f629e6
      newstate->accept_mb |= node->accept_mb;
Packit Service f629e6
#endif /* RE_ENABLE_I18N */
Packit Service f629e6
Packit Service f629e6
      /* If the state has the halt node, the state is a halt state.  */
Packit Service f629e6
      if (type == END_OF_RE)
Packit Service f629e6
	newstate->halt = 1;
Packit Service f629e6
      else if (type == OP_BACK_REF)
Packit Service f629e6
	newstate->has_backref = 1;
Packit Service f629e6
Packit Service f629e6
      if (constraint)
Packit Service f629e6
	{
Packit Service f629e6
	  if (newstate->entrance_nodes == &newstate->nodes)
Packit Service f629e6
	    {
Packit Service f629e6
	      newstate->entrance_nodes = re_malloc (re_node_set, 1);
Packit Service f629e6
	      if (BE (newstate->entrance_nodes == NULL, 0))
Packit Service f629e6
		{
Packit Service f629e6
		  free_state (newstate);
Packit Service f629e6
		  return NULL;
Packit Service f629e6
		}
Packit Service f629e6
	      if (re_node_set_init_copy (newstate->entrance_nodes, nodes)
Packit Service f629e6
		  != REG_NOERROR)
Packit Service f629e6
		return NULL;
Packit Service f629e6
	      nctx_nodes = 0;
Packit Service f629e6
	      newstate->has_constraint = 1;
Packit Service f629e6
	    }
Packit Service f629e6
Packit Service f629e6
	  if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context))
Packit Service f629e6
	    {
Packit Service f629e6
	      re_node_set_remove_at (&newstate->nodes, i - nctx_nodes);
Packit Service f629e6
	      ++nctx_nodes;
Packit Service f629e6
	    }
Packit Service f629e6
	}
Packit Service f629e6
    }
Packit Service f629e6
  err = register_state (dfa, newstate, hash);
Packit Service f629e6
  if (BE (err != REG_NOERROR, 0))
Packit Service f629e6
    {
Packit Service f629e6
      free_state (newstate);
Packit Service f629e6
      newstate = NULL;
Packit Service f629e6
    }
Packit Service f629e6
  return  newstate;
Packit Service f629e6
}