if (MB_CUR_MAX > 1)
if (dfa->mb_cur_max > 1)
parse_bracket_exp (regexp, dfa, token, syntax, err)     re_string_t *regexp;     re_dfa_t *dfa;     re_token_t *token;     reg_syntax_t syntax;     reg_errcode_t *err;{#ifdef _LIBC  const unsigned char *collseqmb;  const char *collseqwc;  uint32_t nrules;  int32_t table_size;  const int32_t *symb_table;  const unsigned char *extra;  /* Local function for parse_bracket_exp used in _LIBC environement.     Seek the collating symbol entry correspondings to NAME.     Return the index of the symbol in the SYMB_TABLE.  */  static inline int32_t  __attribute ((always_inline))  seek_collating_symbol_entry (name, name_len)	 const unsigned char *name;	 size_t name_len;    {      int32_t hash = elem_hash ((const char *) name, name_len);      int32_t elem = hash % table_size;      int32_t second = hash % (table_size - 2);      while (symb_table[2 * elem] != 0)	{	  /* First compare the hashing value.  */	  if (symb_table[2 * elem] == hash	      /* Compare the length of the name.  */	      && name_len == extra[symb_table[2 * elem + 1]]	      /* Compare the name.  */	      && memcmp (name, &extra[symb_table[2 * elem + 1] + 1],			 name_len) == 0)	    {	      /* Yep, this is the entry.  */	      break;	    }	  /* Next entry.  */	  elem += second;	}      return elem;    }  /* Local function for parse_bracket_exp used in _LIBC environement.     Look up the collation sequence value of BR_ELEM.     Return the value if succeeded, UINT_MAX otherwise.  */  static inline unsigned int  __attribute ((always_inline))  lookup_collation_sequence_value (br_elem)	 bracket_elem_t *br_elem;    {      if (br_elem->type == SB_CHAR)	{	  /*	  if (MB_CUR_MAX == 1)	  */	  if (nrules == 0)	    return collseqmb[br_elem->opr.ch];	  else	    {	      wint_t wc = __btowc (br_elem->opr.ch);	      return __collseq_table_lookup (collseqwc, wc);	    }	}      else if (br_elem->type == MB_CHAR)	{	  return __collseq_table_lookup (collseqwc, br_elem->opr.wch);	}      else if (br_elem->type == COLL_SYM)	{	  size_t sym_name_len = strlen ((char *) br_elem->opr.name);	  if (nrules != 0)	    {	      int32_t elem, idx;	      elem = seek_collating_symbol_entry (br_elem->opr.name,						  sym_name_len);	      if (symb_table[2 * elem] != 0)		{		  /* We found the entry.  */		  idx = symb_table[2 * elem + 1];		  /* Skip the name of collating element name.  */		  idx += 1 + extra[idx];		  /* Skip the byte sequence of the collating element.  */		  idx += 1 + extra[idx];		  /* Adjust for the alignment.  */		  idx = (idx + 3) & ~3;		  /* Skip the multibyte collation sequence value.  */		  idx += sizeof (unsigned int);		  /* Skip the wide char sequence of the collating element.  */		  idx += sizeof (unsigned int) *		    (1 + *(unsigned int *) (extra + idx));		  /* Return the collation sequence value.  */		  return *(unsigned int *) (extra + idx);		}	      else if (symb_table[2 * elem] == 0 && sym_name_len == 1)		{		  /* No valid character.  Match it as a single byte		     character.  */		  return collseqmb[br_elem->opr.name[0]];		}	    }	  else if (sym_name_len == 1)	    return collseqmb[br_elem->opr.name[0]];	}      return UINT_MAX;    }  /* Local function for parse_bracket_exp used in _LIBC environement.     Build the range expression which starts from START_ELEM, and ends     at END_ELEM.  The result are written to MBCSET and SBCSET.     RANGE_ALLOC is the allocated size of mbcset->range_starts, and     mbcset->range_ends, is a pointer argument sinse we may     update it.  */  static inline reg_errcode_t  __attribute ((always_inline))# ifdef RE_ENABLE_I18N  build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem)	 re_charset_t *mbcset;	 int *range_alloc;# else /* not RE_ENABLE_I18N */  build_range_exp (sbcset, start_elem, end_elem)# endif /* not RE_ENABLE_I18N */	 re_bitset_ptr_t sbcset;	 bracket_elem_t *start_elem, *end_elem;    {      unsigned int ch;      uint32_t start_collseq;      uint32_t end_collseq;# ifdef RE_ENABLE_I18N      /* Check the space of the arrays.  */      if (*range_alloc == mbcset->nranges)	{	  /* There are not enough space, need realloc.  */	  uint32_t *new_array_start;	  uint32_t *new_array_end;	  int new_nranges;	  /* +1 in case of mbcset->nranges is 0.  */	  new_nranges = 2 * mbcset->nranges + 1;	  /* Use realloc since mbcset->range_starts and mbcset->range_ends	     are NULL if *range_alloc == 0.  */	  new_array_start = re_realloc (mbcset->range_starts, uint32_t,					new_nranges);	  new_array_end = re_realloc (mbcset->range_ends, uint32_t,				      new_nranges);	  if (BE (new_array_start == NULL || new_array_end == NULL, 0))	    return REG_ESPACE;	  mbcset->range_starts = new_array_start;	  mbcset->range_ends = new_array_end;	  *range_alloc = new_nranges;	}# endif /* RE_ENABLE_I18N */      /* Equivalence Classes and Character Classes can't be a range	 start/end.  */      if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS	      || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS,	      0))	return REG_ERANGE;      start_collseq = lookup_collation_sequence_value (start_elem);      end_collseq = lookup_collation_sequence_value (end_elem);      /* Check start/end collation sequence values.  */      if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0))	return REG_ECOLLATE;      if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0))	return REG_ERANGE;# ifdef RE_ENABLE_I18N      /* Got valid collation sequence values, add them as a new entry.  */      mbcset->range_starts[mbcset->nranges] = start_collseq;      mbcset->range_ends[mbcset->nranges++] = end_collseq;# endif /* RE_ENABLE_I18N */      /* Build the table for single byte characters.  */      for (ch = 0; ch <= SBC_MAX; ch++)	{	  uint32_t ch_collseq;	  /*	  if (MB_CUR_MAX == 1)	  */	  if (nrules == 0)	    ch_collseq = collseqmb[ch];	  else	    ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch));	  if (start_collseq <= ch_collseq && ch_collseq <= end_collseq)	    bitset_set (sbcset, ch);	}      return REG_NOERROR;    }  /* Local function for parse_bracket_exp used in _LIBC environement.     Build the collating element which is represented by NAME.     The result are written to MBCSET and SBCSET.     COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a     pointer argument sinse we may update it.  */  static inline reg_errcode_t  __attribute ((always_inline))# ifdef RE_ENABLE_I18N  build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name)	 re_charset_t *mbcset;	 int *coll_sym_alloc;# else /* not RE_ENABLE_I18N */  build_collating_symbol (sbcset, name)# endif /* not RE_ENABLE_I18N */	 re_bitset_ptr_t sbcset;	 const unsigned char *name;    {      int32_t elem, idx;      size_t name_len = strlen ((const char *) name);      if (nrules != 0)	{	  elem = seek_collating_symbol_entry (name, name_len);	  if (symb_table[2 * elem] != 0)	    {	      /* We found the entry.  */	      idx = symb_table[2 * elem + 1];	      /* Skip the name of collating element name.  */	      idx += 1 + extra[idx];	    }	  else if (symb_table[2 * elem] == 0 && name_len == 1)	    {	      /* No valid character, treat it as a normal		 character.  */	      bitset_set (sbcset, name[0]);	      return REG_NOERROR;	    }	  else	    return REG_ECOLLATE;# ifdef RE_ENABLE_I18N	  /* Got valid collation sequence, add it as a new entry.  */	  /* Check the space of the arrays.  */	  if (*coll_sym_alloc == mbcset->ncoll_syms)	    {	      /* Not enough, realloc it.  */	      /* +1 in case of mbcset->ncoll_syms is 0.  */	      *coll_sym_alloc = 2 * mbcset->ncoll_syms + 1;	      /* Use realloc since mbcset->coll_syms is NULL		 if *alloc == 0.  */	      mbcset->coll_syms = re_realloc (mbcset->coll_syms, int32_t,					      *coll_sym_alloc);	      if (BE (mbcset->coll_syms == NULL, 0))		return REG_ESPACE;	    }	  mbcset->coll_syms[mbcset->ncoll_syms++] = idx;# endif /* RE_ENABLE_I18N */	  return REG_NOERROR;	}      else	{	  if (BE (name_len != 1, 0))	    return REG_ECOLLATE;	  else	    {	      bitset_set (sbcset, name[0]);	      return REG_NOERROR;	    }	}    }#endif  re_token_t br_token;  re_bitset_ptr_t sbcset;#ifdef RE_ENABLE_I18N  re_charset_t *mbcset;  int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0;  int equiv_class_alloc = 0, char_class_alloc = 0;#else /* not RE_ENABLE_I18N */  int non_match = 0;#endif /* not RE_ENABLE_I18N */  bin_tree_t *work_tree;  int token_len, new_idx;#ifdef _LIBC  collseqmb = (const unsigned char *)    _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);  nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);  if (nrules)    {      /*      if (MB_CUR_MAX > 1)      */	collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);      table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB);      symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE,						  _NL_COLLATE_SYMB_TABLEMB);      extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,						   _NL_COLLATE_SYMB_EXTRAMB);    }#endif  sbcset = (re_bitset_ptr_t) calloc (sizeof (unsigned int), BITSET_UINTS);#ifdef RE_ENABLE_I18N  mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);#endif /* RE_ENABLE_I18N */#ifdef RE_ENABLE_I18N  if (BE (sbcset == NULL || mbcset == NULL, 0))#else  if (BE (sbcset == NULL, 0))#endif /* RE_ENABLE_I18N */    {      *err = REG_ESPACE;      return NULL;    }  token_len = peek_token_bracket (token, regexp, syntax);  if (BE (token->type == END_OF_RE, 0))    {      *err = REG_BADPAT;      goto parse_bracket_exp_free_return;    }  if (token->type == OP_NON_MATCH_LIST)    {#ifdef RE_ENABLE_I18N      int i;      mbcset->non_match = 1;#else /* not RE_ENABLE_I18N */      non_match = 1;#endif /* not RE_ENABLE_I18N */      if (syntax & RE_HAT_LISTS_NOT_NEWLINE)	bitset_set (sbcset, '\0');      re_string_skip_bytes (regexp, token_len); /* Skip a token.  */      token_len = peek_token_bracket (token, regexp, syntax);      if (BE (token->type == END_OF_RE, 0))	{	  *err = REG_BADPAT;	  goto parse_bracket_exp_free_return;	}#ifdef RE_ENABLE_I18N      if (MB_CUR_MAX > 1)	for (i = 0; i < SBC_MAX; ++i)	  if (__btowc (i) == WEOF)	    bitset_set (sbcset, i);#endif /* RE_ENABLE_I18N */    }  /* We treat the first ']' as a normal character.  */  if (token->type == OP_CLOSE_BRACKET)    token->type = CHARACTER;  while (1)    {      bracket_elem_t start_elem, end_elem;      unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE];      unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE];      reg_errcode_t ret;      int token_len2 = 0, is_range_exp = 0;      re_token_t token2;      start_elem.opr.name = start_name_buf;      ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa,				   syntax);      if (BE (ret != REG_NOERROR, 0))	{	  *err = ret;	  goto parse_bracket_exp_free_return;	}      token_len = peek_token_bracket (token, regexp, syntax);      if (BE (token->type == END_OF_RE, 0))	{	  *err = REG_BADPAT;	  goto parse_bracket_exp_free_return;	}      if (token->type == OP_CHARSET_RANGE)	{	  re_string_skip_bytes (regexp, token_len); /* Skip '-'.  */	  token_len2 = peek_token_bracket (&token2, regexp, syntax);	  if (BE (token->type == END_OF_RE, 0))	    {	      *err = REG_BADPAT;	      goto parse_bracket_exp_free_return;	    }	  if (token2.type == OP_CLOSE_BRACKET)	    {	      /* We treat the last '-' as a normal character.  */	      re_string_skip_bytes (regexp, -token_len);	      token->type = CHARACTER;	    }	  else	    is_range_exp = 1;	}      if (is_range_exp == 1)	{	  end_elem.opr.name = end_name_buf;	  ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2,				       dfa, syntax);	  if (BE (ret != REG_NOERROR, 0))	    {	      *err = ret;	      goto parse_bracket_exp_free_return;	    }	  token_len = peek_token_bracket (token, regexp, syntax);	  if (BE (token->type == END_OF_RE, 0))	    {	      *err = REG_BADPAT;	      goto parse_bracket_exp_free_return;	    }	  *err = build_range_exp (sbcset,#ifdef RE_ENABLE_I18N				  mbcset, &range_alloc,#endif /* RE_ENABLE_I18N */				  &start_elem, &end_elem);	  if (BE (*err != REG_NOERROR, 0))	    goto parse_bracket_exp_free_return;	}      else	{	  switch (start_elem.type)	    {	    case SB_CHAR:	      bitset_set (sbcset, start_elem.opr.ch);	      break;#ifdef RE_ENABLE_I18N	    case MB_CHAR:	      /* Check whether the array has enough space.  */	      if (mbchar_alloc == mbcset->nmbchars)		{		  /* Not enough, realloc it.  */		  /* +1 in case of mbcset->nmbchars is 0.  */		  mbchar_alloc = 2 * mbcset->nmbchars + 1;		  /* Use realloc since array is NULL if *alloc == 0.  */		  mbcset->mbchars = re_realloc (mbcset->mbchars, wchar_t,						mbchar_alloc);		  if (BE (mbcset->mbchars == NULL, 0))		    goto parse_bracket_exp_espace;		}	      mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch;	      break;#endif /* RE_ENABLE_I18N */	    case EQUIV_CLASS:	      *err = build_equiv_class (sbcset,#ifdef RE_ENABLE_I18N					mbcset, &equiv_class_alloc,#endif /* RE_ENABLE_I18N */					start_elem.opr.name);	      if (BE (*err != REG_NOERROR, 0))		goto parse_bracket_exp_free_return;	      break;	    case COLL_SYM:	      *err = build_collating_symbol (sbcset,#ifdef RE_ENABLE_I18N					     mbcset, &coll_sym_alloc,#endif /* RE_ENABLE_I18N */					     start_elem.opr.name);	      if (BE (*err != REG_NOERROR, 0))		goto parse_bracket_exp_free_return;	      break;	    case CHAR_CLASS:	      *err = build_charclass (regexp->trans, sbcset,#ifdef RE_ENABLE_I18N				      mbcset, &char_class_alloc,#endif /* RE_ENABLE_I18N */				      start_elem.opr.name, syntax);	      if (BE (*err != REG_NOERROR, 0))	       goto parse_bracket_exp_free_return;	      break;	    default:	      assert (0);	      break;	    }	}      if (token->type == OP_CLOSE_BRACKET)	break;    }  re_string_skip_bytes (regexp, token_len); /* Skip a token.  */  /* If it is non-matching list.  */#ifdef RE_ENABLE_I18N  if (mbcset->non_match)#else /* not RE_ENABLE_I18N */  if (non_match)#endif /* not RE_ENABLE_I18N */    bitset_not (sbcset);  /* Build a tree for simple bracket.  */  br_token.type = SIMPLE_BRACKET;  br_token.opr.sbcset = sbcset;  new_idx = re_dfa_add_node (dfa, br_token, 0);  work_tree = create_tree (NULL, NULL, 0, new_idx);  if (BE (new_idx == -1 || work_tree == NULL, 0))    goto parse_bracket_exp_espace;#ifdef RE_ENABLE_I18N  if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes      || mbcset->nranges || (MB_CUR_MAX > 1 && (mbcset->nchar_classes						|| mbcset->non_match)))    {      re_token_t alt_token;      bin_tree_t *mbc_tree;      /* Build a tree for complex bracket.  */      br_token.type = COMPLEX_BRACKET;      br_token.opr.mbcset = mbcset;      dfa->has_mb_node = 1;      new_idx = re_dfa_add_node (dfa, br_token, 0);      mbc_tree = create_tree (NULL, NULL, 0, new_idx);      if (BE (new_idx == -1 || mbc_tree == NULL, 0))	goto parse_bracket_exp_espace;      /* Then join them by ALT node.  */      dfa->has_plural_match = 1;      alt_token.type = OP_ALT;      new_idx = re_dfa_add_node (dfa, alt_token, 0);      work_tree = create_tree (work_tree, mbc_tree, 0, new_idx);      if (BE (new_idx != -1 && mbc_tree != NULL, 1))	return work_tree;    }  else    {      free_charset (mbcset);      return work_tree;    }#else /* not RE_ENABLE_I18N */  return work_tree;#endif /* not RE_ENABLE_I18N */ parse_bracket_exp_espace:  *err = REG_ESPACE; parse_bracket_exp_free_return:  re_free (sbcset);#ifdef RE_ENABLE_I18N  free_charset (mbcset);#endif /* RE_ENABLE_I18N */  return NULL;}