Blame lib/regex_internal.c

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