Blame deps/regex/regex_internal.c

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