const re_dfastate_t *init_state,
char *fastmap);
static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len);
-#ifdef RE_ENABLE_I18N
static void free_charset (re_charset_t *cset);
-#endif /* RE_ENABLE_I18N */
static void free_workarea_compile (regex_t *preg);
static reg_errcode_t create_initial_state (re_dfa_t *dfa);
-#ifdef RE_ENABLE_I18N
static void optimize_utf8 (re_dfa_t *dfa);
-#endif
static reg_errcode_t analyze (regex_t *preg);
static reg_errcode_t preorder (bin_tree_t *root,
reg_errcode_t (fn (void *, bin_tree_t *)),
static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem,
re_string_t *regexp,
re_token_t *token);
-#ifdef RE_ENABLE_I18N
static reg_errcode_t build_equiv_class (bitset_t sbcset,
re_charset_t *mbcset,
Idx *equiv_class_alloc,
Idx *char_class_alloc,
const char *class_name,
reg_syntax_t syntax);
-#else /* not RE_ENABLE_I18N */
-static reg_errcode_t build_equiv_class (bitset_t sbcset,
- const unsigned char *name);
-static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans,
- bitset_t sbcset,
- const char *class_name,
- reg_syntax_t syntax);
-#endif /* not RE_ENABLE_I18N */
static bin_tree_t *build_charclass_op (re_dfa_t *dfa,
RE_TRANSLATE_TYPE trans,
const char *class_name,
if (type == CHARACTER)
{
re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c);
-#ifdef RE_ENABLE_I18N
if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
{
unsigned char buf[MB_LEN_MAX];
!= (size_t) -1))
re_set_fastmap (fastmap, false, buf[0]);
}
-#endif
}
else if (type == SIMPLE_BRACKET)
{
re_set_fastmap (fastmap, icase, ch);
}
}
-#ifdef RE_ENABLE_I18N
else if (type == COMPLEX_BRACKET)
{
re_charset_t *cset = dfa->nodes[node].opr.mbcset;
Idx i;
-# ifdef _LIBC
+#ifdef _LIBC
/* See if we have to try all bytes which start multiple collation
elements.
e.g. In da_DK, we want to catch 'a' since "aa" is a valid
if (table[i] < 0)
re_set_fastmap (fastmap, icase, i);
}
-# endif /* _LIBC */
+#endif /* _LIBC */
/* See if we have to start the match at all multibyte characters,
i.e. where we would not find an invalid sequence. This only
sets, the SIMPLE_BRACKET again suffices. */
if (dfa->mb_cur_max > 1
&& (cset->nchar_classes || cset->non_match || cset->nranges
-# ifdef _LIBC
+#ifdef _LIBC
|| cset->nequiv_classes
-# endif /* _LIBC */
+#endif /* _LIBC */
))
{
unsigned char c = 0;
}
}
}
-#endif /* RE_ENABLE_I18N */
- else if (type == OP_PERIOD
-#ifdef RE_ENABLE_I18N
- || type == OP_UTF8_PERIOD
-#endif /* RE_ENABLE_I18N */
- || type == END_OF_RE)
+ else if (type == OP_PERIOD || type == OP_UTF8_PERIOD || type == END_OF_RE)
{
memset (fastmap, '\1', sizeof (char) * SBC_MAX);
if (type == END_OF_RE)
weak_alias (__regerror, regerror)
-#ifdef RE_ENABLE_I18N
/* This static array is used for the map to single-byte characters when
UTF-8 is used. Otherwise we would allocate memory just to initialize
it the same all the time. UTF-8 is the preferred encoding so this is
static const bitset_t utf8_sb_map =
{
/* Set the first 128 bits. */
-# if (defined __GNUC__ || __clang_major__ >= 4) && !defined __STRICT_ANSI__
+#if (defined __GNUC__ || __clang_major__ >= 4) && !defined __STRICT_ANSI__
[0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX
-# else
-# if 4 * BITSET_WORD_BITS < ASCII_CHARS
-# error "bitset_word_t is narrower than 32 bits"
-# elif 3 * BITSET_WORD_BITS < ASCII_CHARS
+#else
+# if 4 * BITSET_WORD_BITS < ASCII_CHARS
+# error "bitset_word_t is narrower than 32 bits"
+# elif 3 * BITSET_WORD_BITS < ASCII_CHARS
BITSET_WORD_MAX, BITSET_WORD_MAX, BITSET_WORD_MAX,
-# elif 2 * BITSET_WORD_BITS < ASCII_CHARS
+# elif 2 * BITSET_WORD_BITS < ASCII_CHARS
BITSET_WORD_MAX, BITSET_WORD_MAX,
-# elif 1 * BITSET_WORD_BITS < ASCII_CHARS
+# elif 1 * BITSET_WORD_BITS < ASCII_CHARS
BITSET_WORD_MAX,
-# endif
+# endif
(BITSET_WORD_MAX
>> (SBC_MAX % BITSET_WORD_BITS == 0
? 0
: BITSET_WORD_BITS - SBC_MAX % BITSET_WORD_BITS))
-# endif
-};
#endif
+};
static void
re_free (entry->array);
}
re_free (dfa->state_table);
-#ifdef RE_ENABLE_I18N
if (dfa->sb_char != utf8_sb_map)
re_free (dfa->sb_char);
-#endif
re_free (dfa->subexp_map);
#ifdef DEBUG
re_free (dfa->re_str);
if (__glibc_unlikely (err != REG_NOERROR))
goto re_compile_internal_free_return;
-#ifdef RE_ENABLE_I18N
/* If possible, do searching in single byte encoding to speed things up. */
if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL)
optimize_utf8 (dfa);
-#endif
/* Then create the initial state of the dfa. */
err = create_initial_state (dfa);
#ifndef _LIBC
const char *codeset_name;
#endif
-#ifdef RE_ENABLE_I18N
size_t max_i18n_object_size = MAX (sizeof (wchar_t), sizeof (wctype_t));
-#else
- size_t max_i18n_object_size = 0;
-#endif
size_t max_object_size =
MAX (sizeof (struct re_state_table_entry),
MAX (sizeof (re_token_t),
dfa->map_notascii = 0;
#endif
-#ifdef RE_ENABLE_I18N
if (dfa->mb_cur_max > 1)
{
if (dfa->is_utf8)
wint_t wch = __btowc (ch);
if (wch != WEOF)
dfa->sb_char[i] |= (bitset_word_t) 1 << j;
-# ifndef _LIBC
+#ifndef _LIBC
if (isascii (ch) && wch != ch)
dfa->map_notascii = 1;
-# endif
+#endif
}
}
}
-#endif
if (__glibc_unlikely (dfa->nodes == NULL || dfa->state_table == NULL))
return REG_ESPACE;
return REG_NOERROR;
}
\f
-#ifdef RE_ENABLE_I18N
/* If it is possible to do searching in single byte encoding instead of UTF-8
to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change
DFA nodes where needed. */
dfa->is_utf8 = 0;
dfa->has_mb_node = dfa->nbackref > 0 || has_period;
}
-#endif
\f
/* Analyze the structure tree, and calculate "first", "next", "edest",
"eclosure", and "inveclosure". */
token->opr.c = c;
token->word_char = 0;
-#ifdef RE_ENABLE_I18N
token->mb_partial = 0;
if (input->mb_cur_max > 1
&& !re_string_first_byte (input, re_string_cur_idx (input)))
token->mb_partial = 1;
return 1;
}
-#endif
if (c == '\\')
{
unsigned char c2;
c2 = re_string_peek_byte_case (input, 1);
token->opr.c = c2;
token->type = CHARACTER;
-#ifdef RE_ENABLE_I18N
if (input->mb_cur_max > 1)
{
wint_t wc = re_string_wchar_at (input,
token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
}
else
-#endif
token->word_char = IS_WORD_CHAR (c2) != 0;
switch (c2)
}
token->type = CHARACTER;
-#ifdef RE_ENABLE_I18N
if (input->mb_cur_max > 1)
{
wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input));
token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
}
else
-#endif
token->word_char = IS_WORD_CHAR (token->opr.c);
switch (c)
c = re_string_peek_byte (input, 0);
token->opr.c = c;
-#ifdef RE_ENABLE_I18N
if (input->mb_cur_max > 1
&& !re_string_first_byte (input, re_string_cur_idx (input)))
{
token->type = CHARACTER;
return 1;
}
-#endif /* RE_ENABLE_I18N */
if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS)
&& re_string_cur_idx (input) + 1 < re_string_length (input))
*err = REG_ESPACE;
return NULL;
}
-#ifdef RE_ENABLE_I18N
if (dfa->mb_cur_max > 1)
{
while (!re_string_eoi (regexp)
}
}
}
-#endif
break;
case OP_OPEN_SUBEXP:
#ifndef _LIBC
-# ifdef RE_ENABLE_I18N
/* Convert the byte B to the corresponding wide character. In a
unibyte locale, treat B as itself. In a multibyte locale, return
WEOF if B is an encoding error. */
{
return mbcset == NULL ? b : __btowc (b);
}
-# endif
/* Local function for parse_bracket_exp only used in case of NOT _LIBC.
Build the range expression which starts from START_ELEM, and ends
update it. */
static reg_errcode_t
-# ifdef RE_ENABLE_I18N
build_range_exp (const reg_syntax_t syntax,
bitset_t sbcset,
re_charset_t *mbcset,
Idx *range_alloc,
const bracket_elem_t *start_elem,
const bracket_elem_t *end_elem)
-# else /* not RE_ENABLE_I18N */
-build_range_exp (const reg_syntax_t syntax,
- bitset_t sbcset,
- const bracket_elem_t *start_elem,
- const bracket_elem_t *end_elem)
-# endif /* not RE_ENABLE_I18N */
{
- unsigned int start_ch, end_ch;
/* Equivalence Classes and Character Classes can't be a range start/end. */
if (__glibc_unlikely (start_elem->type == EQUIV_CLASS
|| start_elem->type == CHAR_CLASS
&& strlen ((char *) end_elem->opr.name) > 1)))
return REG_ECOLLATE;
-# ifdef RE_ENABLE_I18N
- {
- wchar_t wc;
- wint_t start_wc;
- wint_t end_wc;
-
+ unsigned int
start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch
: ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
: 0));
+ unsigned int
end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch
: ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
: 0));
+ wint_t
start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM)
? parse_byte (start_ch, mbcset) : start_elem->opr.wch);
+ wint_t
end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM)
? parse_byte (end_ch, mbcset) : end_elem->opr.wch);
- if (start_wc == WEOF || end_wc == WEOF)
- return REG_ECOLLATE;
- else if (__glibc_unlikely ((syntax & RE_NO_EMPTY_RANGES)
- && start_wc > end_wc))
- return REG_ERANGE;
-
- /* Got valid collation sequence values, add them as a new entry.
- However, for !_LIBC we have no collation elements: if the
- character set is single byte, the single byte character set
- that we build below suffices. parse_bracket_exp passes
- no MBCSET if dfa->mb_cur_max == 1. */
- if (mbcset)
- {
- /* Check the space of the arrays. */
- if (__glibc_unlikely (*range_alloc == mbcset->nranges))
- {
- /* There is not enough space, need realloc. */
- wchar_t *new_array_start, *new_array_end;
- Idx 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, wchar_t,
- new_nranges);
- new_array_end = re_realloc (mbcset->range_ends, wchar_t,
- new_nranges);
-
- if (__glibc_unlikely (new_array_start == NULL
- || new_array_end == NULL))
- {
- re_free (new_array_start);
- re_free (new_array_end);
- return REG_ESPACE;
- }
- mbcset->range_starts = new_array_start;
- mbcset->range_ends = new_array_end;
- *range_alloc = new_nranges;
- }
+ if (start_wc == WEOF || end_wc == WEOF)
+ return REG_ECOLLATE;
+ else if (__glibc_unlikely ((syntax & RE_NO_EMPTY_RANGES)
+ && start_wc > end_wc))
+ return REG_ERANGE;
- mbcset->range_starts[mbcset->nranges] = start_wc;
- mbcset->range_ends[mbcset->nranges++] = end_wc;
- }
+ /* Got valid collation sequence values, add them as a new entry.
+ However, for !_LIBC we have no collation elements: if the
+ character set is single byte, the single byte character set
+ that we build below suffices. parse_bracket_exp passes
+ no MBCSET if dfa->mb_cur_max == 1. */
+ if (mbcset)
+ {
+ /* Check the space of the arrays. */
+ if (__glibc_unlikely (*range_alloc == mbcset->nranges))
+ {
+ /* There is not enough space, need realloc. */
+ wchar_t *new_array_start, *new_array_end;
+ Idx 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, wchar_t,
+ new_nranges);
+ new_array_end = re_realloc (mbcset->range_ends, wchar_t,
+ new_nranges);
+
+ if (__glibc_unlikely (new_array_start == NULL
+ || new_array_end == NULL))
+ {
+ re_free (new_array_start);
+ re_free (new_array_end);
+ return REG_ESPACE;
+ }
+
+ mbcset->range_starts = new_array_start;
+ mbcset->range_ends = new_array_end;
+ *range_alloc = new_nranges;
+ }
+
+ mbcset->range_starts[mbcset->nranges] = start_wc;
+ mbcset->range_ends[mbcset->nranges++] = end_wc;
+ }
+
+ /* Build the table for single byte characters. */
+ for (wchar_t wc = 0; wc < SBC_MAX; ++wc)
+ {
+ if (start_wc <= wc && wc <= end_wc)
+ bitset_set (sbcset, wc);
+ }
- /* Build the table for single byte characters. */
- for (wc = 0; wc < SBC_MAX; ++wc)
- {
- if (start_wc <= wc && wc <= end_wc)
- bitset_set (sbcset, wc);
- }
- }
-# else /* not RE_ENABLE_I18N */
- {
- unsigned int ch;
- start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch
- : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
- : 0));
- end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch
- : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
- : 0));
- if (start_ch > end_ch)
- return REG_ERANGE;
- /* Build the table for single byte characters. */
- for (ch = 0; ch < SBC_MAX; ++ch)
- if (start_ch <= ch && ch <= end_ch)
- bitset_set (sbcset, ch);
- }
-# endif /* not RE_ENABLE_I18N */
return REG_NOERROR;
}
#endif /* not _LIBC */
pointer argument since we may update it. */
static reg_errcode_t
-# ifdef RE_ENABLE_I18N
build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset,
Idx *coll_sym_alloc, const unsigned char *name)
-# else /* not RE_ENABLE_I18N */
-build_collating_symbol (bitset_t sbcset, const unsigned char *name)
-# endif /* not RE_ENABLE_I18N */
{
size_t name_len = strlen ((const char *) name);
if (__glibc_unlikely (name_len != 1))
re_token_t br_token;
re_bitset_ptr_t sbcset;
-#ifdef RE_ENABLE_I18N
re_charset_t *mbcset;
Idx coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0;
Idx equiv_class_alloc = 0, char_class_alloc = 0;
-#endif /* not RE_ENABLE_I18N */
bool non_match = false;
bin_tree_t *work_tree;
int token_len;
}
#endif
sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
-#ifdef RE_ENABLE_I18N
mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
-#endif /* RE_ENABLE_I18N */
-#ifdef RE_ENABLE_I18N
if (__glibc_unlikely (sbcset == NULL || mbcset == NULL))
-#else
- if (__glibc_unlikely (sbcset == NULL))
-#endif /* RE_ENABLE_I18N */
{
re_free (sbcset);
-#ifdef RE_ENABLE_I18N
re_free (mbcset);
-#endif
*err = REG_ESPACE;
return NULL;
}
}
if (token->type == OP_NON_MATCH_LIST)
{
-#ifdef RE_ENABLE_I18N
mbcset->non_match = 1;
-#endif /* not RE_ENABLE_I18N */
non_match = true;
if (syntax & RE_HAT_LISTS_NOT_NEWLINE)
bitset_set (sbcset, '\n');
*err = build_range_exp (sbcset, mbcset, &range_alloc,
&start_elem, &end_elem);
#else
-# ifdef RE_ENABLE_I18N
*err = build_range_exp (syntax, sbcset,
dfa->mb_cur_max > 1 ? mbcset : NULL,
&range_alloc, &start_elem, &end_elem);
-# else
- *err = build_range_exp (syntax, sbcset, &start_elem, &end_elem);
-# endif
-#endif /* RE_ENABLE_I18N */
+#endif
if (__glibc_unlikely (*err != REG_NOERROR))
goto parse_bracket_exp_free_return;
}
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 (__glibc_unlikely (mbchar_alloc == mbcset->nmbchars))
}
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 (__glibc_unlikely (*err != REG_NOERROR))
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 (__glibc_unlikely (*err != REG_NOERROR))
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 */
(const char *) start_elem.opr.name,
syntax);
if (__glibc_unlikely (*err != REG_NOERROR))
if (non_match)
bitset_not (sbcset);
-#ifdef RE_ENABLE_I18N
/* Ensure only single byte characters are set. */
if (dfa->mb_cur_max > 1)
bitset_mask (sbcset, dfa->sb_char);
}
}
else
-#endif /* not RE_ENABLE_I18N */
{
-#ifdef RE_ENABLE_I18N
free_charset (mbcset);
-#endif
/* Build a tree for simple bracket. */
br_token.type = SIMPLE_BRACKET;
br_token.opr.sbcset = sbcset;
*err = REG_ESPACE;
parse_bracket_exp_free_return:
re_free (sbcset);
-#ifdef RE_ENABLE_I18N
free_charset (mbcset);
-#endif /* RE_ENABLE_I18N */
return NULL;
}
re_token_t *token, int token_len, re_dfa_t *dfa,
reg_syntax_t syntax, bool accept_hyphen)
{
-#ifdef RE_ENABLE_I18N
int cur_char_size;
cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp));
if (cur_char_size > 1)
re_string_skip_bytes (regexp, cur_char_size);
return REG_NOERROR;
}
-#endif /* RE_ENABLE_I18N */
re_string_skip_bytes (regexp, token_len); /* Skip a token. */
if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS
|| token->type == OP_OPEN_EQUIV_CLASS)
is a pointer argument since we may update it. */
static reg_errcode_t
-#ifdef RE_ENABLE_I18N
build_equiv_class (bitset_t sbcset, re_charset_t *mbcset,
Idx *equiv_class_alloc, const unsigned char *name)
-#else /* not RE_ENABLE_I18N */
-build_equiv_class (bitset_t sbcset, const unsigned char *name)
-#endif /* not RE_ENABLE_I18N */
{
#ifdef _LIBC
uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
is a pointer argument since we may update it. */
static reg_errcode_t
-#ifdef RE_ENABLE_I18N
build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
re_charset_t *mbcset, Idx *char_class_alloc,
const char *class_name, reg_syntax_t syntax)
-#else /* not RE_ENABLE_I18N */
-build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
- const char *class_name, reg_syntax_t syntax)
-#endif /* not RE_ENABLE_I18N */
{
int i;
const char *name = class_name;
&& (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0))
name = "alpha";
-#ifdef RE_ENABLE_I18N
/* Check the space of the arrays. */
if (__glibc_unlikely (*char_class_alloc == mbcset->nchar_classes))
{
*char_class_alloc = new_char_class_alloc;
}
mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name);
-#endif /* RE_ENABLE_I18N */
#define BUILD_CHARCLASS_LOOP(ctype_func) \
do { \
reg_errcode_t *err)
{
re_bitset_ptr_t sbcset;
-#ifdef RE_ENABLE_I18N
re_charset_t *mbcset;
Idx alloc = 0;
-#endif /* not RE_ENABLE_I18N */
reg_errcode_t ret;
bin_tree_t *tree;
*err = REG_ESPACE;
return NULL;
}
-#ifdef RE_ENABLE_I18N
mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
if (__glibc_unlikely (mbcset == NULL))
{
return NULL;
}
mbcset->non_match = non_match;
-#endif /* RE_ENABLE_I18N */
/* We don't care the syntax in this case. */
- ret = build_charclass (trans, sbcset,
-#ifdef RE_ENABLE_I18N
- mbcset, &alloc,
-#endif /* RE_ENABLE_I18N */
- class_name, 0);
+ ret = build_charclass (trans, sbcset, mbcset, &alloc, class_name, 0);
if (__glibc_unlikely (ret != REG_NOERROR))
{
re_free (sbcset);
-#ifdef RE_ENABLE_I18N
free_charset (mbcset);
-#endif /* RE_ENABLE_I18N */
*err = ret;
return NULL;
}
if (non_match)
bitset_not (sbcset);
-#ifdef RE_ENABLE_I18N
/* Ensure only single byte characters are set. */
if (dfa->mb_cur_max > 1)
bitset_mask (sbcset, dfa->sb_char);
-#endif
/* Build a tree for simple bracket. */
re_token_t br_token = { .type = SIMPLE_BRACKET, .opr.sbcset = sbcset };
if (__glibc_unlikely (tree == NULL))
goto build_word_op_espace;
-#ifdef RE_ENABLE_I18N
if (dfa->mb_cur_max > 1)
{
bin_tree_t *mbc_tree;
free_charset (mbcset);
return tree;
}
-#else /* not RE_ENABLE_I18N */
- return tree;
-#endif /* not RE_ENABLE_I18N */
build_word_op_espace:
re_free (sbcset);
-#ifdef RE_ENABLE_I18N
free_charset (mbcset);
-#endif /* RE_ENABLE_I18N */
*err = REG_ESPACE;
return NULL;
}
return num;
}
\f
-#ifdef RE_ENABLE_I18N
static void
free_charset (re_charset_t *cset)
{
re_free (cset->mbchars);
-# ifdef _LIBC
+#ifdef _LIBC
re_free (cset->coll_syms);
re_free (cset->equiv_classes);
-# endif
+#endif
re_free (cset->range_starts);
re_free (cset->range_ends);
re_free (cset->char_classes);
re_free (cset);
}
-#endif /* RE_ENABLE_I18N */
\f
/* Functions for binary tree operation. */
static void
free_token (re_token_t *node)
{
-#ifdef RE_ENABLE_I18N
if (node->type == COMPLEX_BRACKET && node->duplicated == 0)
free_charset (node->opr.mbcset);
- else
-#endif /* RE_ENABLE_I18N */
- if (node->type == SIMPLE_BRACKET && node->duplicated == 0)
- re_free (node->opr.sbcset);
+ else if (node->type == SIMPLE_BRACKET && node->duplicated == 0)
+ re_free (node->opr.sbcset);
}
/* Worker function for tree walking. Free the allocated memory inside NODE
re_hashval_t hash);
static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr,
Idx new_buf_len);
-#ifdef RE_ENABLE_I18N
static void build_wcs_buffer (re_string_t *pstr);
static reg_errcode_t build_wcs_upper_buffer (re_string_t *pstr);
-#endif /* RE_ENABLE_I18N */
static void build_upper_buffer (re_string_t *pstr);
static void re_string_translate_buffer (re_string_t *pstr);
static unsigned int re_string_context_at (const re_string_t *input, Idx idx,
if (icase)
{
-#ifdef RE_ENABLE_I18N
if (dfa->mb_cur_max > 1)
{
while (1)
}
}
else
-#endif /* RE_ENABLE_I18N */
build_upper_buffer (pstr);
}
else
{
-#ifdef RE_ENABLE_I18N
if (dfa->mb_cur_max > 1)
build_wcs_buffer (pstr);
else
-#endif /* RE_ENABLE_I18N */
{
if (trans != NULL)
re_string_translate_buffer (pstr);
__attribute_warn_unused_result__
re_string_realloc_buffers (re_string_t *pstr, Idx new_buf_len)
{
-#ifdef RE_ENABLE_I18N
if (pstr->mb_cur_max > 1)
{
wint_t *new_wcs;
pstr->offsets = new_offsets;
}
}
-#endif /* RE_ENABLE_I18N */
if (pstr->mbs_allocated)
{
unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char,
pstr->raw_stop = pstr->stop;
}
-#ifdef RE_ENABLE_I18N
/* Build wide character buffer PSTR->WCS.
If the byte sequence of the string are:
*last_wc = wc;
return rawbuf_idx;
}
-#endif /* RE_ENABLE_I18N */
/* Build the buffer PSTR->MBS, and apply the translation if we need.
This function is used in case of REG_ICASE. */
else
{
/* Reset buffer. */
-#ifdef RE_ENABLE_I18N
if (pstr->mb_cur_max > 1)
memset (&pstr->cur_state, '\0', sizeof (mbstate_t));
-#endif /* RE_ENABLE_I18N */
pstr->len = pstr->raw_len;
pstr->stop = pstr->raw_stop;
pstr->valid_len = 0;
if (__glibc_likely (offset < pstr->valid_raw_len))
{
/* Yes, move them to the front of the buffer. */
-#ifdef RE_ENABLE_I18N
if (__glibc_unlikely (pstr->offsets_needed))
{
Idx low = 0, high = pstr->valid_len, mid;
}
}
else
-#endif
{
pstr->tip_context = re_string_context_at (pstr, offset - 1,
eflags);
-#ifdef RE_ENABLE_I18N
if (pstr->mb_cur_max > 1)
memmove (pstr->wcs, pstr->wcs + offset,
(pstr->valid_len - offset) * sizeof (wint_t));
-#endif /* RE_ENABLE_I18N */
if (__glibc_unlikely (pstr->mbs_allocated))
memmove (pstr->mbs, pstr->mbs + offset,
pstr->valid_len - offset);
}
else
{
-#ifdef RE_ENABLE_I18N
/* No, skip all characters until IDX. */
Idx prev_valid_len = pstr->valid_len;
pstr->stop = pstr->raw_stop - idx + offset;
pstr->offsets_needed = 0;
}
-#endif
pstr->valid_len = 0;
-#ifdef RE_ENABLE_I18N
if (pstr->mb_cur_max > 1)
{
Idx wcs_idx;
pstr->valid_raw_len = pstr->valid_len;
}
else
-#endif /* RE_ENABLE_I18N */
{
int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1];
pstr->valid_raw_len = 0;
pstr->stop -= offset;
/* Then build the buffers. */
-#ifdef RE_ENABLE_I18N
if (pstr->mb_cur_max > 1)
{
if (pstr->icase)
build_wcs_buffer (pstr);
}
else
-#endif /* RE_ENABLE_I18N */
if (__glibc_unlikely (pstr->mbs_allocated))
{
if (pstr->icase)
if (__glibc_likely (!pstr->mbs_allocated))
return re_string_peek_byte (pstr, idx);
-#ifdef RE_ENABLE_I18N
if (pstr->mb_cur_max > 1
&& ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx))
return re_string_peek_byte (pstr, idx);
-#endif
off = pstr->cur_idx + idx;
-#ifdef RE_ENABLE_I18N
if (pstr->offsets_needed)
off = pstr->offsets[off];
-#endif
ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];
-#ifdef RE_ENABLE_I18N
/* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I
this function returns CAPITAL LETTER I instead of first byte of
DOTLESS SMALL LETTER I. The latter would confuse the parser,
since peek_byte_case doesn't advance cur_idx in any way. */
if (pstr->offsets_needed && !isascii (ch))
return re_string_peek_byte (pstr, idx);
-#endif
return ch;
}
if (__glibc_likely (!pstr->mbs_allocated))
return re_string_fetch_byte (pstr);
-#ifdef RE_ENABLE_I18N
if (pstr->offsets_needed)
{
Idx off;
re_string_char_size_at (pstr, pstr->cur_idx));
return ch;
}
-#endif
return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++];
}
static void
re_string_destruct (re_string_t *pstr)
{
-#ifdef RE_ENABLE_I18N
re_free (pstr->wcs);
re_free (pstr->offsets);
-#endif /* RE_ENABLE_I18N */
if (pstr->mbs_allocated)
re_free (pstr->mbs);
}
if (__glibc_unlikely (idx == input->len))
return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF
: CONTEXT_NEWLINE | CONTEXT_ENDBUF);
-#ifdef RE_ENABLE_I18N
if (input->mb_cur_max > 1)
{
wint_t wc;
? CONTEXT_NEWLINE : 0);
}
else
-#endif
{
c = re_string_byte_at (input, idx);
if (bitset_contain (input->word_char, c))
}
dfa->nodes[dfa->nodes_len] = token;
dfa->nodes[dfa->nodes_len].constraint = 0;
-#ifdef RE_ENABLE_I18N
dfa->nodes[dfa->nodes_len].accept_mb =
((token.type == OP_PERIOD && dfa->mb_cur_max > 1)
|| token.type == COMPLEX_BRACKET);
-#endif
dfa->nexts[dfa->nodes_len] = -1;
re_node_set_init_empty (dfa->edests + dfa->nodes_len);
re_node_set_init_empty (dfa->eclosures + dfa->nodes_len);
re_token_type_t type = node->type;
if (type == CHARACTER && !node->constraint)
continue;
-#ifdef RE_ENABLE_I18N
newstate->accept_mb |= node->accept_mb;
-#endif /* RE_ENABLE_I18N */
/* If the state has the halt node, the state is a halt state. */
if (type == END_OF_RE)
if (type == CHARACTER && !constraint)
continue;
-#ifdef RE_ENABLE_I18N
newstate->accept_mb |= node->accept_mb;
-#endif /* RE_ENABLE_I18N */
/* If the state has the halt node, the state is a halt state. */
if (type == END_OF_RE)
bool fl_backtrack);
static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs);
-#ifdef RE_ENABLE_I18N
static int sift_states_iter_mb (const re_match_context_t *mctx,
re_sift_context_t *sctx,
Idx node_idx, Idx str_idx, Idx max_str_idx);
-#endif /* RE_ENABLE_I18N */
static reg_errcode_t sift_states_backward (const re_match_context_t *mctx,
re_sift_context_t *sctx);
static reg_errcode_t build_sifted_states (const re_match_context_t *mctx,
re_match_context_t *mctx,
re_dfastate_t *pstate);
#endif
-#ifdef RE_ENABLE_I18N
static reg_errcode_t transit_state_mb (re_match_context_t *mctx,
re_dfastate_t *pstate);
-#endif /* RE_ENABLE_I18N */
static reg_errcode_t transit_state_bkref (re_match_context_t *mctx,
const re_node_set *nodes);
static reg_errcode_t get_subexp (re_match_context_t *mctx,
re_node_set *cur_nodes, Idx cur_str,
Idx subexp_num, int type);
static bool build_trtable (const re_dfa_t *dfa, re_dfastate_t *state);
-#ifdef RE_ENABLE_I18N
static int check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx,
const re_string_t *input, Idx idx);
-# ifdef _LIBC
+#ifdef _LIBC
static unsigned int find_collation_sequence_value (const unsigned char *mbs,
size_t name_len);
-# endif /* _LIBC */
-#endif /* RE_ENABLE_I18N */
+#endif
static Idx group_nodes_into_DFAstates (const re_dfa_t *dfa,
const re_dfastate_t *state,
re_node_set *states_node,
if (__glibc_unlikely (err != REG_NOERROR))
goto free_return;
-#ifdef RE_ENABLE_I18N
- /* Don't consider this char as a possible match start if it part,
- yet isn't the head, of a multibyte character. */
+ /* Don't consider this char as a possible match start if it part,
+ yet isn't the head, of a multibyte character. */
if (!sb && !re_string_first_byte (&mctx.input, 0))
continue;
-#endif
/* It seems to be appropriate one, then use the matcher. */
/* We assume that the matching starts from 0. */
for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)
if (pmatch[reg_idx].rm_so != -1)
{
-#ifdef RE_ENABLE_I18N
if (__glibc_unlikely (mctx.input.offsets_needed != 0))
{
pmatch[reg_idx].rm_so =
? mctx.input.valid_raw_len
: mctx.input.offsets[pmatch[reg_idx].rm_eo]);
}
-#else
- DEBUG_ASSERT (mctx.input.offsets_needed == 0);
-#endif
pmatch[reg_idx].rm_so += match_first;
pmatch[reg_idx].rm_eo += match_first;
}
Idx naccepted = 0;
re_token_type_t type = dfa->nodes[node].type;
-#ifdef RE_ENABLE_I18N
if (dfa->nodes[node].accept_mb)
naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx);
- else
-#endif /* RE_ENABLE_I18N */
- if (type == OP_BACK_REF)
+ else if (type == OP_BACK_REF)
{
Idx subexp_idx = dfa->nodes[node].opr.idx + 1;
if (subexp_idx < nregs)
bool ok;
DEBUG_ASSERT (!IS_EPSILON_NODE (dfa->nodes[prev_node].type));
-#ifdef RE_ENABLE_I18N
/* If the node may accept "multi byte". */
if (dfa->nodes[prev_node].accept_mb)
naccepted = sift_states_iter_mb (mctx, sctx, prev_node,
str_idx, sctx->last_str_idx);
-#endif /* RE_ENABLE_I18N */
/* We don't check backreferences here.
See update_cur_sifted_state(). */
}
-#ifdef RE_ENABLE_I18N
static int
sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx,
Idx node_idx, Idx str_idx, Idx max_str_idx)
'naccepted' bytes input. */
return naccepted;
}
-#endif /* RE_ENABLE_I18N */
-
\f
/* Functions for state transition. */
re_dfastate_t **trtable;
unsigned char ch;
-#ifdef RE_ENABLE_I18N
/* If the current state can accept multibyte. */
if (__glibc_unlikely (state->accept_mb))
{
if (__glibc_unlikely (*err != REG_NOERROR))
return NULL;
}
-#endif /* RE_ENABLE_I18N */
/* Then decide the next state with the single byte. */
#if 0
}
#endif
-#ifdef RE_ENABLE_I18N
static reg_errcode_t
transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate)
{
}
return REG_NOERROR;
}
-#endif /* RE_ENABLE_I18N */
static reg_errcode_t
transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes)
const re_dfa_t *const dfa = mctx->dfa;
bool ok;
Idx cur_idx;
-#ifdef RE_ENABLE_I18N
reg_errcode_t err = REG_NOERROR;
-#endif
re_node_set union_set;
re_node_set_init_empty (&union_set);
for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx)
Idx cur_node = cur_nodes->elems[cur_idx];
DEBUG_ASSERT (!IS_EPSILON_NODE (dfa->nodes[cur_node].type));
-#ifdef RE_ENABLE_I18N
/* If the node may accept "multi byte". */
if (dfa->nodes[cur_node].accept_mb)
{
}
}
}
-#endif /* RE_ENABLE_I18N */
+
if (naccepted
|| check_node_accept (mctx, dfa->nodes + cur_node, str_idx))
{
}
else if (type == OP_PERIOD)
{
-#ifdef RE_ENABLE_I18N
if (dfa->mb_cur_max > 1)
bitset_merge (accepts, dfa->sb_char);
else
-#endif
bitset_set_all (accepts);
if (!(dfa->syntax & RE_DOT_NEWLINE))
bitset_clear (accepts, '\n');
if (dfa->syntax & RE_DOT_NOT_NULL)
bitset_clear (accepts, '\0');
}
-#ifdef RE_ENABLE_I18N
else if (type == OP_UTF8_PERIOD)
{
if (ASCII_CHARS % BITSET_WORD_BITS == 0)
if (dfa->syntax & RE_DOT_NOT_NULL)
bitset_clear (accepts, '\0');
}
-#endif
else
continue;
bitset_empty (accepts);
continue;
}
-#ifdef RE_ENABLE_I18N
if (dfa->mb_cur_max > 1)
for (j = 0; j < BITSET_WORDS; ++j)
any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j]));
else
-#endif
for (j = 0; j < BITSET_WORDS; ++j)
any_set |= (accepts[j] &= dfa->word_char[j]);
if (!any_set)
bitset_empty (accepts);
continue;
}
-#ifdef RE_ENABLE_I18N
if (dfa->mb_cur_max > 1)
for (j = 0; j < BITSET_WORDS; ++j)
any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j]));
else
-#endif
for (j = 0; j < BITSET_WORDS; ++j)
any_set |= (accepts[j] &= ~dfa->word_char[j]);
if (!any_set)
return -1;
}
-#ifdef RE_ENABLE_I18N
/* Check how many bytes the node 'dfa->nodes[node_idx]' accepts.
Return the number of the bytes the node accepts.
STR_IDX is the current index of the input string.
one collating element like '.', '[a-z]', opposite to the other nodes
can only accept one byte. */
-# ifdef _LIBC
-# include <locale/weight.h>
-# endif
+#ifdef _LIBC
+# include <locale/weight.h>
+#endif
static int
check_node_accept_bytes (const re_dfa_t *dfa, Idx node_idx,
if (node->type == COMPLEX_BRACKET)
{
const re_charset_t *cset = node->opr.mbcset;
-# ifdef _LIBC
+#ifdef _LIBC
const unsigned char *pin
= ((const unsigned char *) re_string_get_buffer (input) + str_idx);
Idx j;
uint32_t nrules;
-# endif /* _LIBC */
+#endif
int match_len = 0;
wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars)
? re_string_wchar_at (input, str_idx) : 0);
}
}
-# ifdef _LIBC
+#ifdef _LIBC
nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
if (nrules != 0)
{
}
}
else
-# endif /* _LIBC */
+#endif /* _LIBC */
{
/* match with range expression? */
for (i = 0; i < cset->nranges; ++i)
return 0;
}
-# ifdef _LIBC
+#ifdef _LIBC
static unsigned int
find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len)
{
return UINT_MAX;
}
}
-# endif /* _LIBC */
-#endif /* RE_ENABLE_I18N */
+#endif /* _LIBC */
/* Check whether the node accepts the byte which is IDX-th
byte of the INPUT. */
return false;
break;
-#ifdef RE_ENABLE_I18N
case OP_UTF8_PERIOD:
if (ch >= ASCII_CHARS)
return false;
FALLTHROUGH;
-#endif
case OP_PERIOD:
if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE))
|| (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL)))
/* Then reconstruct the buffers. */
if (pstr->icase)
{
-#ifdef RE_ENABLE_I18N
if (pstr->mb_cur_max > 1)
{
ret = build_wcs_upper_buffer (pstr);
return ret;
}
else
-#endif /* RE_ENABLE_I18N */
build_upper_buffer (pstr);
}
else
{
-#ifdef RE_ENABLE_I18N
if (pstr->mb_cur_max > 1)
build_wcs_buffer (pstr);
else
-#endif /* RE_ENABLE_I18N */
{
if (pstr->trans != NULL)
re_string_translate_buffer (pstr);