Blame lib/regex_internal.c

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