1*820c1a8dSHiroo HAYASHI /* Extended regular expression matching and search library.
2*820c1a8dSHiroo HAYASHI Copyright (C) 2002-2021 Free Software Foundation, Inc.
3*820c1a8dSHiroo HAYASHI This file is part of the GNU C Library.
4*820c1a8dSHiroo HAYASHI Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.
5*820c1a8dSHiroo HAYASHI
6*820c1a8dSHiroo HAYASHI The GNU C Library is free software; you can redistribute it and/or
7*820c1a8dSHiroo HAYASHI modify it under the terms of the GNU Lesser General Public
8*820c1a8dSHiroo HAYASHI License as published by the Free Software Foundation; either
9*820c1a8dSHiroo HAYASHI version 2.1 of the License, or (at your option) any later version.
10*820c1a8dSHiroo HAYASHI
11*820c1a8dSHiroo HAYASHI The GNU C Library is distributed in the hope that it will be useful,
12*820c1a8dSHiroo HAYASHI but WITHOUT ANY WARRANTY; without even the implied warranty of
13*820c1a8dSHiroo HAYASHI MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14*820c1a8dSHiroo HAYASHI Lesser General Public License for more details.
15*820c1a8dSHiroo HAYASHI
16*820c1a8dSHiroo HAYASHI You should have received a copy of the GNU Lesser General Public
17*820c1a8dSHiroo HAYASHI License along with the GNU C Library; if not, see
18*820c1a8dSHiroo HAYASHI <https://www.gnu.org/licenses/>. */
19*820c1a8dSHiroo HAYASHI
20*820c1a8dSHiroo HAYASHI #ifdef _LIBC
21*820c1a8dSHiroo HAYASHI # include <locale/weight.h>
22*820c1a8dSHiroo HAYASHI #endif
23*820c1a8dSHiroo HAYASHI
24*820c1a8dSHiroo HAYASHI static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern,
25*820c1a8dSHiroo HAYASHI size_t length, reg_syntax_t syntax);
26*820c1a8dSHiroo HAYASHI static void re_compile_fastmap_iter (regex_t *bufp,
27*820c1a8dSHiroo HAYASHI const re_dfastate_t *init_state,
28*820c1a8dSHiroo HAYASHI char *fastmap);
29*820c1a8dSHiroo HAYASHI static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len);
30*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
31*820c1a8dSHiroo HAYASHI static void free_charset (re_charset_t *cset);
32*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
33*820c1a8dSHiroo HAYASHI static void free_workarea_compile (regex_t *preg);
34*820c1a8dSHiroo HAYASHI static reg_errcode_t create_initial_state (re_dfa_t *dfa);
35*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
36*820c1a8dSHiroo HAYASHI static void optimize_utf8 (re_dfa_t *dfa);
37*820c1a8dSHiroo HAYASHI #endif
38*820c1a8dSHiroo HAYASHI static reg_errcode_t analyze (regex_t *preg);
39*820c1a8dSHiroo HAYASHI static reg_errcode_t preorder (bin_tree_t *root,
40*820c1a8dSHiroo HAYASHI reg_errcode_t (fn (void *, bin_tree_t *)),
41*820c1a8dSHiroo HAYASHI void *extra);
42*820c1a8dSHiroo HAYASHI static reg_errcode_t postorder (bin_tree_t *root,
43*820c1a8dSHiroo HAYASHI reg_errcode_t (fn (void *, bin_tree_t *)),
44*820c1a8dSHiroo HAYASHI void *extra);
45*820c1a8dSHiroo HAYASHI static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node);
46*820c1a8dSHiroo HAYASHI static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node);
47*820c1a8dSHiroo HAYASHI static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg,
48*820c1a8dSHiroo HAYASHI bin_tree_t *node);
49*820c1a8dSHiroo HAYASHI static reg_errcode_t calc_first (void *extra, bin_tree_t *node);
50*820c1a8dSHiroo HAYASHI static reg_errcode_t calc_next (void *extra, bin_tree_t *node);
51*820c1a8dSHiroo HAYASHI static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node);
52*820c1a8dSHiroo HAYASHI static Idx duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint);
53*820c1a8dSHiroo HAYASHI static Idx search_duplicated_node (const re_dfa_t *dfa, Idx org_node,
54*820c1a8dSHiroo HAYASHI unsigned int constraint);
55*820c1a8dSHiroo HAYASHI static reg_errcode_t calc_eclosure (re_dfa_t *dfa);
56*820c1a8dSHiroo HAYASHI static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa,
57*820c1a8dSHiroo HAYASHI Idx node, bool root);
58*820c1a8dSHiroo HAYASHI static reg_errcode_t calc_inveclosure (re_dfa_t *dfa);
59*820c1a8dSHiroo HAYASHI static Idx fetch_number (re_string_t *input, re_token_t *token,
60*820c1a8dSHiroo HAYASHI reg_syntax_t syntax);
61*820c1a8dSHiroo HAYASHI static int peek_token (re_token_t *token, re_string_t *input,
62*820c1a8dSHiroo HAYASHI reg_syntax_t syntax);
63*820c1a8dSHiroo HAYASHI static bin_tree_t *parse (re_string_t *regexp, regex_t *preg,
64*820c1a8dSHiroo HAYASHI reg_syntax_t syntax, reg_errcode_t *err);
65*820c1a8dSHiroo HAYASHI static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg,
66*820c1a8dSHiroo HAYASHI re_token_t *token, reg_syntax_t syntax,
67*820c1a8dSHiroo HAYASHI Idx nest, reg_errcode_t *err);
68*820c1a8dSHiroo HAYASHI static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg,
69*820c1a8dSHiroo HAYASHI re_token_t *token, reg_syntax_t syntax,
70*820c1a8dSHiroo HAYASHI Idx nest, reg_errcode_t *err);
71*820c1a8dSHiroo HAYASHI static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg,
72*820c1a8dSHiroo HAYASHI re_token_t *token, reg_syntax_t syntax,
73*820c1a8dSHiroo HAYASHI Idx nest, reg_errcode_t *err);
74*820c1a8dSHiroo HAYASHI static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg,
75*820c1a8dSHiroo HAYASHI re_token_t *token, reg_syntax_t syntax,
76*820c1a8dSHiroo HAYASHI Idx nest, reg_errcode_t *err);
77*820c1a8dSHiroo HAYASHI static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp,
78*820c1a8dSHiroo HAYASHI re_dfa_t *dfa, re_token_t *token,
79*820c1a8dSHiroo HAYASHI reg_syntax_t syntax, reg_errcode_t *err);
80*820c1a8dSHiroo HAYASHI static bin_tree_t *parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa,
81*820c1a8dSHiroo HAYASHI re_token_t *token, reg_syntax_t syntax,
82*820c1a8dSHiroo HAYASHI reg_errcode_t *err);
83*820c1a8dSHiroo HAYASHI static reg_errcode_t parse_bracket_element (bracket_elem_t *elem,
84*820c1a8dSHiroo HAYASHI re_string_t *regexp,
85*820c1a8dSHiroo HAYASHI re_token_t *token, int token_len,
86*820c1a8dSHiroo HAYASHI re_dfa_t *dfa,
87*820c1a8dSHiroo HAYASHI reg_syntax_t syntax,
88*820c1a8dSHiroo HAYASHI bool accept_hyphen);
89*820c1a8dSHiroo HAYASHI static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem,
90*820c1a8dSHiroo HAYASHI re_string_t *regexp,
91*820c1a8dSHiroo HAYASHI re_token_t *token);
92*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
93*820c1a8dSHiroo HAYASHI static reg_errcode_t build_equiv_class (bitset_t sbcset,
94*820c1a8dSHiroo HAYASHI re_charset_t *mbcset,
95*820c1a8dSHiroo HAYASHI Idx *equiv_class_alloc,
96*820c1a8dSHiroo HAYASHI const unsigned char *name);
97*820c1a8dSHiroo HAYASHI static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans,
98*820c1a8dSHiroo HAYASHI bitset_t sbcset,
99*820c1a8dSHiroo HAYASHI re_charset_t *mbcset,
100*820c1a8dSHiroo HAYASHI Idx *char_class_alloc,
101*820c1a8dSHiroo HAYASHI const char *class_name,
102*820c1a8dSHiroo HAYASHI reg_syntax_t syntax);
103*820c1a8dSHiroo HAYASHI #else /* not RE_ENABLE_I18N */
104*820c1a8dSHiroo HAYASHI static reg_errcode_t build_equiv_class (bitset_t sbcset,
105*820c1a8dSHiroo HAYASHI const unsigned char *name);
106*820c1a8dSHiroo HAYASHI static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans,
107*820c1a8dSHiroo HAYASHI bitset_t sbcset,
108*820c1a8dSHiroo HAYASHI const char *class_name,
109*820c1a8dSHiroo HAYASHI reg_syntax_t syntax);
110*820c1a8dSHiroo HAYASHI #endif /* not RE_ENABLE_I18N */
111*820c1a8dSHiroo HAYASHI static bin_tree_t *build_charclass_op (re_dfa_t *dfa,
112*820c1a8dSHiroo HAYASHI RE_TRANSLATE_TYPE trans,
113*820c1a8dSHiroo HAYASHI const char *class_name,
114*820c1a8dSHiroo HAYASHI const char *extra,
115*820c1a8dSHiroo HAYASHI bool non_match, reg_errcode_t *err);
116*820c1a8dSHiroo HAYASHI static bin_tree_t *create_tree (re_dfa_t *dfa,
117*820c1a8dSHiroo HAYASHI bin_tree_t *left, bin_tree_t *right,
118*820c1a8dSHiroo HAYASHI re_token_type_t type);
119*820c1a8dSHiroo HAYASHI static bin_tree_t *create_token_tree (re_dfa_t *dfa,
120*820c1a8dSHiroo HAYASHI bin_tree_t *left, bin_tree_t *right,
121*820c1a8dSHiroo HAYASHI const re_token_t *token);
122*820c1a8dSHiroo HAYASHI static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa);
123*820c1a8dSHiroo HAYASHI static void free_token (re_token_t *node);
124*820c1a8dSHiroo HAYASHI static reg_errcode_t free_tree (void *extra, bin_tree_t *node);
125*820c1a8dSHiroo HAYASHI static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node);
126*820c1a8dSHiroo HAYASHI
127*820c1a8dSHiroo HAYASHI /* This table gives an error message for each of the error codes listed
128*820c1a8dSHiroo HAYASHI in regex.h. Obviously the order here has to be same as there.
129*820c1a8dSHiroo HAYASHI POSIX doesn't require that we do anything for REG_NOERROR,
130*820c1a8dSHiroo HAYASHI but why not be nice? */
131*820c1a8dSHiroo HAYASHI
132*820c1a8dSHiroo HAYASHI static const char __re_error_msgid[] =
133*820c1a8dSHiroo HAYASHI {
134*820c1a8dSHiroo HAYASHI #define REG_NOERROR_IDX 0
135*820c1a8dSHiroo HAYASHI gettext_noop ("Success") /* REG_NOERROR */
136*820c1a8dSHiroo HAYASHI "\0"
137*820c1a8dSHiroo HAYASHI #define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success")
138*820c1a8dSHiroo HAYASHI gettext_noop ("No match") /* REG_NOMATCH */
139*820c1a8dSHiroo HAYASHI "\0"
140*820c1a8dSHiroo HAYASHI #define REG_BADPAT_IDX (REG_NOMATCH_IDX + sizeof "No match")
141*820c1a8dSHiroo HAYASHI gettext_noop ("Invalid regular expression") /* REG_BADPAT */
142*820c1a8dSHiroo HAYASHI "\0"
143*820c1a8dSHiroo HAYASHI #define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression")
144*820c1a8dSHiroo HAYASHI gettext_noop ("Invalid collation character") /* REG_ECOLLATE */
145*820c1a8dSHiroo HAYASHI "\0"
146*820c1a8dSHiroo HAYASHI #define REG_ECTYPE_IDX (REG_ECOLLATE_IDX + sizeof "Invalid collation character")
147*820c1a8dSHiroo HAYASHI gettext_noop ("Invalid character class name") /* REG_ECTYPE */
148*820c1a8dSHiroo HAYASHI "\0"
149*820c1a8dSHiroo HAYASHI #define REG_EESCAPE_IDX (REG_ECTYPE_IDX + sizeof "Invalid character class name")
150*820c1a8dSHiroo HAYASHI gettext_noop ("Trailing backslash") /* REG_EESCAPE */
151*820c1a8dSHiroo HAYASHI "\0"
152*820c1a8dSHiroo HAYASHI #define REG_ESUBREG_IDX (REG_EESCAPE_IDX + sizeof "Trailing backslash")
153*820c1a8dSHiroo HAYASHI gettext_noop ("Invalid back reference") /* REG_ESUBREG */
154*820c1a8dSHiroo HAYASHI "\0"
155*820c1a8dSHiroo HAYASHI #define REG_EBRACK_IDX (REG_ESUBREG_IDX + sizeof "Invalid back reference")
156*820c1a8dSHiroo HAYASHI gettext_noop ("Unmatched [, [^, [:, [., or [=") /* REG_EBRACK */
157*820c1a8dSHiroo HAYASHI "\0"
158*820c1a8dSHiroo HAYASHI #define REG_EPAREN_IDX (REG_EBRACK_IDX + sizeof "Unmatched [, [^, [:, [., or [=")
159*820c1a8dSHiroo HAYASHI gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */
160*820c1a8dSHiroo HAYASHI "\0"
161*820c1a8dSHiroo HAYASHI #define REG_EBRACE_IDX (REG_EPAREN_IDX + sizeof "Unmatched ( or \\(")
162*820c1a8dSHiroo HAYASHI gettext_noop ("Unmatched \\{") /* REG_EBRACE */
163*820c1a8dSHiroo HAYASHI "\0"
164*820c1a8dSHiroo HAYASHI #define REG_BADBR_IDX (REG_EBRACE_IDX + sizeof "Unmatched \\{")
165*820c1a8dSHiroo HAYASHI gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */
166*820c1a8dSHiroo HAYASHI "\0"
167*820c1a8dSHiroo HAYASHI #define REG_ERANGE_IDX (REG_BADBR_IDX + sizeof "Invalid content of \\{\\}")
168*820c1a8dSHiroo HAYASHI gettext_noop ("Invalid range end") /* REG_ERANGE */
169*820c1a8dSHiroo HAYASHI "\0"
170*820c1a8dSHiroo HAYASHI #define REG_ESPACE_IDX (REG_ERANGE_IDX + sizeof "Invalid range end")
171*820c1a8dSHiroo HAYASHI gettext_noop ("Memory exhausted") /* REG_ESPACE */
172*820c1a8dSHiroo HAYASHI "\0"
173*820c1a8dSHiroo HAYASHI #define REG_BADRPT_IDX (REG_ESPACE_IDX + sizeof "Memory exhausted")
174*820c1a8dSHiroo HAYASHI gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */
175*820c1a8dSHiroo HAYASHI "\0"
176*820c1a8dSHiroo HAYASHI #define REG_EEND_IDX (REG_BADRPT_IDX + sizeof "Invalid preceding regular expression")
177*820c1a8dSHiroo HAYASHI gettext_noop ("Premature end of regular expression") /* REG_EEND */
178*820c1a8dSHiroo HAYASHI "\0"
179*820c1a8dSHiroo HAYASHI #define REG_ESIZE_IDX (REG_EEND_IDX + sizeof "Premature end of regular expression")
180*820c1a8dSHiroo HAYASHI gettext_noop ("Regular expression too big") /* REG_ESIZE */
181*820c1a8dSHiroo HAYASHI "\0"
182*820c1a8dSHiroo HAYASHI #define REG_ERPAREN_IDX (REG_ESIZE_IDX + sizeof "Regular expression too big")
183*820c1a8dSHiroo HAYASHI gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */
184*820c1a8dSHiroo HAYASHI };
185*820c1a8dSHiroo HAYASHI
186*820c1a8dSHiroo HAYASHI static const size_t __re_error_msgid_idx[] =
187*820c1a8dSHiroo HAYASHI {
188*820c1a8dSHiroo HAYASHI REG_NOERROR_IDX,
189*820c1a8dSHiroo HAYASHI REG_NOMATCH_IDX,
190*820c1a8dSHiroo HAYASHI REG_BADPAT_IDX,
191*820c1a8dSHiroo HAYASHI REG_ECOLLATE_IDX,
192*820c1a8dSHiroo HAYASHI REG_ECTYPE_IDX,
193*820c1a8dSHiroo HAYASHI REG_EESCAPE_IDX,
194*820c1a8dSHiroo HAYASHI REG_ESUBREG_IDX,
195*820c1a8dSHiroo HAYASHI REG_EBRACK_IDX,
196*820c1a8dSHiroo HAYASHI REG_EPAREN_IDX,
197*820c1a8dSHiroo HAYASHI REG_EBRACE_IDX,
198*820c1a8dSHiroo HAYASHI REG_BADBR_IDX,
199*820c1a8dSHiroo HAYASHI REG_ERANGE_IDX,
200*820c1a8dSHiroo HAYASHI REG_ESPACE_IDX,
201*820c1a8dSHiroo HAYASHI REG_BADRPT_IDX,
202*820c1a8dSHiroo HAYASHI REG_EEND_IDX,
203*820c1a8dSHiroo HAYASHI REG_ESIZE_IDX,
204*820c1a8dSHiroo HAYASHI REG_ERPAREN_IDX
205*820c1a8dSHiroo HAYASHI };
206*820c1a8dSHiroo HAYASHI
207*820c1a8dSHiroo HAYASHI /* Entry points for GNU code. */
208*820c1a8dSHiroo HAYASHI
209*820c1a8dSHiroo HAYASHI /* re_compile_pattern is the GNU regular expression compiler: it
210*820c1a8dSHiroo HAYASHI compiles PATTERN (of length LENGTH) and puts the result in BUFP.
211*820c1a8dSHiroo HAYASHI Returns 0 if the pattern was valid, otherwise an error string.
212*820c1a8dSHiroo HAYASHI
213*820c1a8dSHiroo HAYASHI Assumes the 'allocated' (and perhaps 'buffer') and 'translate' fields
214*820c1a8dSHiroo HAYASHI are set in BUFP on entry. */
215*820c1a8dSHiroo HAYASHI
216*820c1a8dSHiroo HAYASHI const char *
re_compile_pattern(const char * pattern,size_t length,struct re_pattern_buffer * bufp)217*820c1a8dSHiroo HAYASHI re_compile_pattern (const char *pattern, size_t length,
218*820c1a8dSHiroo HAYASHI struct re_pattern_buffer *bufp)
219*820c1a8dSHiroo HAYASHI {
220*820c1a8dSHiroo HAYASHI reg_errcode_t ret;
221*820c1a8dSHiroo HAYASHI
222*820c1a8dSHiroo HAYASHI /* And GNU code determines whether or not to get register information
223*820c1a8dSHiroo HAYASHI by passing null for the REGS argument to re_match, etc., not by
224*820c1a8dSHiroo HAYASHI setting no_sub, unless RE_NO_SUB is set. */
225*820c1a8dSHiroo HAYASHI bufp->no_sub = !!(re_syntax_options & RE_NO_SUB);
226*820c1a8dSHiroo HAYASHI
227*820c1a8dSHiroo HAYASHI /* Match anchors at newline. */
228*820c1a8dSHiroo HAYASHI bufp->newline_anchor = 1;
229*820c1a8dSHiroo HAYASHI
230*820c1a8dSHiroo HAYASHI ret = re_compile_internal (bufp, pattern, length, re_syntax_options);
231*820c1a8dSHiroo HAYASHI
232*820c1a8dSHiroo HAYASHI if (!ret)
233*820c1a8dSHiroo HAYASHI return NULL;
234*820c1a8dSHiroo HAYASHI return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
235*820c1a8dSHiroo HAYASHI }
weak_alias(__re_compile_pattern,re_compile_pattern)236*820c1a8dSHiroo HAYASHI weak_alias (__re_compile_pattern, re_compile_pattern)
237*820c1a8dSHiroo HAYASHI
238*820c1a8dSHiroo HAYASHI /* Set by 're_set_syntax' to the current regexp syntax to recognize. Can
239*820c1a8dSHiroo HAYASHI also be assigned to arbitrarily: each pattern buffer stores its own
240*820c1a8dSHiroo HAYASHI syntax, so it can be changed between regex compilations. */
241*820c1a8dSHiroo HAYASHI /* This has no initializer because initialized variables in Emacs
242*820c1a8dSHiroo HAYASHI become read-only after dumping. */
243*820c1a8dSHiroo HAYASHI reg_syntax_t re_syntax_options;
244*820c1a8dSHiroo HAYASHI
245*820c1a8dSHiroo HAYASHI
246*820c1a8dSHiroo HAYASHI /* Specify the precise syntax of regexps for compilation. This provides
247*820c1a8dSHiroo HAYASHI for compatibility for various utilities which historically have
248*820c1a8dSHiroo HAYASHI different, incompatible syntaxes.
249*820c1a8dSHiroo HAYASHI
250*820c1a8dSHiroo HAYASHI The argument SYNTAX is a bit mask comprised of the various bits
251*820c1a8dSHiroo HAYASHI defined in regex.h. We return the old syntax. */
252*820c1a8dSHiroo HAYASHI
253*820c1a8dSHiroo HAYASHI reg_syntax_t
254*820c1a8dSHiroo HAYASHI re_set_syntax (reg_syntax_t syntax)
255*820c1a8dSHiroo HAYASHI {
256*820c1a8dSHiroo HAYASHI reg_syntax_t ret = re_syntax_options;
257*820c1a8dSHiroo HAYASHI
258*820c1a8dSHiroo HAYASHI re_syntax_options = syntax;
259*820c1a8dSHiroo HAYASHI return ret;
260*820c1a8dSHiroo HAYASHI }
weak_alias(__re_set_syntax,re_set_syntax)261*820c1a8dSHiroo HAYASHI weak_alias (__re_set_syntax, re_set_syntax)
262*820c1a8dSHiroo HAYASHI
263*820c1a8dSHiroo HAYASHI int
264*820c1a8dSHiroo HAYASHI re_compile_fastmap (struct re_pattern_buffer *bufp)
265*820c1a8dSHiroo HAYASHI {
266*820c1a8dSHiroo HAYASHI re_dfa_t *dfa = bufp->buffer;
267*820c1a8dSHiroo HAYASHI char *fastmap = bufp->fastmap;
268*820c1a8dSHiroo HAYASHI
269*820c1a8dSHiroo HAYASHI memset (fastmap, '\0', sizeof (char) * SBC_MAX);
270*820c1a8dSHiroo HAYASHI re_compile_fastmap_iter (bufp, dfa->init_state, fastmap);
271*820c1a8dSHiroo HAYASHI if (dfa->init_state != dfa->init_state_word)
272*820c1a8dSHiroo HAYASHI re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap);
273*820c1a8dSHiroo HAYASHI if (dfa->init_state != dfa->init_state_nl)
274*820c1a8dSHiroo HAYASHI re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap);
275*820c1a8dSHiroo HAYASHI if (dfa->init_state != dfa->init_state_begbuf)
276*820c1a8dSHiroo HAYASHI re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap);
277*820c1a8dSHiroo HAYASHI bufp->fastmap_accurate = 1;
278*820c1a8dSHiroo HAYASHI return 0;
279*820c1a8dSHiroo HAYASHI }
weak_alias(__re_compile_fastmap,re_compile_fastmap)280*820c1a8dSHiroo HAYASHI weak_alias (__re_compile_fastmap, re_compile_fastmap)
281*820c1a8dSHiroo HAYASHI
282*820c1a8dSHiroo HAYASHI static inline void
283*820c1a8dSHiroo HAYASHI __attribute__ ((always_inline))
284*820c1a8dSHiroo HAYASHI re_set_fastmap (char *fastmap, bool icase, int ch)
285*820c1a8dSHiroo HAYASHI {
286*820c1a8dSHiroo HAYASHI fastmap[ch] = 1;
287*820c1a8dSHiroo HAYASHI if (icase)
288*820c1a8dSHiroo HAYASHI fastmap[tolower (ch)] = 1;
289*820c1a8dSHiroo HAYASHI }
290*820c1a8dSHiroo HAYASHI
291*820c1a8dSHiroo HAYASHI /* Helper function for re_compile_fastmap.
292*820c1a8dSHiroo HAYASHI Compile fastmap for the initial_state INIT_STATE. */
293*820c1a8dSHiroo HAYASHI
294*820c1a8dSHiroo HAYASHI static void
re_compile_fastmap_iter(regex_t * bufp,const re_dfastate_t * init_state,char * fastmap)295*820c1a8dSHiroo HAYASHI re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,
296*820c1a8dSHiroo HAYASHI char *fastmap)
297*820c1a8dSHiroo HAYASHI {
298*820c1a8dSHiroo HAYASHI re_dfa_t *dfa = bufp->buffer;
299*820c1a8dSHiroo HAYASHI Idx node_cnt;
300*820c1a8dSHiroo HAYASHI bool icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE));
301*820c1a8dSHiroo HAYASHI for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt)
302*820c1a8dSHiroo HAYASHI {
303*820c1a8dSHiroo HAYASHI Idx node = init_state->nodes.elems[node_cnt];
304*820c1a8dSHiroo HAYASHI re_token_type_t type = dfa->nodes[node].type;
305*820c1a8dSHiroo HAYASHI
306*820c1a8dSHiroo HAYASHI if (type == CHARACTER)
307*820c1a8dSHiroo HAYASHI {
308*820c1a8dSHiroo HAYASHI re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c);
309*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
310*820c1a8dSHiroo HAYASHI if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
311*820c1a8dSHiroo HAYASHI {
312*820c1a8dSHiroo HAYASHI unsigned char buf[MB_LEN_MAX];
313*820c1a8dSHiroo HAYASHI unsigned char *p;
314*820c1a8dSHiroo HAYASHI wchar_t wc;
315*820c1a8dSHiroo HAYASHI mbstate_t state;
316*820c1a8dSHiroo HAYASHI
317*820c1a8dSHiroo HAYASHI p = buf;
318*820c1a8dSHiroo HAYASHI *p++ = dfa->nodes[node].opr.c;
319*820c1a8dSHiroo HAYASHI while (++node < dfa->nodes_len
320*820c1a8dSHiroo HAYASHI && dfa->nodes[node].type == CHARACTER
321*820c1a8dSHiroo HAYASHI && dfa->nodes[node].mb_partial)
322*820c1a8dSHiroo HAYASHI *p++ = dfa->nodes[node].opr.c;
323*820c1a8dSHiroo HAYASHI memset (&state, '\0', sizeof (state));
324*820c1a8dSHiroo HAYASHI if (__mbrtowc (&wc, (const char *) buf, p - buf,
325*820c1a8dSHiroo HAYASHI &state) == p - buf
326*820c1a8dSHiroo HAYASHI && (__wcrtomb ((char *) buf, __towlower (wc), &state)
327*820c1a8dSHiroo HAYASHI != (size_t) -1))
328*820c1a8dSHiroo HAYASHI re_set_fastmap (fastmap, false, buf[0]);
329*820c1a8dSHiroo HAYASHI }
330*820c1a8dSHiroo HAYASHI #endif
331*820c1a8dSHiroo HAYASHI }
332*820c1a8dSHiroo HAYASHI else if (type == SIMPLE_BRACKET)
333*820c1a8dSHiroo HAYASHI {
334*820c1a8dSHiroo HAYASHI int i, ch;
335*820c1a8dSHiroo HAYASHI for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
336*820c1a8dSHiroo HAYASHI {
337*820c1a8dSHiroo HAYASHI int j;
338*820c1a8dSHiroo HAYASHI bitset_word_t w = dfa->nodes[node].opr.sbcset[i];
339*820c1a8dSHiroo HAYASHI for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
340*820c1a8dSHiroo HAYASHI if (w & ((bitset_word_t) 1 << j))
341*820c1a8dSHiroo HAYASHI re_set_fastmap (fastmap, icase, ch);
342*820c1a8dSHiroo HAYASHI }
343*820c1a8dSHiroo HAYASHI }
344*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
345*820c1a8dSHiroo HAYASHI else if (type == COMPLEX_BRACKET)
346*820c1a8dSHiroo HAYASHI {
347*820c1a8dSHiroo HAYASHI re_charset_t *cset = dfa->nodes[node].opr.mbcset;
348*820c1a8dSHiroo HAYASHI Idx i;
349*820c1a8dSHiroo HAYASHI
350*820c1a8dSHiroo HAYASHI # ifdef _LIBC
351*820c1a8dSHiroo HAYASHI /* See if we have to try all bytes which start multiple collation
352*820c1a8dSHiroo HAYASHI elements.
353*820c1a8dSHiroo HAYASHI e.g. In da_DK, we want to catch 'a' since "aa" is a valid
354*820c1a8dSHiroo HAYASHI collation element, and don't catch 'b' since 'b' is
355*820c1a8dSHiroo HAYASHI the only collation element which starts from 'b' (and
356*820c1a8dSHiroo HAYASHI it is caught by SIMPLE_BRACKET). */
357*820c1a8dSHiroo HAYASHI if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0
358*820c1a8dSHiroo HAYASHI && (cset->ncoll_syms || cset->nranges))
359*820c1a8dSHiroo HAYASHI {
360*820c1a8dSHiroo HAYASHI const int32_t *table = (const int32_t *)
361*820c1a8dSHiroo HAYASHI _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
362*820c1a8dSHiroo HAYASHI for (i = 0; i < SBC_MAX; ++i)
363*820c1a8dSHiroo HAYASHI if (table[i] < 0)
364*820c1a8dSHiroo HAYASHI re_set_fastmap (fastmap, icase, i);
365*820c1a8dSHiroo HAYASHI }
366*820c1a8dSHiroo HAYASHI # endif /* _LIBC */
367*820c1a8dSHiroo HAYASHI
368*820c1a8dSHiroo HAYASHI /* See if we have to start the match at all multibyte characters,
369*820c1a8dSHiroo HAYASHI i.e. where we would not find an invalid sequence. This only
370*820c1a8dSHiroo HAYASHI applies to multibyte character sets; for single byte character
371*820c1a8dSHiroo HAYASHI sets, the SIMPLE_BRACKET again suffices. */
372*820c1a8dSHiroo HAYASHI if (dfa->mb_cur_max > 1
373*820c1a8dSHiroo HAYASHI && (cset->nchar_classes || cset->non_match || cset->nranges
374*820c1a8dSHiroo HAYASHI # ifdef _LIBC
375*820c1a8dSHiroo HAYASHI || cset->nequiv_classes
376*820c1a8dSHiroo HAYASHI # endif /* _LIBC */
377*820c1a8dSHiroo HAYASHI ))
378*820c1a8dSHiroo HAYASHI {
379*820c1a8dSHiroo HAYASHI unsigned char c = 0;
380*820c1a8dSHiroo HAYASHI do
381*820c1a8dSHiroo HAYASHI {
382*820c1a8dSHiroo HAYASHI mbstate_t mbs;
383*820c1a8dSHiroo HAYASHI memset (&mbs, 0, sizeof (mbs));
384*820c1a8dSHiroo HAYASHI if (__mbrtowc (NULL, (char *) &c, 1, &mbs) == (size_t) -2)
385*820c1a8dSHiroo HAYASHI re_set_fastmap (fastmap, false, (int) c);
386*820c1a8dSHiroo HAYASHI }
387*820c1a8dSHiroo HAYASHI while (++c != 0);
388*820c1a8dSHiroo HAYASHI }
389*820c1a8dSHiroo HAYASHI
390*820c1a8dSHiroo HAYASHI else
391*820c1a8dSHiroo HAYASHI {
392*820c1a8dSHiroo HAYASHI /* ... Else catch all bytes which can start the mbchars. */
393*820c1a8dSHiroo HAYASHI for (i = 0; i < cset->nmbchars; ++i)
394*820c1a8dSHiroo HAYASHI {
395*820c1a8dSHiroo HAYASHI char buf[256];
396*820c1a8dSHiroo HAYASHI mbstate_t state;
397*820c1a8dSHiroo HAYASHI memset (&state, '\0', sizeof (state));
398*820c1a8dSHiroo HAYASHI if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1)
399*820c1a8dSHiroo HAYASHI re_set_fastmap (fastmap, icase, *(unsigned char *) buf);
400*820c1a8dSHiroo HAYASHI if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)
401*820c1a8dSHiroo HAYASHI {
402*820c1a8dSHiroo HAYASHI if (__wcrtomb (buf, __towlower (cset->mbchars[i]), &state)
403*820c1a8dSHiroo HAYASHI != (size_t) -1)
404*820c1a8dSHiroo HAYASHI re_set_fastmap (fastmap, false, *(unsigned char *) buf);
405*820c1a8dSHiroo HAYASHI }
406*820c1a8dSHiroo HAYASHI }
407*820c1a8dSHiroo HAYASHI }
408*820c1a8dSHiroo HAYASHI }
409*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
410*820c1a8dSHiroo HAYASHI else if (type == OP_PERIOD
411*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
412*820c1a8dSHiroo HAYASHI || type == OP_UTF8_PERIOD
413*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
414*820c1a8dSHiroo HAYASHI || type == END_OF_RE)
415*820c1a8dSHiroo HAYASHI {
416*820c1a8dSHiroo HAYASHI memset (fastmap, '\1', sizeof (char) * SBC_MAX);
417*820c1a8dSHiroo HAYASHI if (type == END_OF_RE)
418*820c1a8dSHiroo HAYASHI bufp->can_be_null = 1;
419*820c1a8dSHiroo HAYASHI return;
420*820c1a8dSHiroo HAYASHI }
421*820c1a8dSHiroo HAYASHI }
422*820c1a8dSHiroo HAYASHI }
423*820c1a8dSHiroo HAYASHI
424*820c1a8dSHiroo HAYASHI /* Entry point for POSIX code. */
425*820c1a8dSHiroo HAYASHI /* regcomp takes a regular expression as a string and compiles it.
426*820c1a8dSHiroo HAYASHI
427*820c1a8dSHiroo HAYASHI PREG is a regex_t *. We do not expect any fields to be initialized,
428*820c1a8dSHiroo HAYASHI since POSIX says we shouldn't. Thus, we set
429*820c1a8dSHiroo HAYASHI
430*820c1a8dSHiroo HAYASHI 'buffer' to the compiled pattern;
431*820c1a8dSHiroo HAYASHI 'used' to the length of the compiled pattern;
432*820c1a8dSHiroo HAYASHI 'syntax' to RE_SYNTAX_POSIX_EXTENDED if the
433*820c1a8dSHiroo HAYASHI REG_EXTENDED bit in CFLAGS is set; otherwise, to
434*820c1a8dSHiroo HAYASHI RE_SYNTAX_POSIX_BASIC;
435*820c1a8dSHiroo HAYASHI 'newline_anchor' to REG_NEWLINE being set in CFLAGS;
436*820c1a8dSHiroo HAYASHI 'fastmap' to an allocated space for the fastmap;
437*820c1a8dSHiroo HAYASHI 'fastmap_accurate' to zero;
438*820c1a8dSHiroo HAYASHI 're_nsub' to the number of subexpressions in PATTERN.
439*820c1a8dSHiroo HAYASHI
440*820c1a8dSHiroo HAYASHI PATTERN is the address of the pattern string.
441*820c1a8dSHiroo HAYASHI
442*820c1a8dSHiroo HAYASHI CFLAGS is a series of bits which affect compilation.
443*820c1a8dSHiroo HAYASHI
444*820c1a8dSHiroo HAYASHI If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we
445*820c1a8dSHiroo HAYASHI use POSIX basic syntax.
446*820c1a8dSHiroo HAYASHI
447*820c1a8dSHiroo HAYASHI If REG_NEWLINE is set, then . and [^...] don't match newline.
448*820c1a8dSHiroo HAYASHI Also, regexec will try a match beginning after every newline.
449*820c1a8dSHiroo HAYASHI
450*820c1a8dSHiroo HAYASHI If REG_ICASE is set, then we considers upper- and lowercase
451*820c1a8dSHiroo HAYASHI versions of letters to be equivalent when matching.
452*820c1a8dSHiroo HAYASHI
453*820c1a8dSHiroo HAYASHI If REG_NOSUB is set, then when PREG is passed to regexec, that
454*820c1a8dSHiroo HAYASHI routine will report only success or failure, and nothing about the
455*820c1a8dSHiroo HAYASHI registers.
456*820c1a8dSHiroo HAYASHI
457*820c1a8dSHiroo HAYASHI It returns 0 if it succeeds, nonzero if it doesn't. (See regex.h for
458*820c1a8dSHiroo HAYASHI the return codes and their meanings.) */
459*820c1a8dSHiroo HAYASHI
460*820c1a8dSHiroo HAYASHI int
regcomp(regex_t * __restrict preg,const char * __restrict pattern,int cflags)461*820c1a8dSHiroo HAYASHI regcomp (regex_t *__restrict preg, const char *__restrict pattern, int cflags)
462*820c1a8dSHiroo HAYASHI {
463*820c1a8dSHiroo HAYASHI reg_errcode_t ret;
464*820c1a8dSHiroo HAYASHI reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED
465*820c1a8dSHiroo HAYASHI : RE_SYNTAX_POSIX_BASIC);
466*820c1a8dSHiroo HAYASHI
467*820c1a8dSHiroo HAYASHI preg->buffer = NULL;
468*820c1a8dSHiroo HAYASHI preg->allocated = 0;
469*820c1a8dSHiroo HAYASHI preg->used = 0;
470*820c1a8dSHiroo HAYASHI
471*820c1a8dSHiroo HAYASHI /* Try to allocate space for the fastmap. */
472*820c1a8dSHiroo HAYASHI preg->fastmap = re_malloc (char, SBC_MAX);
473*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (preg->fastmap == NULL))
474*820c1a8dSHiroo HAYASHI return REG_ESPACE;
475*820c1a8dSHiroo HAYASHI
476*820c1a8dSHiroo HAYASHI syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0;
477*820c1a8dSHiroo HAYASHI
478*820c1a8dSHiroo HAYASHI /* If REG_NEWLINE is set, newlines are treated differently. */
479*820c1a8dSHiroo HAYASHI if (cflags & REG_NEWLINE)
480*820c1a8dSHiroo HAYASHI { /* REG_NEWLINE implies neither . nor [^...] match newline. */
481*820c1a8dSHiroo HAYASHI syntax &= ~RE_DOT_NEWLINE;
482*820c1a8dSHiroo HAYASHI syntax |= RE_HAT_LISTS_NOT_NEWLINE;
483*820c1a8dSHiroo HAYASHI /* It also changes the matching behavior. */
484*820c1a8dSHiroo HAYASHI preg->newline_anchor = 1;
485*820c1a8dSHiroo HAYASHI }
486*820c1a8dSHiroo HAYASHI else
487*820c1a8dSHiroo HAYASHI preg->newline_anchor = 0;
488*820c1a8dSHiroo HAYASHI preg->no_sub = !!(cflags & REG_NOSUB);
489*820c1a8dSHiroo HAYASHI preg->translate = NULL;
490*820c1a8dSHiroo HAYASHI
491*820c1a8dSHiroo HAYASHI ret = re_compile_internal (preg, pattern, strlen (pattern), syntax);
492*820c1a8dSHiroo HAYASHI
493*820c1a8dSHiroo HAYASHI /* POSIX doesn't distinguish between an unmatched open-group and an
494*820c1a8dSHiroo HAYASHI unmatched close-group: both are REG_EPAREN. */
495*820c1a8dSHiroo HAYASHI if (ret == REG_ERPAREN)
496*820c1a8dSHiroo HAYASHI ret = REG_EPAREN;
497*820c1a8dSHiroo HAYASHI
498*820c1a8dSHiroo HAYASHI /* We have already checked preg->fastmap != NULL. */
499*820c1a8dSHiroo HAYASHI if (__glibc_likely (ret == REG_NOERROR))
500*820c1a8dSHiroo HAYASHI /* Compute the fastmap now, since regexec cannot modify the pattern
501*820c1a8dSHiroo HAYASHI buffer. This function never fails in this implementation. */
502*820c1a8dSHiroo HAYASHI (void) re_compile_fastmap (preg);
503*820c1a8dSHiroo HAYASHI else
504*820c1a8dSHiroo HAYASHI {
505*820c1a8dSHiroo HAYASHI /* Some error occurred while compiling the expression. */
506*820c1a8dSHiroo HAYASHI re_free (preg->fastmap);
507*820c1a8dSHiroo HAYASHI preg->fastmap = NULL;
508*820c1a8dSHiroo HAYASHI }
509*820c1a8dSHiroo HAYASHI
510*820c1a8dSHiroo HAYASHI return (int) ret;
511*820c1a8dSHiroo HAYASHI }
512*820c1a8dSHiroo HAYASHI libc_hidden_def (__regcomp)
weak_alias(__regcomp,regcomp)513*820c1a8dSHiroo HAYASHI weak_alias (__regcomp, regcomp)
514*820c1a8dSHiroo HAYASHI
515*820c1a8dSHiroo HAYASHI /* Returns a message corresponding to an error code, ERRCODE, returned
516*820c1a8dSHiroo HAYASHI from either regcomp or regexec. We don't use PREG here. */
517*820c1a8dSHiroo HAYASHI
518*820c1a8dSHiroo HAYASHI size_t
519*820c1a8dSHiroo HAYASHI regerror (int errcode, const regex_t *__restrict preg, char *__restrict errbuf,
520*820c1a8dSHiroo HAYASHI size_t errbuf_size)
521*820c1a8dSHiroo HAYASHI {
522*820c1a8dSHiroo HAYASHI const char *msg;
523*820c1a8dSHiroo HAYASHI size_t msg_size;
524*820c1a8dSHiroo HAYASHI int nerrcodes = sizeof __re_error_msgid_idx / sizeof __re_error_msgid_idx[0];
525*820c1a8dSHiroo HAYASHI
526*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (errcode < 0 || errcode >= nerrcodes))
527*820c1a8dSHiroo HAYASHI /* Only error codes returned by the rest of the code should be passed
528*820c1a8dSHiroo HAYASHI to this routine. If we are given anything else, or if other regex
529*820c1a8dSHiroo HAYASHI code generates an invalid error code, then the program has a bug.
530*820c1a8dSHiroo HAYASHI Dump core so we can fix it. */
531*820c1a8dSHiroo HAYASHI abort ();
532*820c1a8dSHiroo HAYASHI
533*820c1a8dSHiroo HAYASHI msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]);
534*820c1a8dSHiroo HAYASHI
535*820c1a8dSHiroo HAYASHI msg_size = strlen (msg) + 1; /* Includes the null. */
536*820c1a8dSHiroo HAYASHI
537*820c1a8dSHiroo HAYASHI if (__glibc_likely (errbuf_size != 0))
538*820c1a8dSHiroo HAYASHI {
539*820c1a8dSHiroo HAYASHI size_t cpy_size = msg_size;
540*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (msg_size > errbuf_size))
541*820c1a8dSHiroo HAYASHI {
542*820c1a8dSHiroo HAYASHI cpy_size = errbuf_size - 1;
543*820c1a8dSHiroo HAYASHI errbuf[cpy_size] = '\0';
544*820c1a8dSHiroo HAYASHI }
545*820c1a8dSHiroo HAYASHI memcpy (errbuf, msg, cpy_size);
546*820c1a8dSHiroo HAYASHI }
547*820c1a8dSHiroo HAYASHI
548*820c1a8dSHiroo HAYASHI return msg_size;
549*820c1a8dSHiroo HAYASHI }
550*820c1a8dSHiroo HAYASHI weak_alias (__regerror, regerror)
551*820c1a8dSHiroo HAYASHI
552*820c1a8dSHiroo HAYASHI
553*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
554*820c1a8dSHiroo HAYASHI /* This static array is used for the map to single-byte characters when
555*820c1a8dSHiroo HAYASHI UTF-8 is used. Otherwise we would allocate memory just to initialize
556*820c1a8dSHiroo HAYASHI it the same all the time. UTF-8 is the preferred encoding so this is
557*820c1a8dSHiroo HAYASHI a worthwhile optimization. */
558*820c1a8dSHiroo HAYASHI static const bitset_t utf8_sb_map =
559*820c1a8dSHiroo HAYASHI {
560*820c1a8dSHiroo HAYASHI /* Set the first 128 bits. */
561*820c1a8dSHiroo HAYASHI # if (defined __GNUC__ || __clang_major__ >= 4) && !defined __STRICT_ANSI__
562*820c1a8dSHiroo HAYASHI [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX
563*820c1a8dSHiroo HAYASHI # else
564*820c1a8dSHiroo HAYASHI # if 4 * BITSET_WORD_BITS < ASCII_CHARS
565*820c1a8dSHiroo HAYASHI # error "bitset_word_t is narrower than 32 bits"
566*820c1a8dSHiroo HAYASHI # elif 3 * BITSET_WORD_BITS < ASCII_CHARS
567*820c1a8dSHiroo HAYASHI BITSET_WORD_MAX, BITSET_WORD_MAX, BITSET_WORD_MAX,
568*820c1a8dSHiroo HAYASHI # elif 2 * BITSET_WORD_BITS < ASCII_CHARS
569*820c1a8dSHiroo HAYASHI BITSET_WORD_MAX, BITSET_WORD_MAX,
570*820c1a8dSHiroo HAYASHI # elif 1 * BITSET_WORD_BITS < ASCII_CHARS
571*820c1a8dSHiroo HAYASHI BITSET_WORD_MAX,
572*820c1a8dSHiroo HAYASHI # endif
573*820c1a8dSHiroo HAYASHI (BITSET_WORD_MAX
574*820c1a8dSHiroo HAYASHI >> (SBC_MAX % BITSET_WORD_BITS == 0
575*820c1a8dSHiroo HAYASHI ? 0
576*820c1a8dSHiroo HAYASHI : BITSET_WORD_BITS - SBC_MAX % BITSET_WORD_BITS))
577*820c1a8dSHiroo HAYASHI # endif
578*820c1a8dSHiroo HAYASHI };
579*820c1a8dSHiroo HAYASHI #endif
580*820c1a8dSHiroo HAYASHI
581*820c1a8dSHiroo HAYASHI
582*820c1a8dSHiroo HAYASHI static void
free_dfa_content(re_dfa_t * dfa)583*820c1a8dSHiroo HAYASHI free_dfa_content (re_dfa_t *dfa)
584*820c1a8dSHiroo HAYASHI {
585*820c1a8dSHiroo HAYASHI Idx i, j;
586*820c1a8dSHiroo HAYASHI
587*820c1a8dSHiroo HAYASHI if (dfa->nodes)
588*820c1a8dSHiroo HAYASHI for (i = 0; i < dfa->nodes_len; ++i)
589*820c1a8dSHiroo HAYASHI free_token (dfa->nodes + i);
590*820c1a8dSHiroo HAYASHI re_free (dfa->nexts);
591*820c1a8dSHiroo HAYASHI for (i = 0; i < dfa->nodes_len; ++i)
592*820c1a8dSHiroo HAYASHI {
593*820c1a8dSHiroo HAYASHI if (dfa->eclosures != NULL)
594*820c1a8dSHiroo HAYASHI re_node_set_free (dfa->eclosures + i);
595*820c1a8dSHiroo HAYASHI if (dfa->inveclosures != NULL)
596*820c1a8dSHiroo HAYASHI re_node_set_free (dfa->inveclosures + i);
597*820c1a8dSHiroo HAYASHI if (dfa->edests != NULL)
598*820c1a8dSHiroo HAYASHI re_node_set_free (dfa->edests + i);
599*820c1a8dSHiroo HAYASHI }
600*820c1a8dSHiroo HAYASHI re_free (dfa->edests);
601*820c1a8dSHiroo HAYASHI re_free (dfa->eclosures);
602*820c1a8dSHiroo HAYASHI re_free (dfa->inveclosures);
603*820c1a8dSHiroo HAYASHI re_free (dfa->nodes);
604*820c1a8dSHiroo HAYASHI
605*820c1a8dSHiroo HAYASHI if (dfa->state_table)
606*820c1a8dSHiroo HAYASHI for (i = 0; i <= dfa->state_hash_mask; ++i)
607*820c1a8dSHiroo HAYASHI {
608*820c1a8dSHiroo HAYASHI struct re_state_table_entry *entry = dfa->state_table + i;
609*820c1a8dSHiroo HAYASHI for (j = 0; j < entry->num; ++j)
610*820c1a8dSHiroo HAYASHI {
611*820c1a8dSHiroo HAYASHI re_dfastate_t *state = entry->array[j];
612*820c1a8dSHiroo HAYASHI free_state (state);
613*820c1a8dSHiroo HAYASHI }
614*820c1a8dSHiroo HAYASHI re_free (entry->array);
615*820c1a8dSHiroo HAYASHI }
616*820c1a8dSHiroo HAYASHI re_free (dfa->state_table);
617*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
618*820c1a8dSHiroo HAYASHI if (dfa->sb_char != utf8_sb_map)
619*820c1a8dSHiroo HAYASHI re_free (dfa->sb_char);
620*820c1a8dSHiroo HAYASHI #endif
621*820c1a8dSHiroo HAYASHI re_free (dfa->subexp_map);
622*820c1a8dSHiroo HAYASHI #ifdef DEBUG
623*820c1a8dSHiroo HAYASHI re_free (dfa->re_str);
624*820c1a8dSHiroo HAYASHI #endif
625*820c1a8dSHiroo HAYASHI
626*820c1a8dSHiroo HAYASHI re_free (dfa);
627*820c1a8dSHiroo HAYASHI }
628*820c1a8dSHiroo HAYASHI
629*820c1a8dSHiroo HAYASHI
630*820c1a8dSHiroo HAYASHI /* Free dynamically allocated space used by PREG. */
631*820c1a8dSHiroo HAYASHI
632*820c1a8dSHiroo HAYASHI void
regfree(regex_t * preg)633*820c1a8dSHiroo HAYASHI regfree (regex_t *preg)
634*820c1a8dSHiroo HAYASHI {
635*820c1a8dSHiroo HAYASHI re_dfa_t *dfa = preg->buffer;
636*820c1a8dSHiroo HAYASHI if (__glibc_likely (dfa != NULL))
637*820c1a8dSHiroo HAYASHI {
638*820c1a8dSHiroo HAYASHI lock_fini (dfa->lock);
639*820c1a8dSHiroo HAYASHI free_dfa_content (dfa);
640*820c1a8dSHiroo HAYASHI }
641*820c1a8dSHiroo HAYASHI preg->buffer = NULL;
642*820c1a8dSHiroo HAYASHI preg->allocated = 0;
643*820c1a8dSHiroo HAYASHI
644*820c1a8dSHiroo HAYASHI re_free (preg->fastmap);
645*820c1a8dSHiroo HAYASHI preg->fastmap = NULL;
646*820c1a8dSHiroo HAYASHI
647*820c1a8dSHiroo HAYASHI re_free (preg->translate);
648*820c1a8dSHiroo HAYASHI preg->translate = NULL;
649*820c1a8dSHiroo HAYASHI }
650*820c1a8dSHiroo HAYASHI libc_hidden_def (__regfree)
651*820c1a8dSHiroo HAYASHI weak_alias (__regfree, regfree)
652*820c1a8dSHiroo HAYASHI
653*820c1a8dSHiroo HAYASHI /* Entry points compatible with 4.2 BSD regex library. We don't define
654*820c1a8dSHiroo HAYASHI them unless specifically requested. */
655*820c1a8dSHiroo HAYASHI
656*820c1a8dSHiroo HAYASHI #if defined _REGEX_RE_COMP || defined _LIBC
657*820c1a8dSHiroo HAYASHI
658*820c1a8dSHiroo HAYASHI /* BSD has one and only one pattern buffer. */
659*820c1a8dSHiroo HAYASHI static struct re_pattern_buffer re_comp_buf;
660*820c1a8dSHiroo HAYASHI
661*820c1a8dSHiroo HAYASHI char *
662*820c1a8dSHiroo HAYASHI # ifdef _LIBC
663*820c1a8dSHiroo HAYASHI /* Make these definitions weak in libc, so POSIX programs can redefine
664*820c1a8dSHiroo HAYASHI these names if they don't use our functions, and still use
665*820c1a8dSHiroo HAYASHI regcomp/regexec above without link errors. */
666*820c1a8dSHiroo HAYASHI weak_function
667*820c1a8dSHiroo HAYASHI # endif
re_comp(const char * s)668*820c1a8dSHiroo HAYASHI re_comp (const char *s)
669*820c1a8dSHiroo HAYASHI {
670*820c1a8dSHiroo HAYASHI reg_errcode_t ret;
671*820c1a8dSHiroo HAYASHI char *fastmap;
672*820c1a8dSHiroo HAYASHI
673*820c1a8dSHiroo HAYASHI if (!s)
674*820c1a8dSHiroo HAYASHI {
675*820c1a8dSHiroo HAYASHI if (!re_comp_buf.buffer)
676*820c1a8dSHiroo HAYASHI return gettext ("No previous regular expression");
677*820c1a8dSHiroo HAYASHI return 0;
678*820c1a8dSHiroo HAYASHI }
679*820c1a8dSHiroo HAYASHI
680*820c1a8dSHiroo HAYASHI if (re_comp_buf.buffer)
681*820c1a8dSHiroo HAYASHI {
682*820c1a8dSHiroo HAYASHI fastmap = re_comp_buf.fastmap;
683*820c1a8dSHiroo HAYASHI re_comp_buf.fastmap = NULL;
684*820c1a8dSHiroo HAYASHI __regfree (&re_comp_buf);
685*820c1a8dSHiroo HAYASHI memset (&re_comp_buf, '\0', sizeof (re_comp_buf));
686*820c1a8dSHiroo HAYASHI re_comp_buf.fastmap = fastmap;
687*820c1a8dSHiroo HAYASHI }
688*820c1a8dSHiroo HAYASHI
689*820c1a8dSHiroo HAYASHI if (re_comp_buf.fastmap == NULL)
690*820c1a8dSHiroo HAYASHI {
691*820c1a8dSHiroo HAYASHI re_comp_buf.fastmap = re_malloc (char, SBC_MAX);
692*820c1a8dSHiroo HAYASHI if (re_comp_buf.fastmap == NULL)
693*820c1a8dSHiroo HAYASHI return (char *) gettext (__re_error_msgid
694*820c1a8dSHiroo HAYASHI + __re_error_msgid_idx[(int) REG_ESPACE]);
695*820c1a8dSHiroo HAYASHI }
696*820c1a8dSHiroo HAYASHI
697*820c1a8dSHiroo HAYASHI /* Since 're_exec' always passes NULL for the 'regs' argument, we
698*820c1a8dSHiroo HAYASHI don't need to initialize the pattern buffer fields which affect it. */
699*820c1a8dSHiroo HAYASHI
700*820c1a8dSHiroo HAYASHI /* Match anchors at newlines. */
701*820c1a8dSHiroo HAYASHI re_comp_buf.newline_anchor = 1;
702*820c1a8dSHiroo HAYASHI
703*820c1a8dSHiroo HAYASHI ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options);
704*820c1a8dSHiroo HAYASHI
705*820c1a8dSHiroo HAYASHI if (!ret)
706*820c1a8dSHiroo HAYASHI return NULL;
707*820c1a8dSHiroo HAYASHI
708*820c1a8dSHiroo HAYASHI /* Yes, we're discarding 'const' here if !HAVE_LIBINTL. */
709*820c1a8dSHiroo HAYASHI return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);
710*820c1a8dSHiroo HAYASHI }
711*820c1a8dSHiroo HAYASHI
712*820c1a8dSHiroo HAYASHI #ifdef _LIBC
libc_freeres_fn(free_mem)713*820c1a8dSHiroo HAYASHI libc_freeres_fn (free_mem)
714*820c1a8dSHiroo HAYASHI {
715*820c1a8dSHiroo HAYASHI __regfree (&re_comp_buf);
716*820c1a8dSHiroo HAYASHI }
717*820c1a8dSHiroo HAYASHI #endif
718*820c1a8dSHiroo HAYASHI
719*820c1a8dSHiroo HAYASHI #endif /* _REGEX_RE_COMP */
720*820c1a8dSHiroo HAYASHI
721*820c1a8dSHiroo HAYASHI /* Internal entry point.
722*820c1a8dSHiroo HAYASHI Compile the regular expression PATTERN, whose length is LENGTH.
723*820c1a8dSHiroo HAYASHI SYNTAX indicate regular expression's syntax. */
724*820c1a8dSHiroo HAYASHI
725*820c1a8dSHiroo HAYASHI static reg_errcode_t
re_compile_internal(regex_t * preg,const char * pattern,size_t length,reg_syntax_t syntax)726*820c1a8dSHiroo HAYASHI re_compile_internal (regex_t *preg, const char * pattern, size_t length,
727*820c1a8dSHiroo HAYASHI reg_syntax_t syntax)
728*820c1a8dSHiroo HAYASHI {
729*820c1a8dSHiroo HAYASHI reg_errcode_t err = REG_NOERROR;
730*820c1a8dSHiroo HAYASHI re_dfa_t *dfa;
731*820c1a8dSHiroo HAYASHI re_string_t regexp;
732*820c1a8dSHiroo HAYASHI
733*820c1a8dSHiroo HAYASHI /* Initialize the pattern buffer. */
734*820c1a8dSHiroo HAYASHI preg->fastmap_accurate = 0;
735*820c1a8dSHiroo HAYASHI preg->syntax = syntax;
736*820c1a8dSHiroo HAYASHI preg->not_bol = preg->not_eol = 0;
737*820c1a8dSHiroo HAYASHI preg->used = 0;
738*820c1a8dSHiroo HAYASHI preg->re_nsub = 0;
739*820c1a8dSHiroo HAYASHI preg->can_be_null = 0;
740*820c1a8dSHiroo HAYASHI preg->regs_allocated = REGS_UNALLOCATED;
741*820c1a8dSHiroo HAYASHI
742*820c1a8dSHiroo HAYASHI /* Initialize the dfa. */
743*820c1a8dSHiroo HAYASHI dfa = preg->buffer;
744*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (preg->allocated < sizeof (re_dfa_t)))
745*820c1a8dSHiroo HAYASHI {
746*820c1a8dSHiroo HAYASHI /* If zero allocated, but buffer is non-null, try to realloc
747*820c1a8dSHiroo HAYASHI enough space. This loses if buffer's address is bogus, but
748*820c1a8dSHiroo HAYASHI that is the user's responsibility. If ->buffer is NULL this
749*820c1a8dSHiroo HAYASHI is a simple allocation. */
750*820c1a8dSHiroo HAYASHI dfa = re_realloc (preg->buffer, re_dfa_t, 1);
751*820c1a8dSHiroo HAYASHI if (dfa == NULL)
752*820c1a8dSHiroo HAYASHI return REG_ESPACE;
753*820c1a8dSHiroo HAYASHI preg->allocated = sizeof (re_dfa_t);
754*820c1a8dSHiroo HAYASHI preg->buffer = dfa;
755*820c1a8dSHiroo HAYASHI }
756*820c1a8dSHiroo HAYASHI preg->used = sizeof (re_dfa_t);
757*820c1a8dSHiroo HAYASHI
758*820c1a8dSHiroo HAYASHI err = init_dfa (dfa, length);
759*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (err == REG_NOERROR && lock_init (dfa->lock) != 0))
760*820c1a8dSHiroo HAYASHI err = REG_ESPACE;
761*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (err != REG_NOERROR))
762*820c1a8dSHiroo HAYASHI {
763*820c1a8dSHiroo HAYASHI free_dfa_content (dfa);
764*820c1a8dSHiroo HAYASHI preg->buffer = NULL;
765*820c1a8dSHiroo HAYASHI preg->allocated = 0;
766*820c1a8dSHiroo HAYASHI return err;
767*820c1a8dSHiroo HAYASHI }
768*820c1a8dSHiroo HAYASHI #ifdef DEBUG
769*820c1a8dSHiroo HAYASHI /* Note: length+1 will not overflow since it is checked in init_dfa. */
770*820c1a8dSHiroo HAYASHI dfa->re_str = re_malloc (char, length + 1);
771*820c1a8dSHiroo HAYASHI strncpy (dfa->re_str, pattern, length + 1);
772*820c1a8dSHiroo HAYASHI #endif
773*820c1a8dSHiroo HAYASHI
774*820c1a8dSHiroo HAYASHI err = re_string_construct (®exp, pattern, length, preg->translate,
775*820c1a8dSHiroo HAYASHI (syntax & RE_ICASE) != 0, dfa);
776*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (err != REG_NOERROR))
777*820c1a8dSHiroo HAYASHI {
778*820c1a8dSHiroo HAYASHI re_compile_internal_free_return:
779*820c1a8dSHiroo HAYASHI free_workarea_compile (preg);
780*820c1a8dSHiroo HAYASHI re_string_destruct (®exp);
781*820c1a8dSHiroo HAYASHI lock_fini (dfa->lock);
782*820c1a8dSHiroo HAYASHI free_dfa_content (dfa);
783*820c1a8dSHiroo HAYASHI preg->buffer = NULL;
784*820c1a8dSHiroo HAYASHI preg->allocated = 0;
785*820c1a8dSHiroo HAYASHI return err;
786*820c1a8dSHiroo HAYASHI }
787*820c1a8dSHiroo HAYASHI
788*820c1a8dSHiroo HAYASHI /* Parse the regular expression, and build a structure tree. */
789*820c1a8dSHiroo HAYASHI preg->re_nsub = 0;
790*820c1a8dSHiroo HAYASHI dfa->str_tree = parse (®exp, preg, syntax, &err);
791*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (dfa->str_tree == NULL))
792*820c1a8dSHiroo HAYASHI goto re_compile_internal_free_return;
793*820c1a8dSHiroo HAYASHI
794*820c1a8dSHiroo HAYASHI /* Analyze the tree and create the nfa. */
795*820c1a8dSHiroo HAYASHI err = analyze (preg);
796*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (err != REG_NOERROR))
797*820c1a8dSHiroo HAYASHI goto re_compile_internal_free_return;
798*820c1a8dSHiroo HAYASHI
799*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
800*820c1a8dSHiroo HAYASHI /* If possible, do searching in single byte encoding to speed things up. */
801*820c1a8dSHiroo HAYASHI if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL)
802*820c1a8dSHiroo HAYASHI optimize_utf8 (dfa);
803*820c1a8dSHiroo HAYASHI #endif
804*820c1a8dSHiroo HAYASHI
805*820c1a8dSHiroo HAYASHI /* Then create the initial state of the dfa. */
806*820c1a8dSHiroo HAYASHI err = create_initial_state (dfa);
807*820c1a8dSHiroo HAYASHI
808*820c1a8dSHiroo HAYASHI /* Release work areas. */
809*820c1a8dSHiroo HAYASHI free_workarea_compile (preg);
810*820c1a8dSHiroo HAYASHI re_string_destruct (®exp);
811*820c1a8dSHiroo HAYASHI
812*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (err != REG_NOERROR))
813*820c1a8dSHiroo HAYASHI {
814*820c1a8dSHiroo HAYASHI lock_fini (dfa->lock);
815*820c1a8dSHiroo HAYASHI free_dfa_content (dfa);
816*820c1a8dSHiroo HAYASHI preg->buffer = NULL;
817*820c1a8dSHiroo HAYASHI preg->allocated = 0;
818*820c1a8dSHiroo HAYASHI }
819*820c1a8dSHiroo HAYASHI
820*820c1a8dSHiroo HAYASHI return err;
821*820c1a8dSHiroo HAYASHI }
822*820c1a8dSHiroo HAYASHI
823*820c1a8dSHiroo HAYASHI /* Initialize DFA. We use the length of the regular expression PAT_LEN
824*820c1a8dSHiroo HAYASHI as the initial length of some arrays. */
825*820c1a8dSHiroo HAYASHI
826*820c1a8dSHiroo HAYASHI static reg_errcode_t
init_dfa(re_dfa_t * dfa,size_t pat_len)827*820c1a8dSHiroo HAYASHI init_dfa (re_dfa_t *dfa, size_t pat_len)
828*820c1a8dSHiroo HAYASHI {
829*820c1a8dSHiroo HAYASHI __re_size_t table_size;
830*820c1a8dSHiroo HAYASHI #ifndef _LIBC
831*820c1a8dSHiroo HAYASHI const char *codeset_name;
832*820c1a8dSHiroo HAYASHI #endif
833*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
834*820c1a8dSHiroo HAYASHI size_t max_i18n_object_size = MAX (sizeof (wchar_t), sizeof (wctype_t));
835*820c1a8dSHiroo HAYASHI #else
836*820c1a8dSHiroo HAYASHI size_t max_i18n_object_size = 0;
837*820c1a8dSHiroo HAYASHI #endif
838*820c1a8dSHiroo HAYASHI size_t max_object_size =
839*820c1a8dSHiroo HAYASHI MAX (sizeof (struct re_state_table_entry),
840*820c1a8dSHiroo HAYASHI MAX (sizeof (re_token_t),
841*820c1a8dSHiroo HAYASHI MAX (sizeof (re_node_set),
842*820c1a8dSHiroo HAYASHI MAX (sizeof (regmatch_t),
843*820c1a8dSHiroo HAYASHI max_i18n_object_size))));
844*820c1a8dSHiroo HAYASHI
845*820c1a8dSHiroo HAYASHI memset (dfa, '\0', sizeof (re_dfa_t));
846*820c1a8dSHiroo HAYASHI
847*820c1a8dSHiroo HAYASHI /* Force allocation of str_tree_storage the first time. */
848*820c1a8dSHiroo HAYASHI dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;
849*820c1a8dSHiroo HAYASHI
850*820c1a8dSHiroo HAYASHI /* Avoid overflows. The extra "/ 2" is for the table_size doubling
851*820c1a8dSHiroo HAYASHI calculation below, and for similar doubling calculations
852*820c1a8dSHiroo HAYASHI elsewhere. And it's <= rather than <, because some of the
853*820c1a8dSHiroo HAYASHI doubling calculations add 1 afterwards. */
854*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (MIN (IDX_MAX, SIZE_MAX / max_object_size) / 2
855*820c1a8dSHiroo HAYASHI <= pat_len))
856*820c1a8dSHiroo HAYASHI return REG_ESPACE;
857*820c1a8dSHiroo HAYASHI
858*820c1a8dSHiroo HAYASHI dfa->nodes_alloc = pat_len + 1;
859*820c1a8dSHiroo HAYASHI dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc);
860*820c1a8dSHiroo HAYASHI
861*820c1a8dSHiroo HAYASHI /* table_size = 2 ^ ceil(log pat_len) */
862*820c1a8dSHiroo HAYASHI for (table_size = 1; ; table_size <<= 1)
863*820c1a8dSHiroo HAYASHI if (table_size > pat_len)
864*820c1a8dSHiroo HAYASHI break;
865*820c1a8dSHiroo HAYASHI
866*820c1a8dSHiroo HAYASHI dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size);
867*820c1a8dSHiroo HAYASHI dfa->state_hash_mask = table_size - 1;
868*820c1a8dSHiroo HAYASHI
869*820c1a8dSHiroo HAYASHI dfa->mb_cur_max = MB_CUR_MAX;
870*820c1a8dSHiroo HAYASHI #ifdef _LIBC
871*820c1a8dSHiroo HAYASHI if (dfa->mb_cur_max == 6
872*820c1a8dSHiroo HAYASHI && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0)
873*820c1a8dSHiroo HAYASHI dfa->is_utf8 = 1;
874*820c1a8dSHiroo HAYASHI dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII)
875*820c1a8dSHiroo HAYASHI != 0);
876*820c1a8dSHiroo HAYASHI #else
877*820c1a8dSHiroo HAYASHI codeset_name = nl_langinfo (CODESET);
878*820c1a8dSHiroo HAYASHI if ((codeset_name[0] == 'U' || codeset_name[0] == 'u')
879*820c1a8dSHiroo HAYASHI && (codeset_name[1] == 'T' || codeset_name[1] == 't')
880*820c1a8dSHiroo HAYASHI && (codeset_name[2] == 'F' || codeset_name[2] == 'f')
881*820c1a8dSHiroo HAYASHI && strcmp (codeset_name + 3 + (codeset_name[3] == '-'), "8") == 0)
882*820c1a8dSHiroo HAYASHI dfa->is_utf8 = 1;
883*820c1a8dSHiroo HAYASHI
884*820c1a8dSHiroo HAYASHI /* We check exhaustively in the loop below if this charset is a
885*820c1a8dSHiroo HAYASHI superset of ASCII. */
886*820c1a8dSHiroo HAYASHI dfa->map_notascii = 0;
887*820c1a8dSHiroo HAYASHI #endif
888*820c1a8dSHiroo HAYASHI
889*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
890*820c1a8dSHiroo HAYASHI if (dfa->mb_cur_max > 1)
891*820c1a8dSHiroo HAYASHI {
892*820c1a8dSHiroo HAYASHI if (dfa->is_utf8)
893*820c1a8dSHiroo HAYASHI dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map;
894*820c1a8dSHiroo HAYASHI else
895*820c1a8dSHiroo HAYASHI {
896*820c1a8dSHiroo HAYASHI int i, j, ch;
897*820c1a8dSHiroo HAYASHI
898*820c1a8dSHiroo HAYASHI dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
899*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (dfa->sb_char == NULL))
900*820c1a8dSHiroo HAYASHI return REG_ESPACE;
901*820c1a8dSHiroo HAYASHI
902*820c1a8dSHiroo HAYASHI /* Set the bits corresponding to single byte chars. */
903*820c1a8dSHiroo HAYASHI for (i = 0, ch = 0; i < BITSET_WORDS; ++i)
904*820c1a8dSHiroo HAYASHI for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
905*820c1a8dSHiroo HAYASHI {
906*820c1a8dSHiroo HAYASHI wint_t wch = __btowc (ch);
907*820c1a8dSHiroo HAYASHI if (wch != WEOF)
908*820c1a8dSHiroo HAYASHI dfa->sb_char[i] |= (bitset_word_t) 1 << j;
909*820c1a8dSHiroo HAYASHI # ifndef _LIBC
910*820c1a8dSHiroo HAYASHI if (isascii (ch) && wch != ch)
911*820c1a8dSHiroo HAYASHI dfa->map_notascii = 1;
912*820c1a8dSHiroo HAYASHI # endif
913*820c1a8dSHiroo HAYASHI }
914*820c1a8dSHiroo HAYASHI }
915*820c1a8dSHiroo HAYASHI }
916*820c1a8dSHiroo HAYASHI #endif
917*820c1a8dSHiroo HAYASHI
918*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (dfa->nodes == NULL || dfa->state_table == NULL))
919*820c1a8dSHiroo HAYASHI return REG_ESPACE;
920*820c1a8dSHiroo HAYASHI return REG_NOERROR;
921*820c1a8dSHiroo HAYASHI }
922*820c1a8dSHiroo HAYASHI
923*820c1a8dSHiroo HAYASHI /* Initialize WORD_CHAR table, which indicate which character is
924*820c1a8dSHiroo HAYASHI "word". In this case "word" means that it is the word construction
925*820c1a8dSHiroo HAYASHI character used by some operators like "\<", "\>", etc. */
926*820c1a8dSHiroo HAYASHI
927*820c1a8dSHiroo HAYASHI static void
init_word_char(re_dfa_t * dfa)928*820c1a8dSHiroo HAYASHI init_word_char (re_dfa_t *dfa)
929*820c1a8dSHiroo HAYASHI {
930*820c1a8dSHiroo HAYASHI int i = 0;
931*820c1a8dSHiroo HAYASHI int j;
932*820c1a8dSHiroo HAYASHI int ch = 0;
933*820c1a8dSHiroo HAYASHI dfa->word_ops_used = 1;
934*820c1a8dSHiroo HAYASHI if (__glibc_likely (dfa->map_notascii == 0))
935*820c1a8dSHiroo HAYASHI {
936*820c1a8dSHiroo HAYASHI /* Avoid uint32_t and uint64_t as some non-GCC platforms lack
937*820c1a8dSHiroo HAYASHI them, an issue when this code is used in Gnulib. */
938*820c1a8dSHiroo HAYASHI bitset_word_t bits0 = 0x00000000;
939*820c1a8dSHiroo HAYASHI bitset_word_t bits1 = 0x03ff0000;
940*820c1a8dSHiroo HAYASHI bitset_word_t bits2 = 0x87fffffe;
941*820c1a8dSHiroo HAYASHI bitset_word_t bits3 = 0x07fffffe;
942*820c1a8dSHiroo HAYASHI if (BITSET_WORD_BITS == 64)
943*820c1a8dSHiroo HAYASHI {
944*820c1a8dSHiroo HAYASHI /* Pacify gcc -Woverflow on 32-bit platformns. */
945*820c1a8dSHiroo HAYASHI dfa->word_char[0] = bits1 << 31 << 1 | bits0;
946*820c1a8dSHiroo HAYASHI dfa->word_char[1] = bits3 << 31 << 1 | bits2;
947*820c1a8dSHiroo HAYASHI i = 2;
948*820c1a8dSHiroo HAYASHI }
949*820c1a8dSHiroo HAYASHI else if (BITSET_WORD_BITS == 32)
950*820c1a8dSHiroo HAYASHI {
951*820c1a8dSHiroo HAYASHI dfa->word_char[0] = bits0;
952*820c1a8dSHiroo HAYASHI dfa->word_char[1] = bits1;
953*820c1a8dSHiroo HAYASHI dfa->word_char[2] = bits2;
954*820c1a8dSHiroo HAYASHI dfa->word_char[3] = bits3;
955*820c1a8dSHiroo HAYASHI i = 4;
956*820c1a8dSHiroo HAYASHI }
957*820c1a8dSHiroo HAYASHI else
958*820c1a8dSHiroo HAYASHI goto general_case;
959*820c1a8dSHiroo HAYASHI ch = 128;
960*820c1a8dSHiroo HAYASHI
961*820c1a8dSHiroo HAYASHI if (__glibc_likely (dfa->is_utf8))
962*820c1a8dSHiroo HAYASHI {
963*820c1a8dSHiroo HAYASHI memset (&dfa->word_char[i], '\0', (SBC_MAX - ch) / 8);
964*820c1a8dSHiroo HAYASHI return;
965*820c1a8dSHiroo HAYASHI }
966*820c1a8dSHiroo HAYASHI }
967*820c1a8dSHiroo HAYASHI
968*820c1a8dSHiroo HAYASHI general_case:
969*820c1a8dSHiroo HAYASHI for (; i < BITSET_WORDS; ++i)
970*820c1a8dSHiroo HAYASHI for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)
971*820c1a8dSHiroo HAYASHI if (isalnum (ch) || ch == '_')
972*820c1a8dSHiroo HAYASHI dfa->word_char[i] |= (bitset_word_t) 1 << j;
973*820c1a8dSHiroo HAYASHI }
974*820c1a8dSHiroo HAYASHI
975*820c1a8dSHiroo HAYASHI /* Free the work area which are only used while compiling. */
976*820c1a8dSHiroo HAYASHI
977*820c1a8dSHiroo HAYASHI static void
free_workarea_compile(regex_t * preg)978*820c1a8dSHiroo HAYASHI free_workarea_compile (regex_t *preg)
979*820c1a8dSHiroo HAYASHI {
980*820c1a8dSHiroo HAYASHI re_dfa_t *dfa = preg->buffer;
981*820c1a8dSHiroo HAYASHI bin_tree_storage_t *storage, *next;
982*820c1a8dSHiroo HAYASHI for (storage = dfa->str_tree_storage; storage; storage = next)
983*820c1a8dSHiroo HAYASHI {
984*820c1a8dSHiroo HAYASHI next = storage->next;
985*820c1a8dSHiroo HAYASHI re_free (storage);
986*820c1a8dSHiroo HAYASHI }
987*820c1a8dSHiroo HAYASHI dfa->str_tree_storage = NULL;
988*820c1a8dSHiroo HAYASHI dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;
989*820c1a8dSHiroo HAYASHI dfa->str_tree = NULL;
990*820c1a8dSHiroo HAYASHI re_free (dfa->org_indices);
991*820c1a8dSHiroo HAYASHI dfa->org_indices = NULL;
992*820c1a8dSHiroo HAYASHI }
993*820c1a8dSHiroo HAYASHI
994*820c1a8dSHiroo HAYASHI /* Create initial states for all contexts. */
995*820c1a8dSHiroo HAYASHI
996*820c1a8dSHiroo HAYASHI static reg_errcode_t
create_initial_state(re_dfa_t * dfa)997*820c1a8dSHiroo HAYASHI create_initial_state (re_dfa_t *dfa)
998*820c1a8dSHiroo HAYASHI {
999*820c1a8dSHiroo HAYASHI Idx first, i;
1000*820c1a8dSHiroo HAYASHI reg_errcode_t err;
1001*820c1a8dSHiroo HAYASHI re_node_set init_nodes;
1002*820c1a8dSHiroo HAYASHI
1003*820c1a8dSHiroo HAYASHI /* Initial states have the epsilon closure of the node which is
1004*820c1a8dSHiroo HAYASHI the first node of the regular expression. */
1005*820c1a8dSHiroo HAYASHI first = dfa->str_tree->first->node_idx;
1006*820c1a8dSHiroo HAYASHI dfa->init_node = first;
1007*820c1a8dSHiroo HAYASHI err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first);
1008*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (err != REG_NOERROR))
1009*820c1a8dSHiroo HAYASHI return err;
1010*820c1a8dSHiroo HAYASHI
1011*820c1a8dSHiroo HAYASHI /* The back-references which are in initial states can epsilon transit,
1012*820c1a8dSHiroo HAYASHI since in this case all of the subexpressions can be null.
1013*820c1a8dSHiroo HAYASHI Then we add epsilon closures of the nodes which are the next nodes of
1014*820c1a8dSHiroo HAYASHI the back-references. */
1015*820c1a8dSHiroo HAYASHI if (dfa->nbackref > 0)
1016*820c1a8dSHiroo HAYASHI for (i = 0; i < init_nodes.nelem; ++i)
1017*820c1a8dSHiroo HAYASHI {
1018*820c1a8dSHiroo HAYASHI Idx node_idx = init_nodes.elems[i];
1019*820c1a8dSHiroo HAYASHI re_token_type_t type = dfa->nodes[node_idx].type;
1020*820c1a8dSHiroo HAYASHI
1021*820c1a8dSHiroo HAYASHI Idx clexp_idx;
1022*820c1a8dSHiroo HAYASHI if (type != OP_BACK_REF)
1023*820c1a8dSHiroo HAYASHI continue;
1024*820c1a8dSHiroo HAYASHI for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx)
1025*820c1a8dSHiroo HAYASHI {
1026*820c1a8dSHiroo HAYASHI re_token_t *clexp_node;
1027*820c1a8dSHiroo HAYASHI clexp_node = dfa->nodes + init_nodes.elems[clexp_idx];
1028*820c1a8dSHiroo HAYASHI if (clexp_node->type == OP_CLOSE_SUBEXP
1029*820c1a8dSHiroo HAYASHI && clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx)
1030*820c1a8dSHiroo HAYASHI break;
1031*820c1a8dSHiroo HAYASHI }
1032*820c1a8dSHiroo HAYASHI if (clexp_idx == init_nodes.nelem)
1033*820c1a8dSHiroo HAYASHI continue;
1034*820c1a8dSHiroo HAYASHI
1035*820c1a8dSHiroo HAYASHI if (type == OP_BACK_REF)
1036*820c1a8dSHiroo HAYASHI {
1037*820c1a8dSHiroo HAYASHI Idx dest_idx = dfa->edests[node_idx].elems[0];
1038*820c1a8dSHiroo HAYASHI if (!re_node_set_contains (&init_nodes, dest_idx))
1039*820c1a8dSHiroo HAYASHI {
1040*820c1a8dSHiroo HAYASHI reg_errcode_t merge_err
1041*820c1a8dSHiroo HAYASHI = re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx);
1042*820c1a8dSHiroo HAYASHI if (merge_err != REG_NOERROR)
1043*820c1a8dSHiroo HAYASHI return merge_err;
1044*820c1a8dSHiroo HAYASHI i = 0;
1045*820c1a8dSHiroo HAYASHI }
1046*820c1a8dSHiroo HAYASHI }
1047*820c1a8dSHiroo HAYASHI }
1048*820c1a8dSHiroo HAYASHI
1049*820c1a8dSHiroo HAYASHI /* It must be the first time to invoke acquire_state. */
1050*820c1a8dSHiroo HAYASHI dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0);
1051*820c1a8dSHiroo HAYASHI /* We don't check ERR here, since the initial state must not be NULL. */
1052*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (dfa->init_state == NULL))
1053*820c1a8dSHiroo HAYASHI return err;
1054*820c1a8dSHiroo HAYASHI if (dfa->init_state->has_constraint)
1055*820c1a8dSHiroo HAYASHI {
1056*820c1a8dSHiroo HAYASHI dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes,
1057*820c1a8dSHiroo HAYASHI CONTEXT_WORD);
1058*820c1a8dSHiroo HAYASHI dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes,
1059*820c1a8dSHiroo HAYASHI CONTEXT_NEWLINE);
1060*820c1a8dSHiroo HAYASHI dfa->init_state_begbuf = re_acquire_state_context (&err, dfa,
1061*820c1a8dSHiroo HAYASHI &init_nodes,
1062*820c1a8dSHiroo HAYASHI CONTEXT_NEWLINE
1063*820c1a8dSHiroo HAYASHI | CONTEXT_BEGBUF);
1064*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (dfa->init_state_word == NULL
1065*820c1a8dSHiroo HAYASHI || dfa->init_state_nl == NULL
1066*820c1a8dSHiroo HAYASHI || dfa->init_state_begbuf == NULL))
1067*820c1a8dSHiroo HAYASHI return err;
1068*820c1a8dSHiroo HAYASHI }
1069*820c1a8dSHiroo HAYASHI else
1070*820c1a8dSHiroo HAYASHI dfa->init_state_word = dfa->init_state_nl
1071*820c1a8dSHiroo HAYASHI = dfa->init_state_begbuf = dfa->init_state;
1072*820c1a8dSHiroo HAYASHI
1073*820c1a8dSHiroo HAYASHI re_node_set_free (&init_nodes);
1074*820c1a8dSHiroo HAYASHI return REG_NOERROR;
1075*820c1a8dSHiroo HAYASHI }
1076*820c1a8dSHiroo HAYASHI
1077*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
1078*820c1a8dSHiroo HAYASHI /* If it is possible to do searching in single byte encoding instead of UTF-8
1079*820c1a8dSHiroo HAYASHI to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change
1080*820c1a8dSHiroo HAYASHI DFA nodes where needed. */
1081*820c1a8dSHiroo HAYASHI
1082*820c1a8dSHiroo HAYASHI static void
optimize_utf8(re_dfa_t * dfa)1083*820c1a8dSHiroo HAYASHI optimize_utf8 (re_dfa_t *dfa)
1084*820c1a8dSHiroo HAYASHI {
1085*820c1a8dSHiroo HAYASHI Idx node;
1086*820c1a8dSHiroo HAYASHI int i;
1087*820c1a8dSHiroo HAYASHI bool mb_chars = false;
1088*820c1a8dSHiroo HAYASHI bool has_period = false;
1089*820c1a8dSHiroo HAYASHI
1090*820c1a8dSHiroo HAYASHI for (node = 0; node < dfa->nodes_len; ++node)
1091*820c1a8dSHiroo HAYASHI switch (dfa->nodes[node].type)
1092*820c1a8dSHiroo HAYASHI {
1093*820c1a8dSHiroo HAYASHI case CHARACTER:
1094*820c1a8dSHiroo HAYASHI if (dfa->nodes[node].opr.c >= ASCII_CHARS)
1095*820c1a8dSHiroo HAYASHI mb_chars = true;
1096*820c1a8dSHiroo HAYASHI break;
1097*820c1a8dSHiroo HAYASHI case ANCHOR:
1098*820c1a8dSHiroo HAYASHI switch (dfa->nodes[node].opr.ctx_type)
1099*820c1a8dSHiroo HAYASHI {
1100*820c1a8dSHiroo HAYASHI case LINE_FIRST:
1101*820c1a8dSHiroo HAYASHI case LINE_LAST:
1102*820c1a8dSHiroo HAYASHI case BUF_FIRST:
1103*820c1a8dSHiroo HAYASHI case BUF_LAST:
1104*820c1a8dSHiroo HAYASHI break;
1105*820c1a8dSHiroo HAYASHI default:
1106*820c1a8dSHiroo HAYASHI /* Word anchors etc. cannot be handled. It's okay to test
1107*820c1a8dSHiroo HAYASHI opr.ctx_type since constraints (for all DFA nodes) are
1108*820c1a8dSHiroo HAYASHI created by ORing one or more opr.ctx_type values. */
1109*820c1a8dSHiroo HAYASHI return;
1110*820c1a8dSHiroo HAYASHI }
1111*820c1a8dSHiroo HAYASHI break;
1112*820c1a8dSHiroo HAYASHI case OP_PERIOD:
1113*820c1a8dSHiroo HAYASHI has_period = true;
1114*820c1a8dSHiroo HAYASHI break;
1115*820c1a8dSHiroo HAYASHI case OP_BACK_REF:
1116*820c1a8dSHiroo HAYASHI case OP_ALT:
1117*820c1a8dSHiroo HAYASHI case END_OF_RE:
1118*820c1a8dSHiroo HAYASHI case OP_DUP_ASTERISK:
1119*820c1a8dSHiroo HAYASHI case OP_OPEN_SUBEXP:
1120*820c1a8dSHiroo HAYASHI case OP_CLOSE_SUBEXP:
1121*820c1a8dSHiroo HAYASHI break;
1122*820c1a8dSHiroo HAYASHI case COMPLEX_BRACKET:
1123*820c1a8dSHiroo HAYASHI return;
1124*820c1a8dSHiroo HAYASHI case SIMPLE_BRACKET:
1125*820c1a8dSHiroo HAYASHI /* Just double check. */
1126*820c1a8dSHiroo HAYASHI {
1127*820c1a8dSHiroo HAYASHI int rshift = (ASCII_CHARS % BITSET_WORD_BITS == 0
1128*820c1a8dSHiroo HAYASHI ? 0
1129*820c1a8dSHiroo HAYASHI : BITSET_WORD_BITS - ASCII_CHARS % BITSET_WORD_BITS);
1130*820c1a8dSHiroo HAYASHI for (i = ASCII_CHARS / BITSET_WORD_BITS; i < BITSET_WORDS; ++i)
1131*820c1a8dSHiroo HAYASHI {
1132*820c1a8dSHiroo HAYASHI if (dfa->nodes[node].opr.sbcset[i] >> rshift != 0)
1133*820c1a8dSHiroo HAYASHI return;
1134*820c1a8dSHiroo HAYASHI rshift = 0;
1135*820c1a8dSHiroo HAYASHI }
1136*820c1a8dSHiroo HAYASHI }
1137*820c1a8dSHiroo HAYASHI break;
1138*820c1a8dSHiroo HAYASHI default:
1139*820c1a8dSHiroo HAYASHI abort ();
1140*820c1a8dSHiroo HAYASHI }
1141*820c1a8dSHiroo HAYASHI
1142*820c1a8dSHiroo HAYASHI if (mb_chars || has_period)
1143*820c1a8dSHiroo HAYASHI for (node = 0; node < dfa->nodes_len; ++node)
1144*820c1a8dSHiroo HAYASHI {
1145*820c1a8dSHiroo HAYASHI if (dfa->nodes[node].type == CHARACTER
1146*820c1a8dSHiroo HAYASHI && dfa->nodes[node].opr.c >= ASCII_CHARS)
1147*820c1a8dSHiroo HAYASHI dfa->nodes[node].mb_partial = 0;
1148*820c1a8dSHiroo HAYASHI else if (dfa->nodes[node].type == OP_PERIOD)
1149*820c1a8dSHiroo HAYASHI dfa->nodes[node].type = OP_UTF8_PERIOD;
1150*820c1a8dSHiroo HAYASHI }
1151*820c1a8dSHiroo HAYASHI
1152*820c1a8dSHiroo HAYASHI /* The search can be in single byte locale. */
1153*820c1a8dSHiroo HAYASHI dfa->mb_cur_max = 1;
1154*820c1a8dSHiroo HAYASHI dfa->is_utf8 = 0;
1155*820c1a8dSHiroo HAYASHI dfa->has_mb_node = dfa->nbackref > 0 || has_period;
1156*820c1a8dSHiroo HAYASHI }
1157*820c1a8dSHiroo HAYASHI #endif
1158*820c1a8dSHiroo HAYASHI
1159*820c1a8dSHiroo HAYASHI /* Analyze the structure tree, and calculate "first", "next", "edest",
1160*820c1a8dSHiroo HAYASHI "eclosure", and "inveclosure". */
1161*820c1a8dSHiroo HAYASHI
1162*820c1a8dSHiroo HAYASHI static reg_errcode_t
analyze(regex_t * preg)1163*820c1a8dSHiroo HAYASHI analyze (regex_t *preg)
1164*820c1a8dSHiroo HAYASHI {
1165*820c1a8dSHiroo HAYASHI re_dfa_t *dfa = preg->buffer;
1166*820c1a8dSHiroo HAYASHI reg_errcode_t ret;
1167*820c1a8dSHiroo HAYASHI
1168*820c1a8dSHiroo HAYASHI /* Allocate arrays. */
1169*820c1a8dSHiroo HAYASHI dfa->nexts = re_malloc (Idx, dfa->nodes_alloc);
1170*820c1a8dSHiroo HAYASHI dfa->org_indices = re_malloc (Idx, dfa->nodes_alloc);
1171*820c1a8dSHiroo HAYASHI dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc);
1172*820c1a8dSHiroo HAYASHI dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc);
1173*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (dfa->nexts == NULL || dfa->org_indices == NULL
1174*820c1a8dSHiroo HAYASHI || dfa->edests == NULL || dfa->eclosures == NULL))
1175*820c1a8dSHiroo HAYASHI return REG_ESPACE;
1176*820c1a8dSHiroo HAYASHI
1177*820c1a8dSHiroo HAYASHI dfa->subexp_map = re_malloc (Idx, preg->re_nsub);
1178*820c1a8dSHiroo HAYASHI if (dfa->subexp_map != NULL)
1179*820c1a8dSHiroo HAYASHI {
1180*820c1a8dSHiroo HAYASHI Idx i;
1181*820c1a8dSHiroo HAYASHI for (i = 0; i < preg->re_nsub; i++)
1182*820c1a8dSHiroo HAYASHI dfa->subexp_map[i] = i;
1183*820c1a8dSHiroo HAYASHI preorder (dfa->str_tree, optimize_subexps, dfa);
1184*820c1a8dSHiroo HAYASHI for (i = 0; i < preg->re_nsub; i++)
1185*820c1a8dSHiroo HAYASHI if (dfa->subexp_map[i] != i)
1186*820c1a8dSHiroo HAYASHI break;
1187*820c1a8dSHiroo HAYASHI if (i == preg->re_nsub)
1188*820c1a8dSHiroo HAYASHI {
1189*820c1a8dSHiroo HAYASHI re_free (dfa->subexp_map);
1190*820c1a8dSHiroo HAYASHI dfa->subexp_map = NULL;
1191*820c1a8dSHiroo HAYASHI }
1192*820c1a8dSHiroo HAYASHI }
1193*820c1a8dSHiroo HAYASHI
1194*820c1a8dSHiroo HAYASHI ret = postorder (dfa->str_tree, lower_subexps, preg);
1195*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (ret != REG_NOERROR))
1196*820c1a8dSHiroo HAYASHI return ret;
1197*820c1a8dSHiroo HAYASHI ret = postorder (dfa->str_tree, calc_first, dfa);
1198*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (ret != REG_NOERROR))
1199*820c1a8dSHiroo HAYASHI return ret;
1200*820c1a8dSHiroo HAYASHI preorder (dfa->str_tree, calc_next, dfa);
1201*820c1a8dSHiroo HAYASHI ret = preorder (dfa->str_tree, link_nfa_nodes, dfa);
1202*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (ret != REG_NOERROR))
1203*820c1a8dSHiroo HAYASHI return ret;
1204*820c1a8dSHiroo HAYASHI ret = calc_eclosure (dfa);
1205*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (ret != REG_NOERROR))
1206*820c1a8dSHiroo HAYASHI return ret;
1207*820c1a8dSHiroo HAYASHI
1208*820c1a8dSHiroo HAYASHI /* We only need this during the prune_impossible_nodes pass in regexec.c;
1209*820c1a8dSHiroo HAYASHI skip it if p_i_n will not run, as calc_inveclosure can be quadratic. */
1210*820c1a8dSHiroo HAYASHI if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match)
1211*820c1a8dSHiroo HAYASHI || dfa->nbackref)
1212*820c1a8dSHiroo HAYASHI {
1213*820c1a8dSHiroo HAYASHI dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len);
1214*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (dfa->inveclosures == NULL))
1215*820c1a8dSHiroo HAYASHI return REG_ESPACE;
1216*820c1a8dSHiroo HAYASHI ret = calc_inveclosure (dfa);
1217*820c1a8dSHiroo HAYASHI }
1218*820c1a8dSHiroo HAYASHI
1219*820c1a8dSHiroo HAYASHI return ret;
1220*820c1a8dSHiroo HAYASHI }
1221*820c1a8dSHiroo HAYASHI
1222*820c1a8dSHiroo HAYASHI /* Our parse trees are very unbalanced, so we cannot use a stack to
1223*820c1a8dSHiroo HAYASHI implement parse tree visits. Instead, we use parent pointers and
1224*820c1a8dSHiroo HAYASHI some hairy code in these two functions. */
1225*820c1a8dSHiroo HAYASHI static reg_errcode_t
postorder(bin_tree_t * root,reg_errcode_t (fn (void *,bin_tree_t *)),void * extra)1226*820c1a8dSHiroo HAYASHI postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)),
1227*820c1a8dSHiroo HAYASHI void *extra)
1228*820c1a8dSHiroo HAYASHI {
1229*820c1a8dSHiroo HAYASHI bin_tree_t *node, *prev;
1230*820c1a8dSHiroo HAYASHI
1231*820c1a8dSHiroo HAYASHI for (node = root; ; )
1232*820c1a8dSHiroo HAYASHI {
1233*820c1a8dSHiroo HAYASHI /* Descend down the tree, preferably to the left (or to the right
1234*820c1a8dSHiroo HAYASHI if that's the only child). */
1235*820c1a8dSHiroo HAYASHI while (node->left || node->right)
1236*820c1a8dSHiroo HAYASHI if (node->left)
1237*820c1a8dSHiroo HAYASHI node = node->left;
1238*820c1a8dSHiroo HAYASHI else
1239*820c1a8dSHiroo HAYASHI node = node->right;
1240*820c1a8dSHiroo HAYASHI
1241*820c1a8dSHiroo HAYASHI do
1242*820c1a8dSHiroo HAYASHI {
1243*820c1a8dSHiroo HAYASHI reg_errcode_t err = fn (extra, node);
1244*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (err != REG_NOERROR))
1245*820c1a8dSHiroo HAYASHI return err;
1246*820c1a8dSHiroo HAYASHI if (node->parent == NULL)
1247*820c1a8dSHiroo HAYASHI return REG_NOERROR;
1248*820c1a8dSHiroo HAYASHI prev = node;
1249*820c1a8dSHiroo HAYASHI node = node->parent;
1250*820c1a8dSHiroo HAYASHI }
1251*820c1a8dSHiroo HAYASHI /* Go up while we have a node that is reached from the right. */
1252*820c1a8dSHiroo HAYASHI while (node->right == prev || node->right == NULL);
1253*820c1a8dSHiroo HAYASHI node = node->right;
1254*820c1a8dSHiroo HAYASHI }
1255*820c1a8dSHiroo HAYASHI }
1256*820c1a8dSHiroo HAYASHI
1257*820c1a8dSHiroo HAYASHI static reg_errcode_t
preorder(bin_tree_t * root,reg_errcode_t (fn (void *,bin_tree_t *)),void * extra)1258*820c1a8dSHiroo HAYASHI preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)),
1259*820c1a8dSHiroo HAYASHI void *extra)
1260*820c1a8dSHiroo HAYASHI {
1261*820c1a8dSHiroo HAYASHI bin_tree_t *node;
1262*820c1a8dSHiroo HAYASHI
1263*820c1a8dSHiroo HAYASHI for (node = root; ; )
1264*820c1a8dSHiroo HAYASHI {
1265*820c1a8dSHiroo HAYASHI reg_errcode_t err = fn (extra, node);
1266*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (err != REG_NOERROR))
1267*820c1a8dSHiroo HAYASHI return err;
1268*820c1a8dSHiroo HAYASHI
1269*820c1a8dSHiroo HAYASHI /* Go to the left node, or up and to the right. */
1270*820c1a8dSHiroo HAYASHI if (node->left)
1271*820c1a8dSHiroo HAYASHI node = node->left;
1272*820c1a8dSHiroo HAYASHI else
1273*820c1a8dSHiroo HAYASHI {
1274*820c1a8dSHiroo HAYASHI bin_tree_t *prev = NULL;
1275*820c1a8dSHiroo HAYASHI while (node->right == prev || node->right == NULL)
1276*820c1a8dSHiroo HAYASHI {
1277*820c1a8dSHiroo HAYASHI prev = node;
1278*820c1a8dSHiroo HAYASHI node = node->parent;
1279*820c1a8dSHiroo HAYASHI if (!node)
1280*820c1a8dSHiroo HAYASHI return REG_NOERROR;
1281*820c1a8dSHiroo HAYASHI }
1282*820c1a8dSHiroo HAYASHI node = node->right;
1283*820c1a8dSHiroo HAYASHI }
1284*820c1a8dSHiroo HAYASHI }
1285*820c1a8dSHiroo HAYASHI }
1286*820c1a8dSHiroo HAYASHI
1287*820c1a8dSHiroo HAYASHI /* Optimization pass: if a SUBEXP is entirely contained, strip it and tell
1288*820c1a8dSHiroo HAYASHI re_search_internal to map the inner one's opr.idx to this one's. Adjust
1289*820c1a8dSHiroo HAYASHI backreferences as well. Requires a preorder visit. */
1290*820c1a8dSHiroo HAYASHI static reg_errcode_t
optimize_subexps(void * extra,bin_tree_t * node)1291*820c1a8dSHiroo HAYASHI optimize_subexps (void *extra, bin_tree_t *node)
1292*820c1a8dSHiroo HAYASHI {
1293*820c1a8dSHiroo HAYASHI re_dfa_t *dfa = (re_dfa_t *) extra;
1294*820c1a8dSHiroo HAYASHI
1295*820c1a8dSHiroo HAYASHI if (node->token.type == OP_BACK_REF && dfa->subexp_map)
1296*820c1a8dSHiroo HAYASHI {
1297*820c1a8dSHiroo HAYASHI int idx = node->token.opr.idx;
1298*820c1a8dSHiroo HAYASHI node->token.opr.idx = dfa->subexp_map[idx];
1299*820c1a8dSHiroo HAYASHI dfa->used_bkref_map |= 1 << node->token.opr.idx;
1300*820c1a8dSHiroo HAYASHI }
1301*820c1a8dSHiroo HAYASHI
1302*820c1a8dSHiroo HAYASHI else if (node->token.type == SUBEXP
1303*820c1a8dSHiroo HAYASHI && node->left && node->left->token.type == SUBEXP)
1304*820c1a8dSHiroo HAYASHI {
1305*820c1a8dSHiroo HAYASHI Idx other_idx = node->left->token.opr.idx;
1306*820c1a8dSHiroo HAYASHI
1307*820c1a8dSHiroo HAYASHI node->left = node->left->left;
1308*820c1a8dSHiroo HAYASHI if (node->left)
1309*820c1a8dSHiroo HAYASHI node->left->parent = node;
1310*820c1a8dSHiroo HAYASHI
1311*820c1a8dSHiroo HAYASHI dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx];
1312*820c1a8dSHiroo HAYASHI if (other_idx < BITSET_WORD_BITS)
1313*820c1a8dSHiroo HAYASHI dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx);
1314*820c1a8dSHiroo HAYASHI }
1315*820c1a8dSHiroo HAYASHI
1316*820c1a8dSHiroo HAYASHI return REG_NOERROR;
1317*820c1a8dSHiroo HAYASHI }
1318*820c1a8dSHiroo HAYASHI
1319*820c1a8dSHiroo HAYASHI /* Lowering pass: Turn each SUBEXP node into the appropriate concatenation
1320*820c1a8dSHiroo HAYASHI of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP. */
1321*820c1a8dSHiroo HAYASHI static reg_errcode_t
lower_subexps(void * extra,bin_tree_t * node)1322*820c1a8dSHiroo HAYASHI lower_subexps (void *extra, bin_tree_t *node)
1323*820c1a8dSHiroo HAYASHI {
1324*820c1a8dSHiroo HAYASHI regex_t *preg = (regex_t *) extra;
1325*820c1a8dSHiroo HAYASHI reg_errcode_t err = REG_NOERROR;
1326*820c1a8dSHiroo HAYASHI
1327*820c1a8dSHiroo HAYASHI if (node->left && node->left->token.type == SUBEXP)
1328*820c1a8dSHiroo HAYASHI {
1329*820c1a8dSHiroo HAYASHI node->left = lower_subexp (&err, preg, node->left);
1330*820c1a8dSHiroo HAYASHI if (node->left)
1331*820c1a8dSHiroo HAYASHI node->left->parent = node;
1332*820c1a8dSHiroo HAYASHI }
1333*820c1a8dSHiroo HAYASHI if (node->right && node->right->token.type == SUBEXP)
1334*820c1a8dSHiroo HAYASHI {
1335*820c1a8dSHiroo HAYASHI node->right = lower_subexp (&err, preg, node->right);
1336*820c1a8dSHiroo HAYASHI if (node->right)
1337*820c1a8dSHiroo HAYASHI node->right->parent = node;
1338*820c1a8dSHiroo HAYASHI }
1339*820c1a8dSHiroo HAYASHI
1340*820c1a8dSHiroo HAYASHI return err;
1341*820c1a8dSHiroo HAYASHI }
1342*820c1a8dSHiroo HAYASHI
1343*820c1a8dSHiroo HAYASHI static bin_tree_t *
lower_subexp(reg_errcode_t * err,regex_t * preg,bin_tree_t * node)1344*820c1a8dSHiroo HAYASHI lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node)
1345*820c1a8dSHiroo HAYASHI {
1346*820c1a8dSHiroo HAYASHI re_dfa_t *dfa = preg->buffer;
1347*820c1a8dSHiroo HAYASHI bin_tree_t *body = node->left;
1348*820c1a8dSHiroo HAYASHI bin_tree_t *op, *cls, *tree1, *tree;
1349*820c1a8dSHiroo HAYASHI
1350*820c1a8dSHiroo HAYASHI if (preg->no_sub
1351*820c1a8dSHiroo HAYASHI /* We do not optimize empty subexpressions, because otherwise we may
1352*820c1a8dSHiroo HAYASHI have bad CONCAT nodes with NULL children. This is obviously not
1353*820c1a8dSHiroo HAYASHI very common, so we do not lose much. An example that triggers
1354*820c1a8dSHiroo HAYASHI this case is the sed "script" /\(\)/x. */
1355*820c1a8dSHiroo HAYASHI && node->left != NULL
1356*820c1a8dSHiroo HAYASHI && (node->token.opr.idx >= BITSET_WORD_BITS
1357*820c1a8dSHiroo HAYASHI || !(dfa->used_bkref_map
1358*820c1a8dSHiroo HAYASHI & ((bitset_word_t) 1 << node->token.opr.idx))))
1359*820c1a8dSHiroo HAYASHI return node->left;
1360*820c1a8dSHiroo HAYASHI
1361*820c1a8dSHiroo HAYASHI /* Convert the SUBEXP node to the concatenation of an
1362*820c1a8dSHiroo HAYASHI OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP. */
1363*820c1a8dSHiroo HAYASHI op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP);
1364*820c1a8dSHiroo HAYASHI cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP);
1365*820c1a8dSHiroo HAYASHI tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls;
1366*820c1a8dSHiroo HAYASHI tree = create_tree (dfa, op, tree1, CONCAT);
1367*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (tree == NULL || tree1 == NULL
1368*820c1a8dSHiroo HAYASHI || op == NULL || cls == NULL))
1369*820c1a8dSHiroo HAYASHI {
1370*820c1a8dSHiroo HAYASHI *err = REG_ESPACE;
1371*820c1a8dSHiroo HAYASHI return NULL;
1372*820c1a8dSHiroo HAYASHI }
1373*820c1a8dSHiroo HAYASHI
1374*820c1a8dSHiroo HAYASHI op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx;
1375*820c1a8dSHiroo HAYASHI op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp;
1376*820c1a8dSHiroo HAYASHI return tree;
1377*820c1a8dSHiroo HAYASHI }
1378*820c1a8dSHiroo HAYASHI
1379*820c1a8dSHiroo HAYASHI /* Pass 1 in building the NFA: compute FIRST and create unlinked automaton
1380*820c1a8dSHiroo HAYASHI nodes. Requires a postorder visit. */
1381*820c1a8dSHiroo HAYASHI static reg_errcode_t
calc_first(void * extra,bin_tree_t * node)1382*820c1a8dSHiroo HAYASHI calc_first (void *extra, bin_tree_t *node)
1383*820c1a8dSHiroo HAYASHI {
1384*820c1a8dSHiroo HAYASHI re_dfa_t *dfa = (re_dfa_t *) extra;
1385*820c1a8dSHiroo HAYASHI if (node->token.type == CONCAT)
1386*820c1a8dSHiroo HAYASHI {
1387*820c1a8dSHiroo HAYASHI node->first = node->left->first;
1388*820c1a8dSHiroo HAYASHI node->node_idx = node->left->node_idx;
1389*820c1a8dSHiroo HAYASHI }
1390*820c1a8dSHiroo HAYASHI else
1391*820c1a8dSHiroo HAYASHI {
1392*820c1a8dSHiroo HAYASHI node->first = node;
1393*820c1a8dSHiroo HAYASHI node->node_idx = re_dfa_add_node (dfa, node->token);
1394*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (node->node_idx == -1))
1395*820c1a8dSHiroo HAYASHI return REG_ESPACE;
1396*820c1a8dSHiroo HAYASHI if (node->token.type == ANCHOR)
1397*820c1a8dSHiroo HAYASHI dfa->nodes[node->node_idx].constraint = node->token.opr.ctx_type;
1398*820c1a8dSHiroo HAYASHI }
1399*820c1a8dSHiroo HAYASHI return REG_NOERROR;
1400*820c1a8dSHiroo HAYASHI }
1401*820c1a8dSHiroo HAYASHI
1402*820c1a8dSHiroo HAYASHI /* Pass 2: compute NEXT on the tree. Preorder visit. */
1403*820c1a8dSHiroo HAYASHI static reg_errcode_t
calc_next(void * extra,bin_tree_t * node)1404*820c1a8dSHiroo HAYASHI calc_next (void *extra, bin_tree_t *node)
1405*820c1a8dSHiroo HAYASHI {
1406*820c1a8dSHiroo HAYASHI switch (node->token.type)
1407*820c1a8dSHiroo HAYASHI {
1408*820c1a8dSHiroo HAYASHI case OP_DUP_ASTERISK:
1409*820c1a8dSHiroo HAYASHI node->left->next = node;
1410*820c1a8dSHiroo HAYASHI break;
1411*820c1a8dSHiroo HAYASHI case CONCAT:
1412*820c1a8dSHiroo HAYASHI node->left->next = node->right->first;
1413*820c1a8dSHiroo HAYASHI node->right->next = node->next;
1414*820c1a8dSHiroo HAYASHI break;
1415*820c1a8dSHiroo HAYASHI default:
1416*820c1a8dSHiroo HAYASHI if (node->left)
1417*820c1a8dSHiroo HAYASHI node->left->next = node->next;
1418*820c1a8dSHiroo HAYASHI if (node->right)
1419*820c1a8dSHiroo HAYASHI node->right->next = node->next;
1420*820c1a8dSHiroo HAYASHI break;
1421*820c1a8dSHiroo HAYASHI }
1422*820c1a8dSHiroo HAYASHI return REG_NOERROR;
1423*820c1a8dSHiroo HAYASHI }
1424*820c1a8dSHiroo HAYASHI
1425*820c1a8dSHiroo HAYASHI /* Pass 3: link all DFA nodes to their NEXT node (any order will do). */
1426*820c1a8dSHiroo HAYASHI static reg_errcode_t
link_nfa_nodes(void * extra,bin_tree_t * node)1427*820c1a8dSHiroo HAYASHI link_nfa_nodes (void *extra, bin_tree_t *node)
1428*820c1a8dSHiroo HAYASHI {
1429*820c1a8dSHiroo HAYASHI re_dfa_t *dfa = (re_dfa_t *) extra;
1430*820c1a8dSHiroo HAYASHI Idx idx = node->node_idx;
1431*820c1a8dSHiroo HAYASHI reg_errcode_t err = REG_NOERROR;
1432*820c1a8dSHiroo HAYASHI
1433*820c1a8dSHiroo HAYASHI switch (node->token.type)
1434*820c1a8dSHiroo HAYASHI {
1435*820c1a8dSHiroo HAYASHI case CONCAT:
1436*820c1a8dSHiroo HAYASHI break;
1437*820c1a8dSHiroo HAYASHI
1438*820c1a8dSHiroo HAYASHI case END_OF_RE:
1439*820c1a8dSHiroo HAYASHI DEBUG_ASSERT (node->next == NULL);
1440*820c1a8dSHiroo HAYASHI break;
1441*820c1a8dSHiroo HAYASHI
1442*820c1a8dSHiroo HAYASHI case OP_DUP_ASTERISK:
1443*820c1a8dSHiroo HAYASHI case OP_ALT:
1444*820c1a8dSHiroo HAYASHI {
1445*820c1a8dSHiroo HAYASHI Idx left, right;
1446*820c1a8dSHiroo HAYASHI dfa->has_plural_match = 1;
1447*820c1a8dSHiroo HAYASHI if (node->left != NULL)
1448*820c1a8dSHiroo HAYASHI left = node->left->first->node_idx;
1449*820c1a8dSHiroo HAYASHI else
1450*820c1a8dSHiroo HAYASHI left = node->next->node_idx;
1451*820c1a8dSHiroo HAYASHI if (node->right != NULL)
1452*820c1a8dSHiroo HAYASHI right = node->right->first->node_idx;
1453*820c1a8dSHiroo HAYASHI else
1454*820c1a8dSHiroo HAYASHI right = node->next->node_idx;
1455*820c1a8dSHiroo HAYASHI DEBUG_ASSERT (left > -1);
1456*820c1a8dSHiroo HAYASHI DEBUG_ASSERT (right > -1);
1457*820c1a8dSHiroo HAYASHI err = re_node_set_init_2 (dfa->edests + idx, left, right);
1458*820c1a8dSHiroo HAYASHI }
1459*820c1a8dSHiroo HAYASHI break;
1460*820c1a8dSHiroo HAYASHI
1461*820c1a8dSHiroo HAYASHI case ANCHOR:
1462*820c1a8dSHiroo HAYASHI case OP_OPEN_SUBEXP:
1463*820c1a8dSHiroo HAYASHI case OP_CLOSE_SUBEXP:
1464*820c1a8dSHiroo HAYASHI err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx);
1465*820c1a8dSHiroo HAYASHI break;
1466*820c1a8dSHiroo HAYASHI
1467*820c1a8dSHiroo HAYASHI case OP_BACK_REF:
1468*820c1a8dSHiroo HAYASHI dfa->nexts[idx] = node->next->node_idx;
1469*820c1a8dSHiroo HAYASHI if (node->token.type == OP_BACK_REF)
1470*820c1a8dSHiroo HAYASHI err = re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]);
1471*820c1a8dSHiroo HAYASHI break;
1472*820c1a8dSHiroo HAYASHI
1473*820c1a8dSHiroo HAYASHI default:
1474*820c1a8dSHiroo HAYASHI DEBUG_ASSERT (!IS_EPSILON_NODE (node->token.type));
1475*820c1a8dSHiroo HAYASHI dfa->nexts[idx] = node->next->node_idx;
1476*820c1a8dSHiroo HAYASHI break;
1477*820c1a8dSHiroo HAYASHI }
1478*820c1a8dSHiroo HAYASHI
1479*820c1a8dSHiroo HAYASHI return err;
1480*820c1a8dSHiroo HAYASHI }
1481*820c1a8dSHiroo HAYASHI
1482*820c1a8dSHiroo HAYASHI /* Duplicate the epsilon closure of the node ROOT_NODE.
1483*820c1a8dSHiroo HAYASHI Note that duplicated nodes have constraint INIT_CONSTRAINT in addition
1484*820c1a8dSHiroo HAYASHI to their own constraint. */
1485*820c1a8dSHiroo HAYASHI
1486*820c1a8dSHiroo HAYASHI static reg_errcode_t
duplicate_node_closure(re_dfa_t * dfa,Idx top_org_node,Idx top_clone_node,Idx root_node,unsigned int init_constraint)1487*820c1a8dSHiroo HAYASHI duplicate_node_closure (re_dfa_t *dfa, Idx top_org_node, Idx top_clone_node,
1488*820c1a8dSHiroo HAYASHI Idx root_node, unsigned int init_constraint)
1489*820c1a8dSHiroo HAYASHI {
1490*820c1a8dSHiroo HAYASHI Idx org_node, clone_node;
1491*820c1a8dSHiroo HAYASHI bool ok;
1492*820c1a8dSHiroo HAYASHI unsigned int constraint = init_constraint;
1493*820c1a8dSHiroo HAYASHI for (org_node = top_org_node, clone_node = top_clone_node;;)
1494*820c1a8dSHiroo HAYASHI {
1495*820c1a8dSHiroo HAYASHI Idx org_dest, clone_dest;
1496*820c1a8dSHiroo HAYASHI if (dfa->nodes[org_node].type == OP_BACK_REF)
1497*820c1a8dSHiroo HAYASHI {
1498*820c1a8dSHiroo HAYASHI /* If the back reference epsilon-transit, its destination must
1499*820c1a8dSHiroo HAYASHI also have the constraint. Then duplicate the epsilon closure
1500*820c1a8dSHiroo HAYASHI of the destination of the back reference, and store it in
1501*820c1a8dSHiroo HAYASHI edests of the back reference. */
1502*820c1a8dSHiroo HAYASHI org_dest = dfa->nexts[org_node];
1503*820c1a8dSHiroo HAYASHI re_node_set_empty (dfa->edests + clone_node);
1504*820c1a8dSHiroo HAYASHI clone_dest = duplicate_node (dfa, org_dest, constraint);
1505*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (clone_dest == -1))
1506*820c1a8dSHiroo HAYASHI return REG_ESPACE;
1507*820c1a8dSHiroo HAYASHI dfa->nexts[clone_node] = dfa->nexts[org_node];
1508*820c1a8dSHiroo HAYASHI ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
1509*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (! ok))
1510*820c1a8dSHiroo HAYASHI return REG_ESPACE;
1511*820c1a8dSHiroo HAYASHI }
1512*820c1a8dSHiroo HAYASHI else if (dfa->edests[org_node].nelem == 0)
1513*820c1a8dSHiroo HAYASHI {
1514*820c1a8dSHiroo HAYASHI /* In case of the node can't epsilon-transit, don't duplicate the
1515*820c1a8dSHiroo HAYASHI destination and store the original destination as the
1516*820c1a8dSHiroo HAYASHI destination of the node. */
1517*820c1a8dSHiroo HAYASHI dfa->nexts[clone_node] = dfa->nexts[org_node];
1518*820c1a8dSHiroo HAYASHI break;
1519*820c1a8dSHiroo HAYASHI }
1520*820c1a8dSHiroo HAYASHI else if (dfa->edests[org_node].nelem == 1)
1521*820c1a8dSHiroo HAYASHI {
1522*820c1a8dSHiroo HAYASHI /* In case of the node can epsilon-transit, and it has only one
1523*820c1a8dSHiroo HAYASHI destination. */
1524*820c1a8dSHiroo HAYASHI org_dest = dfa->edests[org_node].elems[0];
1525*820c1a8dSHiroo HAYASHI re_node_set_empty (dfa->edests + clone_node);
1526*820c1a8dSHiroo HAYASHI /* If the node is root_node itself, it means the epsilon closure
1527*820c1a8dSHiroo HAYASHI has a loop. Then tie it to the destination of the root_node. */
1528*820c1a8dSHiroo HAYASHI if (org_node == root_node && clone_node != org_node)
1529*820c1a8dSHiroo HAYASHI {
1530*820c1a8dSHiroo HAYASHI ok = re_node_set_insert (dfa->edests + clone_node, org_dest);
1531*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (! ok))
1532*820c1a8dSHiroo HAYASHI return REG_ESPACE;
1533*820c1a8dSHiroo HAYASHI break;
1534*820c1a8dSHiroo HAYASHI }
1535*820c1a8dSHiroo HAYASHI /* In case the node has another constraint, append it. */
1536*820c1a8dSHiroo HAYASHI constraint |= dfa->nodes[org_node].constraint;
1537*820c1a8dSHiroo HAYASHI clone_dest = duplicate_node (dfa, org_dest, constraint);
1538*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (clone_dest == -1))
1539*820c1a8dSHiroo HAYASHI return REG_ESPACE;
1540*820c1a8dSHiroo HAYASHI ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
1541*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (! ok))
1542*820c1a8dSHiroo HAYASHI return REG_ESPACE;
1543*820c1a8dSHiroo HAYASHI }
1544*820c1a8dSHiroo HAYASHI else /* dfa->edests[org_node].nelem == 2 */
1545*820c1a8dSHiroo HAYASHI {
1546*820c1a8dSHiroo HAYASHI /* In case of the node can epsilon-transit, and it has two
1547*820c1a8dSHiroo HAYASHI destinations. In the bin_tree_t and DFA, that's '|' and '*'. */
1548*820c1a8dSHiroo HAYASHI org_dest = dfa->edests[org_node].elems[0];
1549*820c1a8dSHiroo HAYASHI re_node_set_empty (dfa->edests + clone_node);
1550*820c1a8dSHiroo HAYASHI /* Search for a duplicated node which satisfies the constraint. */
1551*820c1a8dSHiroo HAYASHI clone_dest = search_duplicated_node (dfa, org_dest, constraint);
1552*820c1a8dSHiroo HAYASHI if (clone_dest == -1)
1553*820c1a8dSHiroo HAYASHI {
1554*820c1a8dSHiroo HAYASHI /* There is no such duplicated node, create a new one. */
1555*820c1a8dSHiroo HAYASHI reg_errcode_t err;
1556*820c1a8dSHiroo HAYASHI clone_dest = duplicate_node (dfa, org_dest, constraint);
1557*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (clone_dest == -1))
1558*820c1a8dSHiroo HAYASHI return REG_ESPACE;
1559*820c1a8dSHiroo HAYASHI ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
1560*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (! ok))
1561*820c1a8dSHiroo HAYASHI return REG_ESPACE;
1562*820c1a8dSHiroo HAYASHI err = duplicate_node_closure (dfa, org_dest, clone_dest,
1563*820c1a8dSHiroo HAYASHI root_node, constraint);
1564*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (err != REG_NOERROR))
1565*820c1a8dSHiroo HAYASHI return err;
1566*820c1a8dSHiroo HAYASHI }
1567*820c1a8dSHiroo HAYASHI else
1568*820c1a8dSHiroo HAYASHI {
1569*820c1a8dSHiroo HAYASHI /* There is a duplicated node which satisfies the constraint,
1570*820c1a8dSHiroo HAYASHI use it to avoid infinite loop. */
1571*820c1a8dSHiroo HAYASHI ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
1572*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (! ok))
1573*820c1a8dSHiroo HAYASHI return REG_ESPACE;
1574*820c1a8dSHiroo HAYASHI }
1575*820c1a8dSHiroo HAYASHI
1576*820c1a8dSHiroo HAYASHI org_dest = dfa->edests[org_node].elems[1];
1577*820c1a8dSHiroo HAYASHI clone_dest = duplicate_node (dfa, org_dest, constraint);
1578*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (clone_dest == -1))
1579*820c1a8dSHiroo HAYASHI return REG_ESPACE;
1580*820c1a8dSHiroo HAYASHI ok = re_node_set_insert (dfa->edests + clone_node, clone_dest);
1581*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (! ok))
1582*820c1a8dSHiroo HAYASHI return REG_ESPACE;
1583*820c1a8dSHiroo HAYASHI }
1584*820c1a8dSHiroo HAYASHI org_node = org_dest;
1585*820c1a8dSHiroo HAYASHI clone_node = clone_dest;
1586*820c1a8dSHiroo HAYASHI }
1587*820c1a8dSHiroo HAYASHI return REG_NOERROR;
1588*820c1a8dSHiroo HAYASHI }
1589*820c1a8dSHiroo HAYASHI
1590*820c1a8dSHiroo HAYASHI /* Search for a node which is duplicated from the node ORG_NODE, and
1591*820c1a8dSHiroo HAYASHI satisfies the constraint CONSTRAINT. */
1592*820c1a8dSHiroo HAYASHI
1593*820c1a8dSHiroo HAYASHI static Idx
search_duplicated_node(const re_dfa_t * dfa,Idx org_node,unsigned int constraint)1594*820c1a8dSHiroo HAYASHI search_duplicated_node (const re_dfa_t *dfa, Idx org_node,
1595*820c1a8dSHiroo HAYASHI unsigned int constraint)
1596*820c1a8dSHiroo HAYASHI {
1597*820c1a8dSHiroo HAYASHI Idx idx;
1598*820c1a8dSHiroo HAYASHI for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx)
1599*820c1a8dSHiroo HAYASHI {
1600*820c1a8dSHiroo HAYASHI if (org_node == dfa->org_indices[idx]
1601*820c1a8dSHiroo HAYASHI && constraint == dfa->nodes[idx].constraint)
1602*820c1a8dSHiroo HAYASHI return idx; /* Found. */
1603*820c1a8dSHiroo HAYASHI }
1604*820c1a8dSHiroo HAYASHI return -1; /* Not found. */
1605*820c1a8dSHiroo HAYASHI }
1606*820c1a8dSHiroo HAYASHI
1607*820c1a8dSHiroo HAYASHI /* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT.
1608*820c1a8dSHiroo HAYASHI Return the index of the new node, or -1 if insufficient storage is
1609*820c1a8dSHiroo HAYASHI available. */
1610*820c1a8dSHiroo HAYASHI
1611*820c1a8dSHiroo HAYASHI static Idx
duplicate_node(re_dfa_t * dfa,Idx org_idx,unsigned int constraint)1612*820c1a8dSHiroo HAYASHI duplicate_node (re_dfa_t *dfa, Idx org_idx, unsigned int constraint)
1613*820c1a8dSHiroo HAYASHI {
1614*820c1a8dSHiroo HAYASHI Idx dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]);
1615*820c1a8dSHiroo HAYASHI if (__glibc_likely (dup_idx != -1))
1616*820c1a8dSHiroo HAYASHI {
1617*820c1a8dSHiroo HAYASHI dfa->nodes[dup_idx].constraint = constraint;
1618*820c1a8dSHiroo HAYASHI dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].constraint;
1619*820c1a8dSHiroo HAYASHI dfa->nodes[dup_idx].duplicated = 1;
1620*820c1a8dSHiroo HAYASHI
1621*820c1a8dSHiroo HAYASHI /* Store the index of the original node. */
1622*820c1a8dSHiroo HAYASHI dfa->org_indices[dup_idx] = org_idx;
1623*820c1a8dSHiroo HAYASHI }
1624*820c1a8dSHiroo HAYASHI return dup_idx;
1625*820c1a8dSHiroo HAYASHI }
1626*820c1a8dSHiroo HAYASHI
1627*820c1a8dSHiroo HAYASHI static reg_errcode_t
calc_inveclosure(re_dfa_t * dfa)1628*820c1a8dSHiroo HAYASHI calc_inveclosure (re_dfa_t *dfa)
1629*820c1a8dSHiroo HAYASHI {
1630*820c1a8dSHiroo HAYASHI Idx src, idx;
1631*820c1a8dSHiroo HAYASHI bool ok;
1632*820c1a8dSHiroo HAYASHI for (idx = 0; idx < dfa->nodes_len; ++idx)
1633*820c1a8dSHiroo HAYASHI re_node_set_init_empty (dfa->inveclosures + idx);
1634*820c1a8dSHiroo HAYASHI
1635*820c1a8dSHiroo HAYASHI for (src = 0; src < dfa->nodes_len; ++src)
1636*820c1a8dSHiroo HAYASHI {
1637*820c1a8dSHiroo HAYASHI Idx *elems = dfa->eclosures[src].elems;
1638*820c1a8dSHiroo HAYASHI for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx)
1639*820c1a8dSHiroo HAYASHI {
1640*820c1a8dSHiroo HAYASHI ok = re_node_set_insert_last (dfa->inveclosures + elems[idx], src);
1641*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (! ok))
1642*820c1a8dSHiroo HAYASHI return REG_ESPACE;
1643*820c1a8dSHiroo HAYASHI }
1644*820c1a8dSHiroo HAYASHI }
1645*820c1a8dSHiroo HAYASHI
1646*820c1a8dSHiroo HAYASHI return REG_NOERROR;
1647*820c1a8dSHiroo HAYASHI }
1648*820c1a8dSHiroo HAYASHI
1649*820c1a8dSHiroo HAYASHI /* Calculate "eclosure" for all the node in DFA. */
1650*820c1a8dSHiroo HAYASHI
1651*820c1a8dSHiroo HAYASHI static reg_errcode_t
calc_eclosure(re_dfa_t * dfa)1652*820c1a8dSHiroo HAYASHI calc_eclosure (re_dfa_t *dfa)
1653*820c1a8dSHiroo HAYASHI {
1654*820c1a8dSHiroo HAYASHI Idx node_idx;
1655*820c1a8dSHiroo HAYASHI bool incomplete;
1656*820c1a8dSHiroo HAYASHI DEBUG_ASSERT (dfa->nodes_len > 0);
1657*820c1a8dSHiroo HAYASHI incomplete = false;
1658*820c1a8dSHiroo HAYASHI /* For each nodes, calculate epsilon closure. */
1659*820c1a8dSHiroo HAYASHI for (node_idx = 0; ; ++node_idx)
1660*820c1a8dSHiroo HAYASHI {
1661*820c1a8dSHiroo HAYASHI reg_errcode_t err;
1662*820c1a8dSHiroo HAYASHI re_node_set eclosure_elem;
1663*820c1a8dSHiroo HAYASHI if (node_idx == dfa->nodes_len)
1664*820c1a8dSHiroo HAYASHI {
1665*820c1a8dSHiroo HAYASHI if (!incomplete)
1666*820c1a8dSHiroo HAYASHI break;
1667*820c1a8dSHiroo HAYASHI incomplete = false;
1668*820c1a8dSHiroo HAYASHI node_idx = 0;
1669*820c1a8dSHiroo HAYASHI }
1670*820c1a8dSHiroo HAYASHI
1671*820c1a8dSHiroo HAYASHI DEBUG_ASSERT (dfa->eclosures[node_idx].nelem != -1);
1672*820c1a8dSHiroo HAYASHI
1673*820c1a8dSHiroo HAYASHI /* If we have already calculated, skip it. */
1674*820c1a8dSHiroo HAYASHI if (dfa->eclosures[node_idx].nelem != 0)
1675*820c1a8dSHiroo HAYASHI continue;
1676*820c1a8dSHiroo HAYASHI /* Calculate epsilon closure of 'node_idx'. */
1677*820c1a8dSHiroo HAYASHI err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, true);
1678*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (err != REG_NOERROR))
1679*820c1a8dSHiroo HAYASHI return err;
1680*820c1a8dSHiroo HAYASHI
1681*820c1a8dSHiroo HAYASHI if (dfa->eclosures[node_idx].nelem == 0)
1682*820c1a8dSHiroo HAYASHI {
1683*820c1a8dSHiroo HAYASHI incomplete = true;
1684*820c1a8dSHiroo HAYASHI re_node_set_free (&eclosure_elem);
1685*820c1a8dSHiroo HAYASHI }
1686*820c1a8dSHiroo HAYASHI }
1687*820c1a8dSHiroo HAYASHI return REG_NOERROR;
1688*820c1a8dSHiroo HAYASHI }
1689*820c1a8dSHiroo HAYASHI
1690*820c1a8dSHiroo HAYASHI /* Calculate epsilon closure of NODE. */
1691*820c1a8dSHiroo HAYASHI
1692*820c1a8dSHiroo HAYASHI static reg_errcode_t
calc_eclosure_iter(re_node_set * new_set,re_dfa_t * dfa,Idx node,bool root)1693*820c1a8dSHiroo HAYASHI calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, Idx node, bool root)
1694*820c1a8dSHiroo HAYASHI {
1695*820c1a8dSHiroo HAYASHI reg_errcode_t err;
1696*820c1a8dSHiroo HAYASHI Idx i;
1697*820c1a8dSHiroo HAYASHI re_node_set eclosure;
1698*820c1a8dSHiroo HAYASHI bool incomplete = false;
1699*820c1a8dSHiroo HAYASHI err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1);
1700*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (err != REG_NOERROR))
1701*820c1a8dSHiroo HAYASHI return err;
1702*820c1a8dSHiroo HAYASHI
1703*820c1a8dSHiroo HAYASHI /* An epsilon closure includes itself. */
1704*820c1a8dSHiroo HAYASHI eclosure.elems[eclosure.nelem++] = node;
1705*820c1a8dSHiroo HAYASHI
1706*820c1a8dSHiroo HAYASHI /* This indicates that we are calculating this node now.
1707*820c1a8dSHiroo HAYASHI We reference this value to avoid infinite loop. */
1708*820c1a8dSHiroo HAYASHI dfa->eclosures[node].nelem = -1;
1709*820c1a8dSHiroo HAYASHI
1710*820c1a8dSHiroo HAYASHI /* If the current node has constraints, duplicate all nodes
1711*820c1a8dSHiroo HAYASHI since they must inherit the constraints. */
1712*820c1a8dSHiroo HAYASHI if (dfa->nodes[node].constraint
1713*820c1a8dSHiroo HAYASHI && dfa->edests[node].nelem
1714*820c1a8dSHiroo HAYASHI && !dfa->nodes[dfa->edests[node].elems[0]].duplicated)
1715*820c1a8dSHiroo HAYASHI {
1716*820c1a8dSHiroo HAYASHI err = duplicate_node_closure (dfa, node, node, node,
1717*820c1a8dSHiroo HAYASHI dfa->nodes[node].constraint);
1718*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (err != REG_NOERROR))
1719*820c1a8dSHiroo HAYASHI return err;
1720*820c1a8dSHiroo HAYASHI }
1721*820c1a8dSHiroo HAYASHI
1722*820c1a8dSHiroo HAYASHI /* Expand each epsilon destination nodes. */
1723*820c1a8dSHiroo HAYASHI if (IS_EPSILON_NODE(dfa->nodes[node].type))
1724*820c1a8dSHiroo HAYASHI for (i = 0; i < dfa->edests[node].nelem; ++i)
1725*820c1a8dSHiroo HAYASHI {
1726*820c1a8dSHiroo HAYASHI re_node_set eclosure_elem;
1727*820c1a8dSHiroo HAYASHI Idx edest = dfa->edests[node].elems[i];
1728*820c1a8dSHiroo HAYASHI /* If calculating the epsilon closure of 'edest' is in progress,
1729*820c1a8dSHiroo HAYASHI return intermediate result. */
1730*820c1a8dSHiroo HAYASHI if (dfa->eclosures[edest].nelem == -1)
1731*820c1a8dSHiroo HAYASHI {
1732*820c1a8dSHiroo HAYASHI incomplete = true;
1733*820c1a8dSHiroo HAYASHI continue;
1734*820c1a8dSHiroo HAYASHI }
1735*820c1a8dSHiroo HAYASHI /* If we haven't calculated the epsilon closure of 'edest' yet,
1736*820c1a8dSHiroo HAYASHI calculate now. Otherwise use calculated epsilon closure. */
1737*820c1a8dSHiroo HAYASHI if (dfa->eclosures[edest].nelem == 0)
1738*820c1a8dSHiroo HAYASHI {
1739*820c1a8dSHiroo HAYASHI err = calc_eclosure_iter (&eclosure_elem, dfa, edest, false);
1740*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (err != REG_NOERROR))
1741*820c1a8dSHiroo HAYASHI return err;
1742*820c1a8dSHiroo HAYASHI }
1743*820c1a8dSHiroo HAYASHI else
1744*820c1a8dSHiroo HAYASHI eclosure_elem = dfa->eclosures[edest];
1745*820c1a8dSHiroo HAYASHI /* Merge the epsilon closure of 'edest'. */
1746*820c1a8dSHiroo HAYASHI err = re_node_set_merge (&eclosure, &eclosure_elem);
1747*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (err != REG_NOERROR))
1748*820c1a8dSHiroo HAYASHI return err;
1749*820c1a8dSHiroo HAYASHI /* If the epsilon closure of 'edest' is incomplete,
1750*820c1a8dSHiroo HAYASHI the epsilon closure of this node is also incomplete. */
1751*820c1a8dSHiroo HAYASHI if (dfa->eclosures[edest].nelem == 0)
1752*820c1a8dSHiroo HAYASHI {
1753*820c1a8dSHiroo HAYASHI incomplete = true;
1754*820c1a8dSHiroo HAYASHI re_node_set_free (&eclosure_elem);
1755*820c1a8dSHiroo HAYASHI }
1756*820c1a8dSHiroo HAYASHI }
1757*820c1a8dSHiroo HAYASHI
1758*820c1a8dSHiroo HAYASHI if (incomplete && !root)
1759*820c1a8dSHiroo HAYASHI dfa->eclosures[node].nelem = 0;
1760*820c1a8dSHiroo HAYASHI else
1761*820c1a8dSHiroo HAYASHI dfa->eclosures[node] = eclosure;
1762*820c1a8dSHiroo HAYASHI *new_set = eclosure;
1763*820c1a8dSHiroo HAYASHI return REG_NOERROR;
1764*820c1a8dSHiroo HAYASHI }
1765*820c1a8dSHiroo HAYASHI
1766*820c1a8dSHiroo HAYASHI /* Functions for token which are used in the parser. */
1767*820c1a8dSHiroo HAYASHI
1768*820c1a8dSHiroo HAYASHI /* Fetch a token from INPUT.
1769*820c1a8dSHiroo HAYASHI We must not use this function inside bracket expressions. */
1770*820c1a8dSHiroo HAYASHI
1771*820c1a8dSHiroo HAYASHI static void
fetch_token(re_token_t * result,re_string_t * input,reg_syntax_t syntax)1772*820c1a8dSHiroo HAYASHI fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax)
1773*820c1a8dSHiroo HAYASHI {
1774*820c1a8dSHiroo HAYASHI re_string_skip_bytes (input, peek_token (result, input, syntax));
1775*820c1a8dSHiroo HAYASHI }
1776*820c1a8dSHiroo HAYASHI
1777*820c1a8dSHiroo HAYASHI /* Peek a token from INPUT, and return the length of the token.
1778*820c1a8dSHiroo HAYASHI We must not use this function inside bracket expressions. */
1779*820c1a8dSHiroo HAYASHI
1780*820c1a8dSHiroo HAYASHI static int
peek_token(re_token_t * token,re_string_t * input,reg_syntax_t syntax)1781*820c1a8dSHiroo HAYASHI peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
1782*820c1a8dSHiroo HAYASHI {
1783*820c1a8dSHiroo HAYASHI unsigned char c;
1784*820c1a8dSHiroo HAYASHI
1785*820c1a8dSHiroo HAYASHI if (re_string_eoi (input))
1786*820c1a8dSHiroo HAYASHI {
1787*820c1a8dSHiroo HAYASHI token->type = END_OF_RE;
1788*820c1a8dSHiroo HAYASHI return 0;
1789*820c1a8dSHiroo HAYASHI }
1790*820c1a8dSHiroo HAYASHI
1791*820c1a8dSHiroo HAYASHI c = re_string_peek_byte (input, 0);
1792*820c1a8dSHiroo HAYASHI token->opr.c = c;
1793*820c1a8dSHiroo HAYASHI
1794*820c1a8dSHiroo HAYASHI token->word_char = 0;
1795*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
1796*820c1a8dSHiroo HAYASHI token->mb_partial = 0;
1797*820c1a8dSHiroo HAYASHI if (input->mb_cur_max > 1
1798*820c1a8dSHiroo HAYASHI && !re_string_first_byte (input, re_string_cur_idx (input)))
1799*820c1a8dSHiroo HAYASHI {
1800*820c1a8dSHiroo HAYASHI token->type = CHARACTER;
1801*820c1a8dSHiroo HAYASHI token->mb_partial = 1;
1802*820c1a8dSHiroo HAYASHI return 1;
1803*820c1a8dSHiroo HAYASHI }
1804*820c1a8dSHiroo HAYASHI #endif
1805*820c1a8dSHiroo HAYASHI if (c == '\\')
1806*820c1a8dSHiroo HAYASHI {
1807*820c1a8dSHiroo HAYASHI unsigned char c2;
1808*820c1a8dSHiroo HAYASHI if (re_string_cur_idx (input) + 1 >= re_string_length (input))
1809*820c1a8dSHiroo HAYASHI {
1810*820c1a8dSHiroo HAYASHI token->type = BACK_SLASH;
1811*820c1a8dSHiroo HAYASHI return 1;
1812*820c1a8dSHiroo HAYASHI }
1813*820c1a8dSHiroo HAYASHI
1814*820c1a8dSHiroo HAYASHI c2 = re_string_peek_byte_case (input, 1);
1815*820c1a8dSHiroo HAYASHI token->opr.c = c2;
1816*820c1a8dSHiroo HAYASHI token->type = CHARACTER;
1817*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
1818*820c1a8dSHiroo HAYASHI if (input->mb_cur_max > 1)
1819*820c1a8dSHiroo HAYASHI {
1820*820c1a8dSHiroo HAYASHI wint_t wc = re_string_wchar_at (input,
1821*820c1a8dSHiroo HAYASHI re_string_cur_idx (input) + 1);
1822*820c1a8dSHiroo HAYASHI token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
1823*820c1a8dSHiroo HAYASHI }
1824*820c1a8dSHiroo HAYASHI else
1825*820c1a8dSHiroo HAYASHI #endif
1826*820c1a8dSHiroo HAYASHI token->word_char = IS_WORD_CHAR (c2) != 0;
1827*820c1a8dSHiroo HAYASHI
1828*820c1a8dSHiroo HAYASHI switch (c2)
1829*820c1a8dSHiroo HAYASHI {
1830*820c1a8dSHiroo HAYASHI case '|':
1831*820c1a8dSHiroo HAYASHI if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR))
1832*820c1a8dSHiroo HAYASHI token->type = OP_ALT;
1833*820c1a8dSHiroo HAYASHI break;
1834*820c1a8dSHiroo HAYASHI case '1': case '2': case '3': case '4': case '5':
1835*820c1a8dSHiroo HAYASHI case '6': case '7': case '8': case '9':
1836*820c1a8dSHiroo HAYASHI if (!(syntax & RE_NO_BK_REFS))
1837*820c1a8dSHiroo HAYASHI {
1838*820c1a8dSHiroo HAYASHI token->type = OP_BACK_REF;
1839*820c1a8dSHiroo HAYASHI token->opr.idx = c2 - '1';
1840*820c1a8dSHiroo HAYASHI }
1841*820c1a8dSHiroo HAYASHI break;
1842*820c1a8dSHiroo HAYASHI case '<':
1843*820c1a8dSHiroo HAYASHI if (!(syntax & RE_NO_GNU_OPS))
1844*820c1a8dSHiroo HAYASHI {
1845*820c1a8dSHiroo HAYASHI token->type = ANCHOR;
1846*820c1a8dSHiroo HAYASHI token->opr.ctx_type = WORD_FIRST;
1847*820c1a8dSHiroo HAYASHI }
1848*820c1a8dSHiroo HAYASHI break;
1849*820c1a8dSHiroo HAYASHI case '>':
1850*820c1a8dSHiroo HAYASHI if (!(syntax & RE_NO_GNU_OPS))
1851*820c1a8dSHiroo HAYASHI {
1852*820c1a8dSHiroo HAYASHI token->type = ANCHOR;
1853*820c1a8dSHiroo HAYASHI token->opr.ctx_type = WORD_LAST;
1854*820c1a8dSHiroo HAYASHI }
1855*820c1a8dSHiroo HAYASHI break;
1856*820c1a8dSHiroo HAYASHI case 'b':
1857*820c1a8dSHiroo HAYASHI if (!(syntax & RE_NO_GNU_OPS))
1858*820c1a8dSHiroo HAYASHI {
1859*820c1a8dSHiroo HAYASHI token->type = ANCHOR;
1860*820c1a8dSHiroo HAYASHI token->opr.ctx_type = WORD_DELIM;
1861*820c1a8dSHiroo HAYASHI }
1862*820c1a8dSHiroo HAYASHI break;
1863*820c1a8dSHiroo HAYASHI case 'B':
1864*820c1a8dSHiroo HAYASHI if (!(syntax & RE_NO_GNU_OPS))
1865*820c1a8dSHiroo HAYASHI {
1866*820c1a8dSHiroo HAYASHI token->type = ANCHOR;
1867*820c1a8dSHiroo HAYASHI token->opr.ctx_type = NOT_WORD_DELIM;
1868*820c1a8dSHiroo HAYASHI }
1869*820c1a8dSHiroo HAYASHI break;
1870*820c1a8dSHiroo HAYASHI case 'w':
1871*820c1a8dSHiroo HAYASHI if (!(syntax & RE_NO_GNU_OPS))
1872*820c1a8dSHiroo HAYASHI token->type = OP_WORD;
1873*820c1a8dSHiroo HAYASHI break;
1874*820c1a8dSHiroo HAYASHI case 'W':
1875*820c1a8dSHiroo HAYASHI if (!(syntax & RE_NO_GNU_OPS))
1876*820c1a8dSHiroo HAYASHI token->type = OP_NOTWORD;
1877*820c1a8dSHiroo HAYASHI break;
1878*820c1a8dSHiroo HAYASHI case 's':
1879*820c1a8dSHiroo HAYASHI if (!(syntax & RE_NO_GNU_OPS))
1880*820c1a8dSHiroo HAYASHI token->type = OP_SPACE;
1881*820c1a8dSHiroo HAYASHI break;
1882*820c1a8dSHiroo HAYASHI case 'S':
1883*820c1a8dSHiroo HAYASHI if (!(syntax & RE_NO_GNU_OPS))
1884*820c1a8dSHiroo HAYASHI token->type = OP_NOTSPACE;
1885*820c1a8dSHiroo HAYASHI break;
1886*820c1a8dSHiroo HAYASHI case '`':
1887*820c1a8dSHiroo HAYASHI if (!(syntax & RE_NO_GNU_OPS))
1888*820c1a8dSHiroo HAYASHI {
1889*820c1a8dSHiroo HAYASHI token->type = ANCHOR;
1890*820c1a8dSHiroo HAYASHI token->opr.ctx_type = BUF_FIRST;
1891*820c1a8dSHiroo HAYASHI }
1892*820c1a8dSHiroo HAYASHI break;
1893*820c1a8dSHiroo HAYASHI case '\'':
1894*820c1a8dSHiroo HAYASHI if (!(syntax & RE_NO_GNU_OPS))
1895*820c1a8dSHiroo HAYASHI {
1896*820c1a8dSHiroo HAYASHI token->type = ANCHOR;
1897*820c1a8dSHiroo HAYASHI token->opr.ctx_type = BUF_LAST;
1898*820c1a8dSHiroo HAYASHI }
1899*820c1a8dSHiroo HAYASHI break;
1900*820c1a8dSHiroo HAYASHI case '(':
1901*820c1a8dSHiroo HAYASHI if (!(syntax & RE_NO_BK_PARENS))
1902*820c1a8dSHiroo HAYASHI token->type = OP_OPEN_SUBEXP;
1903*820c1a8dSHiroo HAYASHI break;
1904*820c1a8dSHiroo HAYASHI case ')':
1905*820c1a8dSHiroo HAYASHI if (!(syntax & RE_NO_BK_PARENS))
1906*820c1a8dSHiroo HAYASHI token->type = OP_CLOSE_SUBEXP;
1907*820c1a8dSHiroo HAYASHI break;
1908*820c1a8dSHiroo HAYASHI case '+':
1909*820c1a8dSHiroo HAYASHI if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))
1910*820c1a8dSHiroo HAYASHI token->type = OP_DUP_PLUS;
1911*820c1a8dSHiroo HAYASHI break;
1912*820c1a8dSHiroo HAYASHI case '?':
1913*820c1a8dSHiroo HAYASHI if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))
1914*820c1a8dSHiroo HAYASHI token->type = OP_DUP_QUESTION;
1915*820c1a8dSHiroo HAYASHI break;
1916*820c1a8dSHiroo HAYASHI case '{':
1917*820c1a8dSHiroo HAYASHI if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))
1918*820c1a8dSHiroo HAYASHI token->type = OP_OPEN_DUP_NUM;
1919*820c1a8dSHiroo HAYASHI break;
1920*820c1a8dSHiroo HAYASHI case '}':
1921*820c1a8dSHiroo HAYASHI if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))
1922*820c1a8dSHiroo HAYASHI token->type = OP_CLOSE_DUP_NUM;
1923*820c1a8dSHiroo HAYASHI break;
1924*820c1a8dSHiroo HAYASHI default:
1925*820c1a8dSHiroo HAYASHI break;
1926*820c1a8dSHiroo HAYASHI }
1927*820c1a8dSHiroo HAYASHI return 2;
1928*820c1a8dSHiroo HAYASHI }
1929*820c1a8dSHiroo HAYASHI
1930*820c1a8dSHiroo HAYASHI token->type = CHARACTER;
1931*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
1932*820c1a8dSHiroo HAYASHI if (input->mb_cur_max > 1)
1933*820c1a8dSHiroo HAYASHI {
1934*820c1a8dSHiroo HAYASHI wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input));
1935*820c1a8dSHiroo HAYASHI token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;
1936*820c1a8dSHiroo HAYASHI }
1937*820c1a8dSHiroo HAYASHI else
1938*820c1a8dSHiroo HAYASHI #endif
1939*820c1a8dSHiroo HAYASHI token->word_char = IS_WORD_CHAR (token->opr.c);
1940*820c1a8dSHiroo HAYASHI
1941*820c1a8dSHiroo HAYASHI switch (c)
1942*820c1a8dSHiroo HAYASHI {
1943*820c1a8dSHiroo HAYASHI case '\n':
1944*820c1a8dSHiroo HAYASHI if (syntax & RE_NEWLINE_ALT)
1945*820c1a8dSHiroo HAYASHI token->type = OP_ALT;
1946*820c1a8dSHiroo HAYASHI break;
1947*820c1a8dSHiroo HAYASHI case '|':
1948*820c1a8dSHiroo HAYASHI if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR))
1949*820c1a8dSHiroo HAYASHI token->type = OP_ALT;
1950*820c1a8dSHiroo HAYASHI break;
1951*820c1a8dSHiroo HAYASHI case '*':
1952*820c1a8dSHiroo HAYASHI token->type = OP_DUP_ASTERISK;
1953*820c1a8dSHiroo HAYASHI break;
1954*820c1a8dSHiroo HAYASHI case '+':
1955*820c1a8dSHiroo HAYASHI if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))
1956*820c1a8dSHiroo HAYASHI token->type = OP_DUP_PLUS;
1957*820c1a8dSHiroo HAYASHI break;
1958*820c1a8dSHiroo HAYASHI case '?':
1959*820c1a8dSHiroo HAYASHI if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))
1960*820c1a8dSHiroo HAYASHI token->type = OP_DUP_QUESTION;
1961*820c1a8dSHiroo HAYASHI break;
1962*820c1a8dSHiroo HAYASHI case '{':
1963*820c1a8dSHiroo HAYASHI if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
1964*820c1a8dSHiroo HAYASHI token->type = OP_OPEN_DUP_NUM;
1965*820c1a8dSHiroo HAYASHI break;
1966*820c1a8dSHiroo HAYASHI case '}':
1967*820c1a8dSHiroo HAYASHI if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))
1968*820c1a8dSHiroo HAYASHI token->type = OP_CLOSE_DUP_NUM;
1969*820c1a8dSHiroo HAYASHI break;
1970*820c1a8dSHiroo HAYASHI case '(':
1971*820c1a8dSHiroo HAYASHI if (syntax & RE_NO_BK_PARENS)
1972*820c1a8dSHiroo HAYASHI token->type = OP_OPEN_SUBEXP;
1973*820c1a8dSHiroo HAYASHI break;
1974*820c1a8dSHiroo HAYASHI case ')':
1975*820c1a8dSHiroo HAYASHI if (syntax & RE_NO_BK_PARENS)
1976*820c1a8dSHiroo HAYASHI token->type = OP_CLOSE_SUBEXP;
1977*820c1a8dSHiroo HAYASHI break;
1978*820c1a8dSHiroo HAYASHI case '[':
1979*820c1a8dSHiroo HAYASHI token->type = OP_OPEN_BRACKET;
1980*820c1a8dSHiroo HAYASHI break;
1981*820c1a8dSHiroo HAYASHI case '.':
1982*820c1a8dSHiroo HAYASHI token->type = OP_PERIOD;
1983*820c1a8dSHiroo HAYASHI break;
1984*820c1a8dSHiroo HAYASHI case '^':
1985*820c1a8dSHiroo HAYASHI if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE))
1986*820c1a8dSHiroo HAYASHI && re_string_cur_idx (input) != 0)
1987*820c1a8dSHiroo HAYASHI {
1988*820c1a8dSHiroo HAYASHI char prev = re_string_peek_byte (input, -1);
1989*820c1a8dSHiroo HAYASHI if (!(syntax & RE_NEWLINE_ALT) || prev != '\n')
1990*820c1a8dSHiroo HAYASHI break;
1991*820c1a8dSHiroo HAYASHI }
1992*820c1a8dSHiroo HAYASHI token->type = ANCHOR;
1993*820c1a8dSHiroo HAYASHI token->opr.ctx_type = LINE_FIRST;
1994*820c1a8dSHiroo HAYASHI break;
1995*820c1a8dSHiroo HAYASHI case '$':
1996*820c1a8dSHiroo HAYASHI if (!(syntax & RE_CONTEXT_INDEP_ANCHORS)
1997*820c1a8dSHiroo HAYASHI && re_string_cur_idx (input) + 1 != re_string_length (input))
1998*820c1a8dSHiroo HAYASHI {
1999*820c1a8dSHiroo HAYASHI re_token_t next;
2000*820c1a8dSHiroo HAYASHI re_string_skip_bytes (input, 1);
2001*820c1a8dSHiroo HAYASHI peek_token (&next, input, syntax);
2002*820c1a8dSHiroo HAYASHI re_string_skip_bytes (input, -1);
2003*820c1a8dSHiroo HAYASHI if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP)
2004*820c1a8dSHiroo HAYASHI break;
2005*820c1a8dSHiroo HAYASHI }
2006*820c1a8dSHiroo HAYASHI token->type = ANCHOR;
2007*820c1a8dSHiroo HAYASHI token->opr.ctx_type = LINE_LAST;
2008*820c1a8dSHiroo HAYASHI break;
2009*820c1a8dSHiroo HAYASHI default:
2010*820c1a8dSHiroo HAYASHI break;
2011*820c1a8dSHiroo HAYASHI }
2012*820c1a8dSHiroo HAYASHI return 1;
2013*820c1a8dSHiroo HAYASHI }
2014*820c1a8dSHiroo HAYASHI
2015*820c1a8dSHiroo HAYASHI /* Peek a token from INPUT, and return the length of the token.
2016*820c1a8dSHiroo HAYASHI We must not use this function out of bracket expressions. */
2017*820c1a8dSHiroo HAYASHI
2018*820c1a8dSHiroo HAYASHI static int
peek_token_bracket(re_token_t * token,re_string_t * input,reg_syntax_t syntax)2019*820c1a8dSHiroo HAYASHI peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax)
2020*820c1a8dSHiroo HAYASHI {
2021*820c1a8dSHiroo HAYASHI unsigned char c;
2022*820c1a8dSHiroo HAYASHI if (re_string_eoi (input))
2023*820c1a8dSHiroo HAYASHI {
2024*820c1a8dSHiroo HAYASHI token->type = END_OF_RE;
2025*820c1a8dSHiroo HAYASHI return 0;
2026*820c1a8dSHiroo HAYASHI }
2027*820c1a8dSHiroo HAYASHI c = re_string_peek_byte (input, 0);
2028*820c1a8dSHiroo HAYASHI token->opr.c = c;
2029*820c1a8dSHiroo HAYASHI
2030*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
2031*820c1a8dSHiroo HAYASHI if (input->mb_cur_max > 1
2032*820c1a8dSHiroo HAYASHI && !re_string_first_byte (input, re_string_cur_idx (input)))
2033*820c1a8dSHiroo HAYASHI {
2034*820c1a8dSHiroo HAYASHI token->type = CHARACTER;
2035*820c1a8dSHiroo HAYASHI return 1;
2036*820c1a8dSHiroo HAYASHI }
2037*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
2038*820c1a8dSHiroo HAYASHI
2039*820c1a8dSHiroo HAYASHI if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS)
2040*820c1a8dSHiroo HAYASHI && re_string_cur_idx (input) + 1 < re_string_length (input))
2041*820c1a8dSHiroo HAYASHI {
2042*820c1a8dSHiroo HAYASHI /* In this case, '\' escape a character. */
2043*820c1a8dSHiroo HAYASHI unsigned char c2;
2044*820c1a8dSHiroo HAYASHI re_string_skip_bytes (input, 1);
2045*820c1a8dSHiroo HAYASHI c2 = re_string_peek_byte (input, 0);
2046*820c1a8dSHiroo HAYASHI token->opr.c = c2;
2047*820c1a8dSHiroo HAYASHI token->type = CHARACTER;
2048*820c1a8dSHiroo HAYASHI return 1;
2049*820c1a8dSHiroo HAYASHI }
2050*820c1a8dSHiroo HAYASHI if (c == '[') /* '[' is a special char in a bracket exps. */
2051*820c1a8dSHiroo HAYASHI {
2052*820c1a8dSHiroo HAYASHI unsigned char c2;
2053*820c1a8dSHiroo HAYASHI int token_len;
2054*820c1a8dSHiroo HAYASHI if (re_string_cur_idx (input) + 1 < re_string_length (input))
2055*820c1a8dSHiroo HAYASHI c2 = re_string_peek_byte (input, 1);
2056*820c1a8dSHiroo HAYASHI else
2057*820c1a8dSHiroo HAYASHI c2 = 0;
2058*820c1a8dSHiroo HAYASHI token->opr.c = c2;
2059*820c1a8dSHiroo HAYASHI token_len = 2;
2060*820c1a8dSHiroo HAYASHI switch (c2)
2061*820c1a8dSHiroo HAYASHI {
2062*820c1a8dSHiroo HAYASHI case '.':
2063*820c1a8dSHiroo HAYASHI token->type = OP_OPEN_COLL_ELEM;
2064*820c1a8dSHiroo HAYASHI break;
2065*820c1a8dSHiroo HAYASHI
2066*820c1a8dSHiroo HAYASHI case '=':
2067*820c1a8dSHiroo HAYASHI token->type = OP_OPEN_EQUIV_CLASS;
2068*820c1a8dSHiroo HAYASHI break;
2069*820c1a8dSHiroo HAYASHI
2070*820c1a8dSHiroo HAYASHI case ':':
2071*820c1a8dSHiroo HAYASHI if (syntax & RE_CHAR_CLASSES)
2072*820c1a8dSHiroo HAYASHI {
2073*820c1a8dSHiroo HAYASHI token->type = OP_OPEN_CHAR_CLASS;
2074*820c1a8dSHiroo HAYASHI break;
2075*820c1a8dSHiroo HAYASHI }
2076*820c1a8dSHiroo HAYASHI FALLTHROUGH;
2077*820c1a8dSHiroo HAYASHI default:
2078*820c1a8dSHiroo HAYASHI token->type = CHARACTER;
2079*820c1a8dSHiroo HAYASHI token->opr.c = c;
2080*820c1a8dSHiroo HAYASHI token_len = 1;
2081*820c1a8dSHiroo HAYASHI break;
2082*820c1a8dSHiroo HAYASHI }
2083*820c1a8dSHiroo HAYASHI return token_len;
2084*820c1a8dSHiroo HAYASHI }
2085*820c1a8dSHiroo HAYASHI switch (c)
2086*820c1a8dSHiroo HAYASHI {
2087*820c1a8dSHiroo HAYASHI case '-':
2088*820c1a8dSHiroo HAYASHI token->type = OP_CHARSET_RANGE;
2089*820c1a8dSHiroo HAYASHI break;
2090*820c1a8dSHiroo HAYASHI case ']':
2091*820c1a8dSHiroo HAYASHI token->type = OP_CLOSE_BRACKET;
2092*820c1a8dSHiroo HAYASHI break;
2093*820c1a8dSHiroo HAYASHI case '^':
2094*820c1a8dSHiroo HAYASHI token->type = OP_NON_MATCH_LIST;
2095*820c1a8dSHiroo HAYASHI break;
2096*820c1a8dSHiroo HAYASHI default:
2097*820c1a8dSHiroo HAYASHI token->type = CHARACTER;
2098*820c1a8dSHiroo HAYASHI }
2099*820c1a8dSHiroo HAYASHI return 1;
2100*820c1a8dSHiroo HAYASHI }
2101*820c1a8dSHiroo HAYASHI
2102*820c1a8dSHiroo HAYASHI /* Functions for parser. */
2103*820c1a8dSHiroo HAYASHI
2104*820c1a8dSHiroo HAYASHI /* Entry point of the parser.
2105*820c1a8dSHiroo HAYASHI Parse the regular expression REGEXP and return the structure tree.
2106*820c1a8dSHiroo HAYASHI If an error occurs, ERR is set by error code, and return NULL.
2107*820c1a8dSHiroo HAYASHI This function build the following tree, from regular expression <reg_exp>:
2108*820c1a8dSHiroo HAYASHI CAT
2109*820c1a8dSHiroo HAYASHI / \
2110*820c1a8dSHiroo HAYASHI / \
2111*820c1a8dSHiroo HAYASHI <reg_exp> EOR
2112*820c1a8dSHiroo HAYASHI
2113*820c1a8dSHiroo HAYASHI CAT means concatenation.
2114*820c1a8dSHiroo HAYASHI EOR means end of regular expression. */
2115*820c1a8dSHiroo HAYASHI
2116*820c1a8dSHiroo HAYASHI static bin_tree_t *
parse(re_string_t * regexp,regex_t * preg,reg_syntax_t syntax,reg_errcode_t * err)2117*820c1a8dSHiroo HAYASHI parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax,
2118*820c1a8dSHiroo HAYASHI reg_errcode_t *err)
2119*820c1a8dSHiroo HAYASHI {
2120*820c1a8dSHiroo HAYASHI re_dfa_t *dfa = preg->buffer;
2121*820c1a8dSHiroo HAYASHI bin_tree_t *tree, *eor, *root;
2122*820c1a8dSHiroo HAYASHI re_token_t current_token;
2123*820c1a8dSHiroo HAYASHI dfa->syntax = syntax;
2124*820c1a8dSHiroo HAYASHI fetch_token (¤t_token, regexp, syntax | RE_CARET_ANCHORS_HERE);
2125*820c1a8dSHiroo HAYASHI tree = parse_reg_exp (regexp, preg, ¤t_token, syntax, 0, err);
2126*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL))
2127*820c1a8dSHiroo HAYASHI return NULL;
2128*820c1a8dSHiroo HAYASHI eor = create_tree (dfa, NULL, NULL, END_OF_RE);
2129*820c1a8dSHiroo HAYASHI if (tree != NULL)
2130*820c1a8dSHiroo HAYASHI root = create_tree (dfa, tree, eor, CONCAT);
2131*820c1a8dSHiroo HAYASHI else
2132*820c1a8dSHiroo HAYASHI root = eor;
2133*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (eor == NULL || root == NULL))
2134*820c1a8dSHiroo HAYASHI {
2135*820c1a8dSHiroo HAYASHI *err = REG_ESPACE;
2136*820c1a8dSHiroo HAYASHI return NULL;
2137*820c1a8dSHiroo HAYASHI }
2138*820c1a8dSHiroo HAYASHI return root;
2139*820c1a8dSHiroo HAYASHI }
2140*820c1a8dSHiroo HAYASHI
2141*820c1a8dSHiroo HAYASHI /* This function build the following tree, from regular expression
2142*820c1a8dSHiroo HAYASHI <branch1>|<branch2>:
2143*820c1a8dSHiroo HAYASHI ALT
2144*820c1a8dSHiroo HAYASHI / \
2145*820c1a8dSHiroo HAYASHI / \
2146*820c1a8dSHiroo HAYASHI <branch1> <branch2>
2147*820c1a8dSHiroo HAYASHI
2148*820c1a8dSHiroo HAYASHI ALT means alternative, which represents the operator '|'. */
2149*820c1a8dSHiroo HAYASHI
2150*820c1a8dSHiroo HAYASHI static bin_tree_t *
parse_reg_exp(re_string_t * regexp,regex_t * preg,re_token_t * token,reg_syntax_t syntax,Idx nest,reg_errcode_t * err)2151*820c1a8dSHiroo HAYASHI parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
2152*820c1a8dSHiroo HAYASHI reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
2153*820c1a8dSHiroo HAYASHI {
2154*820c1a8dSHiroo HAYASHI re_dfa_t *dfa = preg->buffer;
2155*820c1a8dSHiroo HAYASHI bin_tree_t *tree, *branch = NULL;
2156*820c1a8dSHiroo HAYASHI bitset_word_t initial_bkref_map = dfa->completed_bkref_map;
2157*820c1a8dSHiroo HAYASHI tree = parse_branch (regexp, preg, token, syntax, nest, err);
2158*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL))
2159*820c1a8dSHiroo HAYASHI return NULL;
2160*820c1a8dSHiroo HAYASHI
2161*820c1a8dSHiroo HAYASHI while (token->type == OP_ALT)
2162*820c1a8dSHiroo HAYASHI {
2163*820c1a8dSHiroo HAYASHI fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE);
2164*820c1a8dSHiroo HAYASHI if (token->type != OP_ALT && token->type != END_OF_RE
2165*820c1a8dSHiroo HAYASHI && (nest == 0 || token->type != OP_CLOSE_SUBEXP))
2166*820c1a8dSHiroo HAYASHI {
2167*820c1a8dSHiroo HAYASHI bitset_word_t accumulated_bkref_map = dfa->completed_bkref_map;
2168*820c1a8dSHiroo HAYASHI dfa->completed_bkref_map = initial_bkref_map;
2169*820c1a8dSHiroo HAYASHI branch = parse_branch (regexp, preg, token, syntax, nest, err);
2170*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*err != REG_NOERROR && branch == NULL))
2171*820c1a8dSHiroo HAYASHI {
2172*820c1a8dSHiroo HAYASHI if (tree != NULL)
2173*820c1a8dSHiroo HAYASHI postorder (tree, free_tree, NULL);
2174*820c1a8dSHiroo HAYASHI return NULL;
2175*820c1a8dSHiroo HAYASHI }
2176*820c1a8dSHiroo HAYASHI dfa->completed_bkref_map |= accumulated_bkref_map;
2177*820c1a8dSHiroo HAYASHI }
2178*820c1a8dSHiroo HAYASHI else
2179*820c1a8dSHiroo HAYASHI branch = NULL;
2180*820c1a8dSHiroo HAYASHI tree = create_tree (dfa, tree, branch, OP_ALT);
2181*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (tree == NULL))
2182*820c1a8dSHiroo HAYASHI {
2183*820c1a8dSHiroo HAYASHI *err = REG_ESPACE;
2184*820c1a8dSHiroo HAYASHI return NULL;
2185*820c1a8dSHiroo HAYASHI }
2186*820c1a8dSHiroo HAYASHI }
2187*820c1a8dSHiroo HAYASHI return tree;
2188*820c1a8dSHiroo HAYASHI }
2189*820c1a8dSHiroo HAYASHI
2190*820c1a8dSHiroo HAYASHI /* This function build the following tree, from regular expression
2191*820c1a8dSHiroo HAYASHI <exp1><exp2>:
2192*820c1a8dSHiroo HAYASHI CAT
2193*820c1a8dSHiroo HAYASHI / \
2194*820c1a8dSHiroo HAYASHI / \
2195*820c1a8dSHiroo HAYASHI <exp1> <exp2>
2196*820c1a8dSHiroo HAYASHI
2197*820c1a8dSHiroo HAYASHI CAT means concatenation. */
2198*820c1a8dSHiroo HAYASHI
2199*820c1a8dSHiroo HAYASHI static bin_tree_t *
parse_branch(re_string_t * regexp,regex_t * preg,re_token_t * token,reg_syntax_t syntax,Idx nest,reg_errcode_t * err)2200*820c1a8dSHiroo HAYASHI parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token,
2201*820c1a8dSHiroo HAYASHI reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
2202*820c1a8dSHiroo HAYASHI {
2203*820c1a8dSHiroo HAYASHI bin_tree_t *tree, *expr;
2204*820c1a8dSHiroo HAYASHI re_dfa_t *dfa = preg->buffer;
2205*820c1a8dSHiroo HAYASHI tree = parse_expression (regexp, preg, token, syntax, nest, err);
2206*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL))
2207*820c1a8dSHiroo HAYASHI return NULL;
2208*820c1a8dSHiroo HAYASHI
2209*820c1a8dSHiroo HAYASHI while (token->type != OP_ALT && token->type != END_OF_RE
2210*820c1a8dSHiroo HAYASHI && (nest == 0 || token->type != OP_CLOSE_SUBEXP))
2211*820c1a8dSHiroo HAYASHI {
2212*820c1a8dSHiroo HAYASHI expr = parse_expression (regexp, preg, token, syntax, nest, err);
2213*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*err != REG_NOERROR && expr == NULL))
2214*820c1a8dSHiroo HAYASHI {
2215*820c1a8dSHiroo HAYASHI if (tree != NULL)
2216*820c1a8dSHiroo HAYASHI postorder (tree, free_tree, NULL);
2217*820c1a8dSHiroo HAYASHI return NULL;
2218*820c1a8dSHiroo HAYASHI }
2219*820c1a8dSHiroo HAYASHI if (tree != NULL && expr != NULL)
2220*820c1a8dSHiroo HAYASHI {
2221*820c1a8dSHiroo HAYASHI bin_tree_t *newtree = create_tree (dfa, tree, expr, CONCAT);
2222*820c1a8dSHiroo HAYASHI if (newtree == NULL)
2223*820c1a8dSHiroo HAYASHI {
2224*820c1a8dSHiroo HAYASHI postorder (expr, free_tree, NULL);
2225*820c1a8dSHiroo HAYASHI postorder (tree, free_tree, NULL);
2226*820c1a8dSHiroo HAYASHI *err = REG_ESPACE;
2227*820c1a8dSHiroo HAYASHI return NULL;
2228*820c1a8dSHiroo HAYASHI }
2229*820c1a8dSHiroo HAYASHI tree = newtree;
2230*820c1a8dSHiroo HAYASHI }
2231*820c1a8dSHiroo HAYASHI else if (tree == NULL)
2232*820c1a8dSHiroo HAYASHI tree = expr;
2233*820c1a8dSHiroo HAYASHI /* Otherwise expr == NULL, we don't need to create new tree. */
2234*820c1a8dSHiroo HAYASHI }
2235*820c1a8dSHiroo HAYASHI return tree;
2236*820c1a8dSHiroo HAYASHI }
2237*820c1a8dSHiroo HAYASHI
2238*820c1a8dSHiroo HAYASHI /* This function build the following tree, from regular expression a*:
2239*820c1a8dSHiroo HAYASHI *
2240*820c1a8dSHiroo HAYASHI |
2241*820c1a8dSHiroo HAYASHI a
2242*820c1a8dSHiroo HAYASHI */
2243*820c1a8dSHiroo HAYASHI
2244*820c1a8dSHiroo HAYASHI static bin_tree_t *
parse_expression(re_string_t * regexp,regex_t * preg,re_token_t * token,reg_syntax_t syntax,Idx nest,reg_errcode_t * err)2245*820c1a8dSHiroo HAYASHI parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,
2246*820c1a8dSHiroo HAYASHI reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
2247*820c1a8dSHiroo HAYASHI {
2248*820c1a8dSHiroo HAYASHI re_dfa_t *dfa = preg->buffer;
2249*820c1a8dSHiroo HAYASHI bin_tree_t *tree;
2250*820c1a8dSHiroo HAYASHI switch (token->type)
2251*820c1a8dSHiroo HAYASHI {
2252*820c1a8dSHiroo HAYASHI case CHARACTER:
2253*820c1a8dSHiroo HAYASHI tree = create_token_tree (dfa, NULL, NULL, token);
2254*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (tree == NULL))
2255*820c1a8dSHiroo HAYASHI {
2256*820c1a8dSHiroo HAYASHI *err = REG_ESPACE;
2257*820c1a8dSHiroo HAYASHI return NULL;
2258*820c1a8dSHiroo HAYASHI }
2259*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
2260*820c1a8dSHiroo HAYASHI if (dfa->mb_cur_max > 1)
2261*820c1a8dSHiroo HAYASHI {
2262*820c1a8dSHiroo HAYASHI while (!re_string_eoi (regexp)
2263*820c1a8dSHiroo HAYASHI && !re_string_first_byte (regexp, re_string_cur_idx (regexp)))
2264*820c1a8dSHiroo HAYASHI {
2265*820c1a8dSHiroo HAYASHI bin_tree_t *mbc_remain;
2266*820c1a8dSHiroo HAYASHI fetch_token (token, regexp, syntax);
2267*820c1a8dSHiroo HAYASHI mbc_remain = create_token_tree (dfa, NULL, NULL, token);
2268*820c1a8dSHiroo HAYASHI tree = create_tree (dfa, tree, mbc_remain, CONCAT);
2269*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (mbc_remain == NULL || tree == NULL))
2270*820c1a8dSHiroo HAYASHI {
2271*820c1a8dSHiroo HAYASHI *err = REG_ESPACE;
2272*820c1a8dSHiroo HAYASHI return NULL;
2273*820c1a8dSHiroo HAYASHI }
2274*820c1a8dSHiroo HAYASHI }
2275*820c1a8dSHiroo HAYASHI }
2276*820c1a8dSHiroo HAYASHI #endif
2277*820c1a8dSHiroo HAYASHI break;
2278*820c1a8dSHiroo HAYASHI
2279*820c1a8dSHiroo HAYASHI case OP_OPEN_SUBEXP:
2280*820c1a8dSHiroo HAYASHI tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err);
2281*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL))
2282*820c1a8dSHiroo HAYASHI return NULL;
2283*820c1a8dSHiroo HAYASHI break;
2284*820c1a8dSHiroo HAYASHI
2285*820c1a8dSHiroo HAYASHI case OP_OPEN_BRACKET:
2286*820c1a8dSHiroo HAYASHI tree = parse_bracket_exp (regexp, dfa, token, syntax, err);
2287*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL))
2288*820c1a8dSHiroo HAYASHI return NULL;
2289*820c1a8dSHiroo HAYASHI break;
2290*820c1a8dSHiroo HAYASHI
2291*820c1a8dSHiroo HAYASHI case OP_BACK_REF:
2292*820c1a8dSHiroo HAYASHI if (!__glibc_likely (dfa->completed_bkref_map & (1 << token->opr.idx)))
2293*820c1a8dSHiroo HAYASHI {
2294*820c1a8dSHiroo HAYASHI *err = REG_ESUBREG;
2295*820c1a8dSHiroo HAYASHI return NULL;
2296*820c1a8dSHiroo HAYASHI }
2297*820c1a8dSHiroo HAYASHI dfa->used_bkref_map |= 1 << token->opr.idx;
2298*820c1a8dSHiroo HAYASHI tree = create_token_tree (dfa, NULL, NULL, token);
2299*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (tree == NULL))
2300*820c1a8dSHiroo HAYASHI {
2301*820c1a8dSHiroo HAYASHI *err = REG_ESPACE;
2302*820c1a8dSHiroo HAYASHI return NULL;
2303*820c1a8dSHiroo HAYASHI }
2304*820c1a8dSHiroo HAYASHI ++dfa->nbackref;
2305*820c1a8dSHiroo HAYASHI dfa->has_mb_node = 1;
2306*820c1a8dSHiroo HAYASHI break;
2307*820c1a8dSHiroo HAYASHI
2308*820c1a8dSHiroo HAYASHI case OP_OPEN_DUP_NUM:
2309*820c1a8dSHiroo HAYASHI if (syntax & RE_CONTEXT_INVALID_DUP)
2310*820c1a8dSHiroo HAYASHI {
2311*820c1a8dSHiroo HAYASHI *err = REG_BADRPT;
2312*820c1a8dSHiroo HAYASHI return NULL;
2313*820c1a8dSHiroo HAYASHI }
2314*820c1a8dSHiroo HAYASHI FALLTHROUGH;
2315*820c1a8dSHiroo HAYASHI case OP_DUP_ASTERISK:
2316*820c1a8dSHiroo HAYASHI case OP_DUP_PLUS:
2317*820c1a8dSHiroo HAYASHI case OP_DUP_QUESTION:
2318*820c1a8dSHiroo HAYASHI if (syntax & RE_CONTEXT_INVALID_OPS)
2319*820c1a8dSHiroo HAYASHI {
2320*820c1a8dSHiroo HAYASHI *err = REG_BADRPT;
2321*820c1a8dSHiroo HAYASHI return NULL;
2322*820c1a8dSHiroo HAYASHI }
2323*820c1a8dSHiroo HAYASHI else if (syntax & RE_CONTEXT_INDEP_OPS)
2324*820c1a8dSHiroo HAYASHI {
2325*820c1a8dSHiroo HAYASHI fetch_token (token, regexp, syntax);
2326*820c1a8dSHiroo HAYASHI return parse_expression (regexp, preg, token, syntax, nest, err);
2327*820c1a8dSHiroo HAYASHI }
2328*820c1a8dSHiroo HAYASHI FALLTHROUGH;
2329*820c1a8dSHiroo HAYASHI case OP_CLOSE_SUBEXP:
2330*820c1a8dSHiroo HAYASHI if ((token->type == OP_CLOSE_SUBEXP)
2331*820c1a8dSHiroo HAYASHI && !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD))
2332*820c1a8dSHiroo HAYASHI {
2333*820c1a8dSHiroo HAYASHI *err = REG_ERPAREN;
2334*820c1a8dSHiroo HAYASHI return NULL;
2335*820c1a8dSHiroo HAYASHI }
2336*820c1a8dSHiroo HAYASHI FALLTHROUGH;
2337*820c1a8dSHiroo HAYASHI case OP_CLOSE_DUP_NUM:
2338*820c1a8dSHiroo HAYASHI /* We treat it as a normal character. */
2339*820c1a8dSHiroo HAYASHI
2340*820c1a8dSHiroo HAYASHI /* Then we can these characters as normal characters. */
2341*820c1a8dSHiroo HAYASHI token->type = CHARACTER;
2342*820c1a8dSHiroo HAYASHI /* mb_partial and word_char bits should be initialized already
2343*820c1a8dSHiroo HAYASHI by peek_token. */
2344*820c1a8dSHiroo HAYASHI tree = create_token_tree (dfa, NULL, NULL, token);
2345*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (tree == NULL))
2346*820c1a8dSHiroo HAYASHI {
2347*820c1a8dSHiroo HAYASHI *err = REG_ESPACE;
2348*820c1a8dSHiroo HAYASHI return NULL;
2349*820c1a8dSHiroo HAYASHI }
2350*820c1a8dSHiroo HAYASHI break;
2351*820c1a8dSHiroo HAYASHI
2352*820c1a8dSHiroo HAYASHI case ANCHOR:
2353*820c1a8dSHiroo HAYASHI if ((token->opr.ctx_type
2354*820c1a8dSHiroo HAYASHI & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST))
2355*820c1a8dSHiroo HAYASHI && dfa->word_ops_used == 0)
2356*820c1a8dSHiroo HAYASHI init_word_char (dfa);
2357*820c1a8dSHiroo HAYASHI if (token->opr.ctx_type == WORD_DELIM
2358*820c1a8dSHiroo HAYASHI || token->opr.ctx_type == NOT_WORD_DELIM)
2359*820c1a8dSHiroo HAYASHI {
2360*820c1a8dSHiroo HAYASHI bin_tree_t *tree_first, *tree_last;
2361*820c1a8dSHiroo HAYASHI if (token->opr.ctx_type == WORD_DELIM)
2362*820c1a8dSHiroo HAYASHI {
2363*820c1a8dSHiroo HAYASHI token->opr.ctx_type = WORD_FIRST;
2364*820c1a8dSHiroo HAYASHI tree_first = create_token_tree (dfa, NULL, NULL, token);
2365*820c1a8dSHiroo HAYASHI token->opr.ctx_type = WORD_LAST;
2366*820c1a8dSHiroo HAYASHI }
2367*820c1a8dSHiroo HAYASHI else
2368*820c1a8dSHiroo HAYASHI {
2369*820c1a8dSHiroo HAYASHI token->opr.ctx_type = INSIDE_WORD;
2370*820c1a8dSHiroo HAYASHI tree_first = create_token_tree (dfa, NULL, NULL, token);
2371*820c1a8dSHiroo HAYASHI token->opr.ctx_type = INSIDE_NOTWORD;
2372*820c1a8dSHiroo HAYASHI }
2373*820c1a8dSHiroo HAYASHI tree_last = create_token_tree (dfa, NULL, NULL, token);
2374*820c1a8dSHiroo HAYASHI tree = create_tree (dfa, tree_first, tree_last, OP_ALT);
2375*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (tree_first == NULL || tree_last == NULL
2376*820c1a8dSHiroo HAYASHI || tree == NULL))
2377*820c1a8dSHiroo HAYASHI {
2378*820c1a8dSHiroo HAYASHI *err = REG_ESPACE;
2379*820c1a8dSHiroo HAYASHI return NULL;
2380*820c1a8dSHiroo HAYASHI }
2381*820c1a8dSHiroo HAYASHI }
2382*820c1a8dSHiroo HAYASHI else
2383*820c1a8dSHiroo HAYASHI {
2384*820c1a8dSHiroo HAYASHI tree = create_token_tree (dfa, NULL, NULL, token);
2385*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (tree == NULL))
2386*820c1a8dSHiroo HAYASHI {
2387*820c1a8dSHiroo HAYASHI *err = REG_ESPACE;
2388*820c1a8dSHiroo HAYASHI return NULL;
2389*820c1a8dSHiroo HAYASHI }
2390*820c1a8dSHiroo HAYASHI }
2391*820c1a8dSHiroo HAYASHI /* We must return here, since ANCHORs can't be followed
2392*820c1a8dSHiroo HAYASHI by repetition operators.
2393*820c1a8dSHiroo HAYASHI eg. RE"^*" is invalid or "<ANCHOR(^)><CHAR(*)>",
2394*820c1a8dSHiroo HAYASHI it must not be "<ANCHOR(^)><REPEAT(*)>". */
2395*820c1a8dSHiroo HAYASHI fetch_token (token, regexp, syntax);
2396*820c1a8dSHiroo HAYASHI return tree;
2397*820c1a8dSHiroo HAYASHI
2398*820c1a8dSHiroo HAYASHI case OP_PERIOD:
2399*820c1a8dSHiroo HAYASHI tree = create_token_tree (dfa, NULL, NULL, token);
2400*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (tree == NULL))
2401*820c1a8dSHiroo HAYASHI {
2402*820c1a8dSHiroo HAYASHI *err = REG_ESPACE;
2403*820c1a8dSHiroo HAYASHI return NULL;
2404*820c1a8dSHiroo HAYASHI }
2405*820c1a8dSHiroo HAYASHI if (dfa->mb_cur_max > 1)
2406*820c1a8dSHiroo HAYASHI dfa->has_mb_node = 1;
2407*820c1a8dSHiroo HAYASHI break;
2408*820c1a8dSHiroo HAYASHI
2409*820c1a8dSHiroo HAYASHI case OP_WORD:
2410*820c1a8dSHiroo HAYASHI case OP_NOTWORD:
2411*820c1a8dSHiroo HAYASHI tree = build_charclass_op (dfa, regexp->trans,
2412*820c1a8dSHiroo HAYASHI "alnum",
2413*820c1a8dSHiroo HAYASHI "_",
2414*820c1a8dSHiroo HAYASHI token->type == OP_NOTWORD, err);
2415*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL))
2416*820c1a8dSHiroo HAYASHI return NULL;
2417*820c1a8dSHiroo HAYASHI break;
2418*820c1a8dSHiroo HAYASHI
2419*820c1a8dSHiroo HAYASHI case OP_SPACE:
2420*820c1a8dSHiroo HAYASHI case OP_NOTSPACE:
2421*820c1a8dSHiroo HAYASHI tree = build_charclass_op (dfa, regexp->trans,
2422*820c1a8dSHiroo HAYASHI "space",
2423*820c1a8dSHiroo HAYASHI "",
2424*820c1a8dSHiroo HAYASHI token->type == OP_NOTSPACE, err);
2425*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*err != REG_NOERROR && tree == NULL))
2426*820c1a8dSHiroo HAYASHI return NULL;
2427*820c1a8dSHiroo HAYASHI break;
2428*820c1a8dSHiroo HAYASHI
2429*820c1a8dSHiroo HAYASHI case OP_ALT:
2430*820c1a8dSHiroo HAYASHI case END_OF_RE:
2431*820c1a8dSHiroo HAYASHI return NULL;
2432*820c1a8dSHiroo HAYASHI
2433*820c1a8dSHiroo HAYASHI case BACK_SLASH:
2434*820c1a8dSHiroo HAYASHI *err = REG_EESCAPE;
2435*820c1a8dSHiroo HAYASHI return NULL;
2436*820c1a8dSHiroo HAYASHI
2437*820c1a8dSHiroo HAYASHI default:
2438*820c1a8dSHiroo HAYASHI /* Must not happen? */
2439*820c1a8dSHiroo HAYASHI DEBUG_ASSERT (false);
2440*820c1a8dSHiroo HAYASHI return NULL;
2441*820c1a8dSHiroo HAYASHI }
2442*820c1a8dSHiroo HAYASHI fetch_token (token, regexp, syntax);
2443*820c1a8dSHiroo HAYASHI
2444*820c1a8dSHiroo HAYASHI while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS
2445*820c1a8dSHiroo HAYASHI || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM)
2446*820c1a8dSHiroo HAYASHI {
2447*820c1a8dSHiroo HAYASHI bin_tree_t *dup_tree = parse_dup_op (tree, regexp, dfa, token,
2448*820c1a8dSHiroo HAYASHI syntax, err);
2449*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*err != REG_NOERROR && dup_tree == NULL))
2450*820c1a8dSHiroo HAYASHI {
2451*820c1a8dSHiroo HAYASHI if (tree != NULL)
2452*820c1a8dSHiroo HAYASHI postorder (tree, free_tree, NULL);
2453*820c1a8dSHiroo HAYASHI return NULL;
2454*820c1a8dSHiroo HAYASHI }
2455*820c1a8dSHiroo HAYASHI tree = dup_tree;
2456*820c1a8dSHiroo HAYASHI /* In BRE consecutive duplications are not allowed. */
2457*820c1a8dSHiroo HAYASHI if ((syntax & RE_CONTEXT_INVALID_DUP)
2458*820c1a8dSHiroo HAYASHI && (token->type == OP_DUP_ASTERISK
2459*820c1a8dSHiroo HAYASHI || token->type == OP_OPEN_DUP_NUM))
2460*820c1a8dSHiroo HAYASHI {
2461*820c1a8dSHiroo HAYASHI if (tree != NULL)
2462*820c1a8dSHiroo HAYASHI postorder (tree, free_tree, NULL);
2463*820c1a8dSHiroo HAYASHI *err = REG_BADRPT;
2464*820c1a8dSHiroo HAYASHI return NULL;
2465*820c1a8dSHiroo HAYASHI }
2466*820c1a8dSHiroo HAYASHI }
2467*820c1a8dSHiroo HAYASHI
2468*820c1a8dSHiroo HAYASHI return tree;
2469*820c1a8dSHiroo HAYASHI }
2470*820c1a8dSHiroo HAYASHI
2471*820c1a8dSHiroo HAYASHI /* This function build the following tree, from regular expression
2472*820c1a8dSHiroo HAYASHI (<reg_exp>):
2473*820c1a8dSHiroo HAYASHI SUBEXP
2474*820c1a8dSHiroo HAYASHI |
2475*820c1a8dSHiroo HAYASHI <reg_exp>
2476*820c1a8dSHiroo HAYASHI */
2477*820c1a8dSHiroo HAYASHI
2478*820c1a8dSHiroo HAYASHI static bin_tree_t *
parse_sub_exp(re_string_t * regexp,regex_t * preg,re_token_t * token,reg_syntax_t syntax,Idx nest,reg_errcode_t * err)2479*820c1a8dSHiroo HAYASHI parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,
2480*820c1a8dSHiroo HAYASHI reg_syntax_t syntax, Idx nest, reg_errcode_t *err)
2481*820c1a8dSHiroo HAYASHI {
2482*820c1a8dSHiroo HAYASHI re_dfa_t *dfa = preg->buffer;
2483*820c1a8dSHiroo HAYASHI bin_tree_t *tree;
2484*820c1a8dSHiroo HAYASHI size_t cur_nsub;
2485*820c1a8dSHiroo HAYASHI cur_nsub = preg->re_nsub++;
2486*820c1a8dSHiroo HAYASHI
2487*820c1a8dSHiroo HAYASHI fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE);
2488*820c1a8dSHiroo HAYASHI
2489*820c1a8dSHiroo HAYASHI /* The subexpression may be a null string. */
2490*820c1a8dSHiroo HAYASHI if (token->type == OP_CLOSE_SUBEXP)
2491*820c1a8dSHiroo HAYASHI tree = NULL;
2492*820c1a8dSHiroo HAYASHI else
2493*820c1a8dSHiroo HAYASHI {
2494*820c1a8dSHiroo HAYASHI tree = parse_reg_exp (regexp, preg, token, syntax, nest, err);
2495*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*err == REG_NOERROR
2496*820c1a8dSHiroo HAYASHI && token->type != OP_CLOSE_SUBEXP))
2497*820c1a8dSHiroo HAYASHI {
2498*820c1a8dSHiroo HAYASHI if (tree != NULL)
2499*820c1a8dSHiroo HAYASHI postorder (tree, free_tree, NULL);
2500*820c1a8dSHiroo HAYASHI *err = REG_EPAREN;
2501*820c1a8dSHiroo HAYASHI }
2502*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*err != REG_NOERROR))
2503*820c1a8dSHiroo HAYASHI return NULL;
2504*820c1a8dSHiroo HAYASHI }
2505*820c1a8dSHiroo HAYASHI
2506*820c1a8dSHiroo HAYASHI if (cur_nsub <= '9' - '1')
2507*820c1a8dSHiroo HAYASHI dfa->completed_bkref_map |= 1 << cur_nsub;
2508*820c1a8dSHiroo HAYASHI
2509*820c1a8dSHiroo HAYASHI tree = create_tree (dfa, tree, NULL, SUBEXP);
2510*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (tree == NULL))
2511*820c1a8dSHiroo HAYASHI {
2512*820c1a8dSHiroo HAYASHI *err = REG_ESPACE;
2513*820c1a8dSHiroo HAYASHI return NULL;
2514*820c1a8dSHiroo HAYASHI }
2515*820c1a8dSHiroo HAYASHI tree->token.opr.idx = cur_nsub;
2516*820c1a8dSHiroo HAYASHI return tree;
2517*820c1a8dSHiroo HAYASHI }
2518*820c1a8dSHiroo HAYASHI
2519*820c1a8dSHiroo HAYASHI /* This function parse repetition operators like "*", "+", "{1,3}" etc. */
2520*820c1a8dSHiroo HAYASHI
2521*820c1a8dSHiroo HAYASHI static bin_tree_t *
parse_dup_op(bin_tree_t * elem,re_string_t * regexp,re_dfa_t * dfa,re_token_t * token,reg_syntax_t syntax,reg_errcode_t * err)2522*820c1a8dSHiroo HAYASHI parse_dup_op (bin_tree_t *elem, re_string_t *regexp, re_dfa_t *dfa,
2523*820c1a8dSHiroo HAYASHI re_token_t *token, reg_syntax_t syntax, reg_errcode_t *err)
2524*820c1a8dSHiroo HAYASHI {
2525*820c1a8dSHiroo HAYASHI bin_tree_t *tree = NULL, *old_tree = NULL;
2526*820c1a8dSHiroo HAYASHI Idx i, start, end, start_idx = re_string_cur_idx (regexp);
2527*820c1a8dSHiroo HAYASHI re_token_t start_token = *token;
2528*820c1a8dSHiroo HAYASHI
2529*820c1a8dSHiroo HAYASHI if (token->type == OP_OPEN_DUP_NUM)
2530*820c1a8dSHiroo HAYASHI {
2531*820c1a8dSHiroo HAYASHI end = 0;
2532*820c1a8dSHiroo HAYASHI start = fetch_number (regexp, token, syntax);
2533*820c1a8dSHiroo HAYASHI if (start == -1)
2534*820c1a8dSHiroo HAYASHI {
2535*820c1a8dSHiroo HAYASHI if (token->type == CHARACTER && token->opr.c == ',')
2536*820c1a8dSHiroo HAYASHI start = 0; /* We treat "{,m}" as "{0,m}". */
2537*820c1a8dSHiroo HAYASHI else
2538*820c1a8dSHiroo HAYASHI {
2539*820c1a8dSHiroo HAYASHI *err = REG_BADBR; /* <re>{} is invalid. */
2540*820c1a8dSHiroo HAYASHI return NULL;
2541*820c1a8dSHiroo HAYASHI }
2542*820c1a8dSHiroo HAYASHI }
2543*820c1a8dSHiroo HAYASHI if (__glibc_likely (start != -2))
2544*820c1a8dSHiroo HAYASHI {
2545*820c1a8dSHiroo HAYASHI /* We treat "{n}" as "{n,n}". */
2546*820c1a8dSHiroo HAYASHI end = ((token->type == OP_CLOSE_DUP_NUM) ? start
2547*820c1a8dSHiroo HAYASHI : ((token->type == CHARACTER && token->opr.c == ',')
2548*820c1a8dSHiroo HAYASHI ? fetch_number (regexp, token, syntax) : -2));
2549*820c1a8dSHiroo HAYASHI }
2550*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (start == -2 || end == -2))
2551*820c1a8dSHiroo HAYASHI {
2552*820c1a8dSHiroo HAYASHI /* Invalid sequence. */
2553*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (!(syntax & RE_INVALID_INTERVAL_ORD)))
2554*820c1a8dSHiroo HAYASHI {
2555*820c1a8dSHiroo HAYASHI if (token->type == END_OF_RE)
2556*820c1a8dSHiroo HAYASHI *err = REG_EBRACE;
2557*820c1a8dSHiroo HAYASHI else
2558*820c1a8dSHiroo HAYASHI *err = REG_BADBR;
2559*820c1a8dSHiroo HAYASHI
2560*820c1a8dSHiroo HAYASHI return NULL;
2561*820c1a8dSHiroo HAYASHI }
2562*820c1a8dSHiroo HAYASHI
2563*820c1a8dSHiroo HAYASHI /* If the syntax bit is set, rollback. */
2564*820c1a8dSHiroo HAYASHI re_string_set_index (regexp, start_idx);
2565*820c1a8dSHiroo HAYASHI *token = start_token;
2566*820c1a8dSHiroo HAYASHI token->type = CHARACTER;
2567*820c1a8dSHiroo HAYASHI /* mb_partial and word_char bits should be already initialized by
2568*820c1a8dSHiroo HAYASHI peek_token. */
2569*820c1a8dSHiroo HAYASHI return elem;
2570*820c1a8dSHiroo HAYASHI }
2571*820c1a8dSHiroo HAYASHI
2572*820c1a8dSHiroo HAYASHI if (__glibc_unlikely ((end != -1 && start > end)
2573*820c1a8dSHiroo HAYASHI || token->type != OP_CLOSE_DUP_NUM))
2574*820c1a8dSHiroo HAYASHI {
2575*820c1a8dSHiroo HAYASHI /* First number greater than second. */
2576*820c1a8dSHiroo HAYASHI *err = REG_BADBR;
2577*820c1a8dSHiroo HAYASHI return NULL;
2578*820c1a8dSHiroo HAYASHI }
2579*820c1a8dSHiroo HAYASHI
2580*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (RE_DUP_MAX < (end == -1 ? start : end)))
2581*820c1a8dSHiroo HAYASHI {
2582*820c1a8dSHiroo HAYASHI *err = REG_ESIZE;
2583*820c1a8dSHiroo HAYASHI return NULL;
2584*820c1a8dSHiroo HAYASHI }
2585*820c1a8dSHiroo HAYASHI }
2586*820c1a8dSHiroo HAYASHI else
2587*820c1a8dSHiroo HAYASHI {
2588*820c1a8dSHiroo HAYASHI start = (token->type == OP_DUP_PLUS) ? 1 : 0;
2589*820c1a8dSHiroo HAYASHI end = (token->type == OP_DUP_QUESTION) ? 1 : -1;
2590*820c1a8dSHiroo HAYASHI }
2591*820c1a8dSHiroo HAYASHI
2592*820c1a8dSHiroo HAYASHI fetch_token (token, regexp, syntax);
2593*820c1a8dSHiroo HAYASHI
2594*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (elem == NULL))
2595*820c1a8dSHiroo HAYASHI return NULL;
2596*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (start == 0 && end == 0))
2597*820c1a8dSHiroo HAYASHI {
2598*820c1a8dSHiroo HAYASHI postorder (elem, free_tree, NULL);
2599*820c1a8dSHiroo HAYASHI return NULL;
2600*820c1a8dSHiroo HAYASHI }
2601*820c1a8dSHiroo HAYASHI
2602*820c1a8dSHiroo HAYASHI /* Extract "<re>{n,m}" to "<re><re>...<re><re>{0,<m-n>}". */
2603*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (start > 0))
2604*820c1a8dSHiroo HAYASHI {
2605*820c1a8dSHiroo HAYASHI tree = elem;
2606*820c1a8dSHiroo HAYASHI for (i = 2; i <= start; ++i)
2607*820c1a8dSHiroo HAYASHI {
2608*820c1a8dSHiroo HAYASHI elem = duplicate_tree (elem, dfa);
2609*820c1a8dSHiroo HAYASHI tree = create_tree (dfa, tree, elem, CONCAT);
2610*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (elem == NULL || tree == NULL))
2611*820c1a8dSHiroo HAYASHI goto parse_dup_op_espace;
2612*820c1a8dSHiroo HAYASHI }
2613*820c1a8dSHiroo HAYASHI
2614*820c1a8dSHiroo HAYASHI if (start == end)
2615*820c1a8dSHiroo HAYASHI return tree;
2616*820c1a8dSHiroo HAYASHI
2617*820c1a8dSHiroo HAYASHI /* Duplicate ELEM before it is marked optional. */
2618*820c1a8dSHiroo HAYASHI elem = duplicate_tree (elem, dfa);
2619*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (elem == NULL))
2620*820c1a8dSHiroo HAYASHI goto parse_dup_op_espace;
2621*820c1a8dSHiroo HAYASHI old_tree = tree;
2622*820c1a8dSHiroo HAYASHI }
2623*820c1a8dSHiroo HAYASHI else
2624*820c1a8dSHiroo HAYASHI old_tree = NULL;
2625*820c1a8dSHiroo HAYASHI
2626*820c1a8dSHiroo HAYASHI if (elem->token.type == SUBEXP)
2627*820c1a8dSHiroo HAYASHI {
2628*820c1a8dSHiroo HAYASHI uintptr_t subidx = elem->token.opr.idx;
2629*820c1a8dSHiroo HAYASHI postorder (elem, mark_opt_subexp, (void *) subidx);
2630*820c1a8dSHiroo HAYASHI }
2631*820c1a8dSHiroo HAYASHI
2632*820c1a8dSHiroo HAYASHI tree = create_tree (dfa, elem, NULL,
2633*820c1a8dSHiroo HAYASHI (end == -1 ? OP_DUP_ASTERISK : OP_ALT));
2634*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (tree == NULL))
2635*820c1a8dSHiroo HAYASHI goto parse_dup_op_espace;
2636*820c1a8dSHiroo HAYASHI
2637*820c1a8dSHiroo HAYASHI /* This loop is actually executed only when end != -1,
2638*820c1a8dSHiroo HAYASHI to rewrite <re>{0,n} as (<re>(<re>...<re>?)?)?... We have
2639*820c1a8dSHiroo HAYASHI already created the start+1-th copy. */
2640*820c1a8dSHiroo HAYASHI if (TYPE_SIGNED (Idx) || end != -1)
2641*820c1a8dSHiroo HAYASHI for (i = start + 2; i <= end; ++i)
2642*820c1a8dSHiroo HAYASHI {
2643*820c1a8dSHiroo HAYASHI elem = duplicate_tree (elem, dfa);
2644*820c1a8dSHiroo HAYASHI tree = create_tree (dfa, tree, elem, CONCAT);
2645*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (elem == NULL || tree == NULL))
2646*820c1a8dSHiroo HAYASHI goto parse_dup_op_espace;
2647*820c1a8dSHiroo HAYASHI
2648*820c1a8dSHiroo HAYASHI tree = create_tree (dfa, tree, NULL, OP_ALT);
2649*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (tree == NULL))
2650*820c1a8dSHiroo HAYASHI goto parse_dup_op_espace;
2651*820c1a8dSHiroo HAYASHI }
2652*820c1a8dSHiroo HAYASHI
2653*820c1a8dSHiroo HAYASHI if (old_tree)
2654*820c1a8dSHiroo HAYASHI tree = create_tree (dfa, old_tree, tree, CONCAT);
2655*820c1a8dSHiroo HAYASHI
2656*820c1a8dSHiroo HAYASHI return tree;
2657*820c1a8dSHiroo HAYASHI
2658*820c1a8dSHiroo HAYASHI parse_dup_op_espace:
2659*820c1a8dSHiroo HAYASHI *err = REG_ESPACE;
2660*820c1a8dSHiroo HAYASHI return NULL;
2661*820c1a8dSHiroo HAYASHI }
2662*820c1a8dSHiroo HAYASHI
2663*820c1a8dSHiroo HAYASHI /* Size of the names for collating symbol/equivalence_class/character_class.
2664*820c1a8dSHiroo HAYASHI I'm not sure, but maybe enough. */
2665*820c1a8dSHiroo HAYASHI #define BRACKET_NAME_BUF_SIZE 32
2666*820c1a8dSHiroo HAYASHI
2667*820c1a8dSHiroo HAYASHI #ifndef _LIBC
2668*820c1a8dSHiroo HAYASHI
2669*820c1a8dSHiroo HAYASHI # ifdef RE_ENABLE_I18N
2670*820c1a8dSHiroo HAYASHI /* Convert the byte B to the corresponding wide character. In a
2671*820c1a8dSHiroo HAYASHI unibyte locale, treat B as itself. In a multibyte locale, return
2672*820c1a8dSHiroo HAYASHI WEOF if B is an encoding error. */
2673*820c1a8dSHiroo HAYASHI static wint_t
parse_byte(unsigned char b,re_charset_t * mbcset)2674*820c1a8dSHiroo HAYASHI parse_byte (unsigned char b, re_charset_t *mbcset)
2675*820c1a8dSHiroo HAYASHI {
2676*820c1a8dSHiroo HAYASHI return mbcset == NULL ? b : __btowc (b);
2677*820c1a8dSHiroo HAYASHI }
2678*820c1a8dSHiroo HAYASHI # endif
2679*820c1a8dSHiroo HAYASHI
2680*820c1a8dSHiroo HAYASHI /* Local function for parse_bracket_exp only used in case of NOT _LIBC.
2681*820c1a8dSHiroo HAYASHI Build the range expression which starts from START_ELEM, and ends
2682*820c1a8dSHiroo HAYASHI at END_ELEM. The result are written to MBCSET and SBCSET.
2683*820c1a8dSHiroo HAYASHI RANGE_ALLOC is the allocated size of mbcset->range_starts, and
2684*820c1a8dSHiroo HAYASHI mbcset->range_ends, is a pointer argument since we may
2685*820c1a8dSHiroo HAYASHI update it. */
2686*820c1a8dSHiroo HAYASHI
2687*820c1a8dSHiroo HAYASHI static reg_errcode_t
2688*820c1a8dSHiroo HAYASHI # 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)2689*820c1a8dSHiroo HAYASHI build_range_exp (const reg_syntax_t syntax,
2690*820c1a8dSHiroo HAYASHI bitset_t sbcset,
2691*820c1a8dSHiroo HAYASHI re_charset_t *mbcset,
2692*820c1a8dSHiroo HAYASHI Idx *range_alloc,
2693*820c1a8dSHiroo HAYASHI const bracket_elem_t *start_elem,
2694*820c1a8dSHiroo HAYASHI const bracket_elem_t *end_elem)
2695*820c1a8dSHiroo HAYASHI # else /* not RE_ENABLE_I18N */
2696*820c1a8dSHiroo HAYASHI build_range_exp (const reg_syntax_t syntax,
2697*820c1a8dSHiroo HAYASHI bitset_t sbcset,
2698*820c1a8dSHiroo HAYASHI const bracket_elem_t *start_elem,
2699*820c1a8dSHiroo HAYASHI const bracket_elem_t *end_elem)
2700*820c1a8dSHiroo HAYASHI # endif /* not RE_ENABLE_I18N */
2701*820c1a8dSHiroo HAYASHI {
2702*820c1a8dSHiroo HAYASHI unsigned int start_ch, end_ch;
2703*820c1a8dSHiroo HAYASHI /* Equivalence Classes and Character Classes can't be a range start/end. */
2704*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (start_elem->type == EQUIV_CLASS
2705*820c1a8dSHiroo HAYASHI || start_elem->type == CHAR_CLASS
2706*820c1a8dSHiroo HAYASHI || end_elem->type == EQUIV_CLASS
2707*820c1a8dSHiroo HAYASHI || end_elem->type == CHAR_CLASS))
2708*820c1a8dSHiroo HAYASHI return REG_ERANGE;
2709*820c1a8dSHiroo HAYASHI
2710*820c1a8dSHiroo HAYASHI /* We can handle no multi character collating elements without libc
2711*820c1a8dSHiroo HAYASHI support. */
2712*820c1a8dSHiroo HAYASHI if (__glibc_unlikely ((start_elem->type == COLL_SYM
2713*820c1a8dSHiroo HAYASHI && strlen ((char *) start_elem->opr.name) > 1)
2714*820c1a8dSHiroo HAYASHI || (end_elem->type == COLL_SYM
2715*820c1a8dSHiroo HAYASHI && strlen ((char *) end_elem->opr.name) > 1)))
2716*820c1a8dSHiroo HAYASHI return REG_ECOLLATE;
2717*820c1a8dSHiroo HAYASHI
2718*820c1a8dSHiroo HAYASHI # ifdef RE_ENABLE_I18N
2719*820c1a8dSHiroo HAYASHI {
2720*820c1a8dSHiroo HAYASHI wchar_t wc;
2721*820c1a8dSHiroo HAYASHI wint_t start_wc;
2722*820c1a8dSHiroo HAYASHI wint_t end_wc;
2723*820c1a8dSHiroo HAYASHI
2724*820c1a8dSHiroo HAYASHI start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch
2725*820c1a8dSHiroo HAYASHI : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
2726*820c1a8dSHiroo HAYASHI : 0));
2727*820c1a8dSHiroo HAYASHI end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch
2728*820c1a8dSHiroo HAYASHI : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
2729*820c1a8dSHiroo HAYASHI : 0));
2730*820c1a8dSHiroo HAYASHI start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM)
2731*820c1a8dSHiroo HAYASHI ? parse_byte (start_ch, mbcset) : start_elem->opr.wch);
2732*820c1a8dSHiroo HAYASHI end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM)
2733*820c1a8dSHiroo HAYASHI ? parse_byte (end_ch, mbcset) : end_elem->opr.wch);
2734*820c1a8dSHiroo HAYASHI if (start_wc == WEOF || end_wc == WEOF)
2735*820c1a8dSHiroo HAYASHI return REG_ECOLLATE;
2736*820c1a8dSHiroo HAYASHI else if (__glibc_unlikely ((syntax & RE_NO_EMPTY_RANGES)
2737*820c1a8dSHiroo HAYASHI && start_wc > end_wc))
2738*820c1a8dSHiroo HAYASHI return REG_ERANGE;
2739*820c1a8dSHiroo HAYASHI
2740*820c1a8dSHiroo HAYASHI /* Got valid collation sequence values, add them as a new entry.
2741*820c1a8dSHiroo HAYASHI However, for !_LIBC we have no collation elements: if the
2742*820c1a8dSHiroo HAYASHI character set is single byte, the single byte character set
2743*820c1a8dSHiroo HAYASHI that we build below suffices. parse_bracket_exp passes
2744*820c1a8dSHiroo HAYASHI no MBCSET if dfa->mb_cur_max == 1. */
2745*820c1a8dSHiroo HAYASHI if (mbcset)
2746*820c1a8dSHiroo HAYASHI {
2747*820c1a8dSHiroo HAYASHI /* Check the space of the arrays. */
2748*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*range_alloc == mbcset->nranges))
2749*820c1a8dSHiroo HAYASHI {
2750*820c1a8dSHiroo HAYASHI /* There is not enough space, need realloc. */
2751*820c1a8dSHiroo HAYASHI wchar_t *new_array_start, *new_array_end;
2752*820c1a8dSHiroo HAYASHI Idx new_nranges;
2753*820c1a8dSHiroo HAYASHI
2754*820c1a8dSHiroo HAYASHI /* +1 in case of mbcset->nranges is 0. */
2755*820c1a8dSHiroo HAYASHI new_nranges = 2 * mbcset->nranges + 1;
2756*820c1a8dSHiroo HAYASHI /* Use realloc since mbcset->range_starts and mbcset->range_ends
2757*820c1a8dSHiroo HAYASHI are NULL if *range_alloc == 0. */
2758*820c1a8dSHiroo HAYASHI new_array_start = re_realloc (mbcset->range_starts, wchar_t,
2759*820c1a8dSHiroo HAYASHI new_nranges);
2760*820c1a8dSHiroo HAYASHI new_array_end = re_realloc (mbcset->range_ends, wchar_t,
2761*820c1a8dSHiroo HAYASHI new_nranges);
2762*820c1a8dSHiroo HAYASHI
2763*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (new_array_start == NULL
2764*820c1a8dSHiroo HAYASHI || new_array_end == NULL))
2765*820c1a8dSHiroo HAYASHI {
2766*820c1a8dSHiroo HAYASHI re_free (new_array_start);
2767*820c1a8dSHiroo HAYASHI re_free (new_array_end);
2768*820c1a8dSHiroo HAYASHI return REG_ESPACE;
2769*820c1a8dSHiroo HAYASHI }
2770*820c1a8dSHiroo HAYASHI
2771*820c1a8dSHiroo HAYASHI mbcset->range_starts = new_array_start;
2772*820c1a8dSHiroo HAYASHI mbcset->range_ends = new_array_end;
2773*820c1a8dSHiroo HAYASHI *range_alloc = new_nranges;
2774*820c1a8dSHiroo HAYASHI }
2775*820c1a8dSHiroo HAYASHI
2776*820c1a8dSHiroo HAYASHI mbcset->range_starts[mbcset->nranges] = start_wc;
2777*820c1a8dSHiroo HAYASHI mbcset->range_ends[mbcset->nranges++] = end_wc;
2778*820c1a8dSHiroo HAYASHI }
2779*820c1a8dSHiroo HAYASHI
2780*820c1a8dSHiroo HAYASHI /* Build the table for single byte characters. */
2781*820c1a8dSHiroo HAYASHI for (wc = 0; wc < SBC_MAX; ++wc)
2782*820c1a8dSHiroo HAYASHI {
2783*820c1a8dSHiroo HAYASHI if (start_wc <= wc && wc <= end_wc)
2784*820c1a8dSHiroo HAYASHI bitset_set (sbcset, wc);
2785*820c1a8dSHiroo HAYASHI }
2786*820c1a8dSHiroo HAYASHI }
2787*820c1a8dSHiroo HAYASHI # else /* not RE_ENABLE_I18N */
2788*820c1a8dSHiroo HAYASHI {
2789*820c1a8dSHiroo HAYASHI unsigned int ch;
2790*820c1a8dSHiroo HAYASHI start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch
2791*820c1a8dSHiroo HAYASHI : ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]
2792*820c1a8dSHiroo HAYASHI : 0));
2793*820c1a8dSHiroo HAYASHI end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch
2794*820c1a8dSHiroo HAYASHI : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]
2795*820c1a8dSHiroo HAYASHI : 0));
2796*820c1a8dSHiroo HAYASHI if (start_ch > end_ch)
2797*820c1a8dSHiroo HAYASHI return REG_ERANGE;
2798*820c1a8dSHiroo HAYASHI /* Build the table for single byte characters. */
2799*820c1a8dSHiroo HAYASHI for (ch = 0; ch < SBC_MAX; ++ch)
2800*820c1a8dSHiroo HAYASHI if (start_ch <= ch && ch <= end_ch)
2801*820c1a8dSHiroo HAYASHI bitset_set (sbcset, ch);
2802*820c1a8dSHiroo HAYASHI }
2803*820c1a8dSHiroo HAYASHI # endif /* not RE_ENABLE_I18N */
2804*820c1a8dSHiroo HAYASHI return REG_NOERROR;
2805*820c1a8dSHiroo HAYASHI }
2806*820c1a8dSHiroo HAYASHI #endif /* not _LIBC */
2807*820c1a8dSHiroo HAYASHI
2808*820c1a8dSHiroo HAYASHI #ifndef _LIBC
2809*820c1a8dSHiroo HAYASHI /* Helper function for parse_bracket_exp only used in case of NOT _LIBC..
2810*820c1a8dSHiroo HAYASHI Build the collating element which is represented by NAME.
2811*820c1a8dSHiroo HAYASHI The result are written to MBCSET and SBCSET.
2812*820c1a8dSHiroo HAYASHI COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
2813*820c1a8dSHiroo HAYASHI pointer argument since we may update it. */
2814*820c1a8dSHiroo HAYASHI
2815*820c1a8dSHiroo HAYASHI static reg_errcode_t
2816*820c1a8dSHiroo HAYASHI # ifdef RE_ENABLE_I18N
build_collating_symbol(bitset_t sbcset,re_charset_t * mbcset,Idx * coll_sym_alloc,const unsigned char * name)2817*820c1a8dSHiroo HAYASHI build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset,
2818*820c1a8dSHiroo HAYASHI Idx *coll_sym_alloc, const unsigned char *name)
2819*820c1a8dSHiroo HAYASHI # else /* not RE_ENABLE_I18N */
2820*820c1a8dSHiroo HAYASHI build_collating_symbol (bitset_t sbcset, const unsigned char *name)
2821*820c1a8dSHiroo HAYASHI # endif /* not RE_ENABLE_I18N */
2822*820c1a8dSHiroo HAYASHI {
2823*820c1a8dSHiroo HAYASHI size_t name_len = strlen ((const char *) name);
2824*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (name_len != 1))
2825*820c1a8dSHiroo HAYASHI return REG_ECOLLATE;
2826*820c1a8dSHiroo HAYASHI else
2827*820c1a8dSHiroo HAYASHI {
2828*820c1a8dSHiroo HAYASHI bitset_set (sbcset, name[0]);
2829*820c1a8dSHiroo HAYASHI return REG_NOERROR;
2830*820c1a8dSHiroo HAYASHI }
2831*820c1a8dSHiroo HAYASHI }
2832*820c1a8dSHiroo HAYASHI #endif /* not _LIBC */
2833*820c1a8dSHiroo HAYASHI
2834*820c1a8dSHiroo HAYASHI /* This function parse bracket expression like "[abc]", "[a-c]",
2835*820c1a8dSHiroo HAYASHI "[[.a-a.]]" etc. */
2836*820c1a8dSHiroo HAYASHI
2837*820c1a8dSHiroo HAYASHI static bin_tree_t *
parse_bracket_exp(re_string_t * regexp,re_dfa_t * dfa,re_token_t * token,reg_syntax_t syntax,reg_errcode_t * err)2838*820c1a8dSHiroo HAYASHI parse_bracket_exp (re_string_t *regexp, re_dfa_t *dfa, re_token_t *token,
2839*820c1a8dSHiroo HAYASHI reg_syntax_t syntax, reg_errcode_t *err)
2840*820c1a8dSHiroo HAYASHI {
2841*820c1a8dSHiroo HAYASHI #ifdef _LIBC
2842*820c1a8dSHiroo HAYASHI const unsigned char *collseqmb;
2843*820c1a8dSHiroo HAYASHI const char *collseqwc;
2844*820c1a8dSHiroo HAYASHI uint32_t nrules;
2845*820c1a8dSHiroo HAYASHI int32_t table_size;
2846*820c1a8dSHiroo HAYASHI const int32_t *symb_table;
2847*820c1a8dSHiroo HAYASHI const unsigned char *extra;
2848*820c1a8dSHiroo HAYASHI
2849*820c1a8dSHiroo HAYASHI /* Local function for parse_bracket_exp used in _LIBC environment.
2850*820c1a8dSHiroo HAYASHI Seek the collating symbol entry corresponding to NAME.
2851*820c1a8dSHiroo HAYASHI Return the index of the symbol in the SYMB_TABLE,
2852*820c1a8dSHiroo HAYASHI or -1 if not found. */
2853*820c1a8dSHiroo HAYASHI
2854*820c1a8dSHiroo HAYASHI auto inline int32_t
2855*820c1a8dSHiroo HAYASHI __attribute__ ((always_inline))
2856*820c1a8dSHiroo HAYASHI seek_collating_symbol_entry (const unsigned char *name, size_t name_len)
2857*820c1a8dSHiroo HAYASHI {
2858*820c1a8dSHiroo HAYASHI int32_t elem;
2859*820c1a8dSHiroo HAYASHI
2860*820c1a8dSHiroo HAYASHI for (elem = 0; elem < table_size; elem++)
2861*820c1a8dSHiroo HAYASHI if (symb_table[2 * elem] != 0)
2862*820c1a8dSHiroo HAYASHI {
2863*820c1a8dSHiroo HAYASHI int32_t idx = symb_table[2 * elem + 1];
2864*820c1a8dSHiroo HAYASHI /* Skip the name of collating element name. */
2865*820c1a8dSHiroo HAYASHI idx += 1 + extra[idx];
2866*820c1a8dSHiroo HAYASHI if (/* Compare the length of the name. */
2867*820c1a8dSHiroo HAYASHI name_len == extra[idx]
2868*820c1a8dSHiroo HAYASHI /* Compare the name. */
2869*820c1a8dSHiroo HAYASHI && memcmp (name, &extra[idx + 1], name_len) == 0)
2870*820c1a8dSHiroo HAYASHI /* Yep, this is the entry. */
2871*820c1a8dSHiroo HAYASHI return elem;
2872*820c1a8dSHiroo HAYASHI }
2873*820c1a8dSHiroo HAYASHI return -1;
2874*820c1a8dSHiroo HAYASHI }
2875*820c1a8dSHiroo HAYASHI
2876*820c1a8dSHiroo HAYASHI /* Local function for parse_bracket_exp used in _LIBC environment.
2877*820c1a8dSHiroo HAYASHI Look up the collation sequence value of BR_ELEM.
2878*820c1a8dSHiroo HAYASHI Return the value if succeeded, UINT_MAX otherwise. */
2879*820c1a8dSHiroo HAYASHI
2880*820c1a8dSHiroo HAYASHI auto inline unsigned int
2881*820c1a8dSHiroo HAYASHI __attribute__ ((always_inline))
2882*820c1a8dSHiroo HAYASHI lookup_collation_sequence_value (bracket_elem_t *br_elem)
2883*820c1a8dSHiroo HAYASHI {
2884*820c1a8dSHiroo HAYASHI if (br_elem->type == SB_CHAR)
2885*820c1a8dSHiroo HAYASHI {
2886*820c1a8dSHiroo HAYASHI /*
2887*820c1a8dSHiroo HAYASHI if (MB_CUR_MAX == 1)
2888*820c1a8dSHiroo HAYASHI */
2889*820c1a8dSHiroo HAYASHI if (nrules == 0)
2890*820c1a8dSHiroo HAYASHI return collseqmb[br_elem->opr.ch];
2891*820c1a8dSHiroo HAYASHI else
2892*820c1a8dSHiroo HAYASHI {
2893*820c1a8dSHiroo HAYASHI wint_t wc = __btowc (br_elem->opr.ch);
2894*820c1a8dSHiroo HAYASHI return __collseq_table_lookup (collseqwc, wc);
2895*820c1a8dSHiroo HAYASHI }
2896*820c1a8dSHiroo HAYASHI }
2897*820c1a8dSHiroo HAYASHI else if (br_elem->type == MB_CHAR)
2898*820c1a8dSHiroo HAYASHI {
2899*820c1a8dSHiroo HAYASHI if (nrules != 0)
2900*820c1a8dSHiroo HAYASHI return __collseq_table_lookup (collseqwc, br_elem->opr.wch);
2901*820c1a8dSHiroo HAYASHI }
2902*820c1a8dSHiroo HAYASHI else if (br_elem->type == COLL_SYM)
2903*820c1a8dSHiroo HAYASHI {
2904*820c1a8dSHiroo HAYASHI size_t sym_name_len = strlen ((char *) br_elem->opr.name);
2905*820c1a8dSHiroo HAYASHI if (nrules != 0)
2906*820c1a8dSHiroo HAYASHI {
2907*820c1a8dSHiroo HAYASHI int32_t elem, idx;
2908*820c1a8dSHiroo HAYASHI elem = seek_collating_symbol_entry (br_elem->opr.name,
2909*820c1a8dSHiroo HAYASHI sym_name_len);
2910*820c1a8dSHiroo HAYASHI if (elem != -1)
2911*820c1a8dSHiroo HAYASHI {
2912*820c1a8dSHiroo HAYASHI /* We found the entry. */
2913*820c1a8dSHiroo HAYASHI idx = symb_table[2 * elem + 1];
2914*820c1a8dSHiroo HAYASHI /* Skip the name of collating element name. */
2915*820c1a8dSHiroo HAYASHI idx += 1 + extra[idx];
2916*820c1a8dSHiroo HAYASHI /* Skip the byte sequence of the collating element. */
2917*820c1a8dSHiroo HAYASHI idx += 1 + extra[idx];
2918*820c1a8dSHiroo HAYASHI /* Adjust for the alignment. */
2919*820c1a8dSHiroo HAYASHI idx = (idx + 3) & ~3;
2920*820c1a8dSHiroo HAYASHI /* Skip the multibyte collation sequence value. */
2921*820c1a8dSHiroo HAYASHI idx += sizeof (unsigned int);
2922*820c1a8dSHiroo HAYASHI /* Skip the wide char sequence of the collating element. */
2923*820c1a8dSHiroo HAYASHI idx += sizeof (unsigned int) *
2924*820c1a8dSHiroo HAYASHI (1 + *(unsigned int *) (extra + idx));
2925*820c1a8dSHiroo HAYASHI /* Return the collation sequence value. */
2926*820c1a8dSHiroo HAYASHI return *(unsigned int *) (extra + idx);
2927*820c1a8dSHiroo HAYASHI }
2928*820c1a8dSHiroo HAYASHI else if (sym_name_len == 1)
2929*820c1a8dSHiroo HAYASHI {
2930*820c1a8dSHiroo HAYASHI /* No valid character. Match it as a single byte
2931*820c1a8dSHiroo HAYASHI character. */
2932*820c1a8dSHiroo HAYASHI return collseqmb[br_elem->opr.name[0]];
2933*820c1a8dSHiroo HAYASHI }
2934*820c1a8dSHiroo HAYASHI }
2935*820c1a8dSHiroo HAYASHI else if (sym_name_len == 1)
2936*820c1a8dSHiroo HAYASHI return collseqmb[br_elem->opr.name[0]];
2937*820c1a8dSHiroo HAYASHI }
2938*820c1a8dSHiroo HAYASHI return UINT_MAX;
2939*820c1a8dSHiroo HAYASHI }
2940*820c1a8dSHiroo HAYASHI
2941*820c1a8dSHiroo HAYASHI /* Local function for parse_bracket_exp used in _LIBC environment.
2942*820c1a8dSHiroo HAYASHI Build the range expression which starts from START_ELEM, and ends
2943*820c1a8dSHiroo HAYASHI at END_ELEM. The result are written to MBCSET and SBCSET.
2944*820c1a8dSHiroo HAYASHI RANGE_ALLOC is the allocated size of mbcset->range_starts, and
2945*820c1a8dSHiroo HAYASHI mbcset->range_ends, is a pointer argument since we may
2946*820c1a8dSHiroo HAYASHI update it. */
2947*820c1a8dSHiroo HAYASHI
2948*820c1a8dSHiroo HAYASHI auto inline reg_errcode_t
2949*820c1a8dSHiroo HAYASHI __attribute__ ((always_inline))
2950*820c1a8dSHiroo HAYASHI build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc,
2951*820c1a8dSHiroo HAYASHI bracket_elem_t *start_elem, bracket_elem_t *end_elem)
2952*820c1a8dSHiroo HAYASHI {
2953*820c1a8dSHiroo HAYASHI unsigned int ch;
2954*820c1a8dSHiroo HAYASHI uint32_t start_collseq;
2955*820c1a8dSHiroo HAYASHI uint32_t end_collseq;
2956*820c1a8dSHiroo HAYASHI
2957*820c1a8dSHiroo HAYASHI /* Equivalence Classes and Character Classes can't be a range
2958*820c1a8dSHiroo HAYASHI start/end. */
2959*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (start_elem->type == EQUIV_CLASS
2960*820c1a8dSHiroo HAYASHI || start_elem->type == CHAR_CLASS
2961*820c1a8dSHiroo HAYASHI || end_elem->type == EQUIV_CLASS
2962*820c1a8dSHiroo HAYASHI || end_elem->type == CHAR_CLASS))
2963*820c1a8dSHiroo HAYASHI return REG_ERANGE;
2964*820c1a8dSHiroo HAYASHI
2965*820c1a8dSHiroo HAYASHI /* FIXME: Implement rational ranges here, too. */
2966*820c1a8dSHiroo HAYASHI start_collseq = lookup_collation_sequence_value (start_elem);
2967*820c1a8dSHiroo HAYASHI end_collseq = lookup_collation_sequence_value (end_elem);
2968*820c1a8dSHiroo HAYASHI /* Check start/end collation sequence values. */
2969*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (start_collseq == UINT_MAX
2970*820c1a8dSHiroo HAYASHI || end_collseq == UINT_MAX))
2971*820c1a8dSHiroo HAYASHI return REG_ECOLLATE;
2972*820c1a8dSHiroo HAYASHI if (__glibc_unlikely ((syntax & RE_NO_EMPTY_RANGES)
2973*820c1a8dSHiroo HAYASHI && start_collseq > end_collseq))
2974*820c1a8dSHiroo HAYASHI return REG_ERANGE;
2975*820c1a8dSHiroo HAYASHI
2976*820c1a8dSHiroo HAYASHI /* Got valid collation sequence values, add them as a new entry.
2977*820c1a8dSHiroo HAYASHI However, if we have no collation elements, and the character set
2978*820c1a8dSHiroo HAYASHI is single byte, the single byte character set that we
2979*820c1a8dSHiroo HAYASHI build below suffices. */
2980*820c1a8dSHiroo HAYASHI if (nrules > 0 || dfa->mb_cur_max > 1)
2981*820c1a8dSHiroo HAYASHI {
2982*820c1a8dSHiroo HAYASHI /* Check the space of the arrays. */
2983*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*range_alloc == mbcset->nranges))
2984*820c1a8dSHiroo HAYASHI {
2985*820c1a8dSHiroo HAYASHI /* There is not enough space, need realloc. */
2986*820c1a8dSHiroo HAYASHI uint32_t *new_array_start;
2987*820c1a8dSHiroo HAYASHI uint32_t *new_array_end;
2988*820c1a8dSHiroo HAYASHI Idx new_nranges;
2989*820c1a8dSHiroo HAYASHI
2990*820c1a8dSHiroo HAYASHI /* +1 in case of mbcset->nranges is 0. */
2991*820c1a8dSHiroo HAYASHI new_nranges = 2 * mbcset->nranges + 1;
2992*820c1a8dSHiroo HAYASHI new_array_start = re_realloc (mbcset->range_starts, uint32_t,
2993*820c1a8dSHiroo HAYASHI new_nranges);
2994*820c1a8dSHiroo HAYASHI new_array_end = re_realloc (mbcset->range_ends, uint32_t,
2995*820c1a8dSHiroo HAYASHI new_nranges);
2996*820c1a8dSHiroo HAYASHI
2997*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (new_array_start == NULL
2998*820c1a8dSHiroo HAYASHI || new_array_end == NULL))
2999*820c1a8dSHiroo HAYASHI return REG_ESPACE;
3000*820c1a8dSHiroo HAYASHI
3001*820c1a8dSHiroo HAYASHI mbcset->range_starts = new_array_start;
3002*820c1a8dSHiroo HAYASHI mbcset->range_ends = new_array_end;
3003*820c1a8dSHiroo HAYASHI *range_alloc = new_nranges;
3004*820c1a8dSHiroo HAYASHI }
3005*820c1a8dSHiroo HAYASHI
3006*820c1a8dSHiroo HAYASHI mbcset->range_starts[mbcset->nranges] = start_collseq;
3007*820c1a8dSHiroo HAYASHI mbcset->range_ends[mbcset->nranges++] = end_collseq;
3008*820c1a8dSHiroo HAYASHI }
3009*820c1a8dSHiroo HAYASHI
3010*820c1a8dSHiroo HAYASHI /* Build the table for single byte characters. */
3011*820c1a8dSHiroo HAYASHI for (ch = 0; ch < SBC_MAX; ch++)
3012*820c1a8dSHiroo HAYASHI {
3013*820c1a8dSHiroo HAYASHI uint32_t ch_collseq;
3014*820c1a8dSHiroo HAYASHI /*
3015*820c1a8dSHiroo HAYASHI if (MB_CUR_MAX == 1)
3016*820c1a8dSHiroo HAYASHI */
3017*820c1a8dSHiroo HAYASHI if (nrules == 0)
3018*820c1a8dSHiroo HAYASHI ch_collseq = collseqmb[ch];
3019*820c1a8dSHiroo HAYASHI else
3020*820c1a8dSHiroo HAYASHI ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch));
3021*820c1a8dSHiroo HAYASHI if (start_collseq <= ch_collseq && ch_collseq <= end_collseq)
3022*820c1a8dSHiroo HAYASHI bitset_set (sbcset, ch);
3023*820c1a8dSHiroo HAYASHI }
3024*820c1a8dSHiroo HAYASHI return REG_NOERROR;
3025*820c1a8dSHiroo HAYASHI }
3026*820c1a8dSHiroo HAYASHI
3027*820c1a8dSHiroo HAYASHI /* Local function for parse_bracket_exp used in _LIBC environment.
3028*820c1a8dSHiroo HAYASHI Build the collating element which is represented by NAME.
3029*820c1a8dSHiroo HAYASHI The result are written to MBCSET and SBCSET.
3030*820c1a8dSHiroo HAYASHI COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
3031*820c1a8dSHiroo HAYASHI pointer argument since we may update it. */
3032*820c1a8dSHiroo HAYASHI
3033*820c1a8dSHiroo HAYASHI auto inline reg_errcode_t
3034*820c1a8dSHiroo HAYASHI __attribute__ ((always_inline))
3035*820c1a8dSHiroo HAYASHI build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset,
3036*820c1a8dSHiroo HAYASHI Idx *coll_sym_alloc, const unsigned char *name)
3037*820c1a8dSHiroo HAYASHI {
3038*820c1a8dSHiroo HAYASHI int32_t elem, idx;
3039*820c1a8dSHiroo HAYASHI size_t name_len = strlen ((const char *) name);
3040*820c1a8dSHiroo HAYASHI if (nrules != 0)
3041*820c1a8dSHiroo HAYASHI {
3042*820c1a8dSHiroo HAYASHI elem = seek_collating_symbol_entry (name, name_len);
3043*820c1a8dSHiroo HAYASHI if (elem != -1)
3044*820c1a8dSHiroo HAYASHI {
3045*820c1a8dSHiroo HAYASHI /* We found the entry. */
3046*820c1a8dSHiroo HAYASHI idx = symb_table[2 * elem + 1];
3047*820c1a8dSHiroo HAYASHI /* Skip the name of collating element name. */
3048*820c1a8dSHiroo HAYASHI idx += 1 + extra[idx];
3049*820c1a8dSHiroo HAYASHI }
3050*820c1a8dSHiroo HAYASHI else if (name_len == 1)
3051*820c1a8dSHiroo HAYASHI {
3052*820c1a8dSHiroo HAYASHI /* No valid character, treat it as a normal
3053*820c1a8dSHiroo HAYASHI character. */
3054*820c1a8dSHiroo HAYASHI bitset_set (sbcset, name[0]);
3055*820c1a8dSHiroo HAYASHI return REG_NOERROR;
3056*820c1a8dSHiroo HAYASHI }
3057*820c1a8dSHiroo HAYASHI else
3058*820c1a8dSHiroo HAYASHI return REG_ECOLLATE;
3059*820c1a8dSHiroo HAYASHI
3060*820c1a8dSHiroo HAYASHI /* Got valid collation sequence, add it as a new entry. */
3061*820c1a8dSHiroo HAYASHI /* Check the space of the arrays. */
3062*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*coll_sym_alloc == mbcset->ncoll_syms))
3063*820c1a8dSHiroo HAYASHI {
3064*820c1a8dSHiroo HAYASHI /* Not enough, realloc it. */
3065*820c1a8dSHiroo HAYASHI /* +1 in case of mbcset->ncoll_syms is 0. */
3066*820c1a8dSHiroo HAYASHI Idx new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1;
3067*820c1a8dSHiroo HAYASHI /* Use realloc since mbcset->coll_syms is NULL
3068*820c1a8dSHiroo HAYASHI if *alloc == 0. */
3069*820c1a8dSHiroo HAYASHI int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t,
3070*820c1a8dSHiroo HAYASHI new_coll_sym_alloc);
3071*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (new_coll_syms == NULL))
3072*820c1a8dSHiroo HAYASHI return REG_ESPACE;
3073*820c1a8dSHiroo HAYASHI mbcset->coll_syms = new_coll_syms;
3074*820c1a8dSHiroo HAYASHI *coll_sym_alloc = new_coll_sym_alloc;
3075*820c1a8dSHiroo HAYASHI }
3076*820c1a8dSHiroo HAYASHI mbcset->coll_syms[mbcset->ncoll_syms++] = idx;
3077*820c1a8dSHiroo HAYASHI return REG_NOERROR;
3078*820c1a8dSHiroo HAYASHI }
3079*820c1a8dSHiroo HAYASHI else
3080*820c1a8dSHiroo HAYASHI {
3081*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (name_len != 1))
3082*820c1a8dSHiroo HAYASHI return REG_ECOLLATE;
3083*820c1a8dSHiroo HAYASHI else
3084*820c1a8dSHiroo HAYASHI {
3085*820c1a8dSHiroo HAYASHI bitset_set (sbcset, name[0]);
3086*820c1a8dSHiroo HAYASHI return REG_NOERROR;
3087*820c1a8dSHiroo HAYASHI }
3088*820c1a8dSHiroo HAYASHI }
3089*820c1a8dSHiroo HAYASHI }
3090*820c1a8dSHiroo HAYASHI #endif
3091*820c1a8dSHiroo HAYASHI
3092*820c1a8dSHiroo HAYASHI re_token_t br_token;
3093*820c1a8dSHiroo HAYASHI re_bitset_ptr_t sbcset;
3094*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3095*820c1a8dSHiroo HAYASHI re_charset_t *mbcset;
3096*820c1a8dSHiroo HAYASHI Idx coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0;
3097*820c1a8dSHiroo HAYASHI Idx equiv_class_alloc = 0, char_class_alloc = 0;
3098*820c1a8dSHiroo HAYASHI #endif /* not RE_ENABLE_I18N */
3099*820c1a8dSHiroo HAYASHI bool non_match = false;
3100*820c1a8dSHiroo HAYASHI bin_tree_t *work_tree;
3101*820c1a8dSHiroo HAYASHI int token_len;
3102*820c1a8dSHiroo HAYASHI bool first_round = true;
3103*820c1a8dSHiroo HAYASHI #ifdef _LIBC
3104*820c1a8dSHiroo HAYASHI collseqmb = (const unsigned char *)
3105*820c1a8dSHiroo HAYASHI _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);
3106*820c1a8dSHiroo HAYASHI nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
3107*820c1a8dSHiroo HAYASHI if (nrules)
3108*820c1a8dSHiroo HAYASHI {
3109*820c1a8dSHiroo HAYASHI /*
3110*820c1a8dSHiroo HAYASHI if (MB_CUR_MAX > 1)
3111*820c1a8dSHiroo HAYASHI */
3112*820c1a8dSHiroo HAYASHI collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);
3113*820c1a8dSHiroo HAYASHI table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB);
3114*820c1a8dSHiroo HAYASHI symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE,
3115*820c1a8dSHiroo HAYASHI _NL_COLLATE_SYMB_TABLEMB);
3116*820c1a8dSHiroo HAYASHI extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
3117*820c1a8dSHiroo HAYASHI _NL_COLLATE_SYMB_EXTRAMB);
3118*820c1a8dSHiroo HAYASHI }
3119*820c1a8dSHiroo HAYASHI #endif
3120*820c1a8dSHiroo HAYASHI sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
3121*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3122*820c1a8dSHiroo HAYASHI mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
3123*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
3124*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3125*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (sbcset == NULL || mbcset == NULL))
3126*820c1a8dSHiroo HAYASHI #else
3127*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (sbcset == NULL))
3128*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
3129*820c1a8dSHiroo HAYASHI {
3130*820c1a8dSHiroo HAYASHI re_free (sbcset);
3131*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3132*820c1a8dSHiroo HAYASHI re_free (mbcset);
3133*820c1a8dSHiroo HAYASHI #endif
3134*820c1a8dSHiroo HAYASHI *err = REG_ESPACE;
3135*820c1a8dSHiroo HAYASHI return NULL;
3136*820c1a8dSHiroo HAYASHI }
3137*820c1a8dSHiroo HAYASHI
3138*820c1a8dSHiroo HAYASHI token_len = peek_token_bracket (token, regexp, syntax);
3139*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (token->type == END_OF_RE))
3140*820c1a8dSHiroo HAYASHI {
3141*820c1a8dSHiroo HAYASHI *err = REG_BADPAT;
3142*820c1a8dSHiroo HAYASHI goto parse_bracket_exp_free_return;
3143*820c1a8dSHiroo HAYASHI }
3144*820c1a8dSHiroo HAYASHI if (token->type == OP_NON_MATCH_LIST)
3145*820c1a8dSHiroo HAYASHI {
3146*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3147*820c1a8dSHiroo HAYASHI mbcset->non_match = 1;
3148*820c1a8dSHiroo HAYASHI #endif /* not RE_ENABLE_I18N */
3149*820c1a8dSHiroo HAYASHI non_match = true;
3150*820c1a8dSHiroo HAYASHI if (syntax & RE_HAT_LISTS_NOT_NEWLINE)
3151*820c1a8dSHiroo HAYASHI bitset_set (sbcset, '\n');
3152*820c1a8dSHiroo HAYASHI re_string_skip_bytes (regexp, token_len); /* Skip a token. */
3153*820c1a8dSHiroo HAYASHI token_len = peek_token_bracket (token, regexp, syntax);
3154*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (token->type == END_OF_RE))
3155*820c1a8dSHiroo HAYASHI {
3156*820c1a8dSHiroo HAYASHI *err = REG_BADPAT;
3157*820c1a8dSHiroo HAYASHI goto parse_bracket_exp_free_return;
3158*820c1a8dSHiroo HAYASHI }
3159*820c1a8dSHiroo HAYASHI }
3160*820c1a8dSHiroo HAYASHI
3161*820c1a8dSHiroo HAYASHI /* We treat the first ']' as a normal character. */
3162*820c1a8dSHiroo HAYASHI if (token->type == OP_CLOSE_BRACKET)
3163*820c1a8dSHiroo HAYASHI token->type = CHARACTER;
3164*820c1a8dSHiroo HAYASHI
3165*820c1a8dSHiroo HAYASHI while (1)
3166*820c1a8dSHiroo HAYASHI {
3167*820c1a8dSHiroo HAYASHI bracket_elem_t start_elem, end_elem;
3168*820c1a8dSHiroo HAYASHI unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE];
3169*820c1a8dSHiroo HAYASHI unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE];
3170*820c1a8dSHiroo HAYASHI reg_errcode_t ret;
3171*820c1a8dSHiroo HAYASHI int token_len2 = 0;
3172*820c1a8dSHiroo HAYASHI bool is_range_exp = false;
3173*820c1a8dSHiroo HAYASHI re_token_t token2;
3174*820c1a8dSHiroo HAYASHI
3175*820c1a8dSHiroo HAYASHI start_elem.opr.name = start_name_buf;
3176*820c1a8dSHiroo HAYASHI start_elem.type = COLL_SYM;
3177*820c1a8dSHiroo HAYASHI ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa,
3178*820c1a8dSHiroo HAYASHI syntax, first_round);
3179*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (ret != REG_NOERROR))
3180*820c1a8dSHiroo HAYASHI {
3181*820c1a8dSHiroo HAYASHI *err = ret;
3182*820c1a8dSHiroo HAYASHI goto parse_bracket_exp_free_return;
3183*820c1a8dSHiroo HAYASHI }
3184*820c1a8dSHiroo HAYASHI first_round = false;
3185*820c1a8dSHiroo HAYASHI
3186*820c1a8dSHiroo HAYASHI /* Get information about the next token. We need it in any case. */
3187*820c1a8dSHiroo HAYASHI token_len = peek_token_bracket (token, regexp, syntax);
3188*820c1a8dSHiroo HAYASHI
3189*820c1a8dSHiroo HAYASHI /* Do not check for ranges if we know they are not allowed. */
3190*820c1a8dSHiroo HAYASHI if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS)
3191*820c1a8dSHiroo HAYASHI {
3192*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (token->type == END_OF_RE))
3193*820c1a8dSHiroo HAYASHI {
3194*820c1a8dSHiroo HAYASHI *err = REG_EBRACK;
3195*820c1a8dSHiroo HAYASHI goto parse_bracket_exp_free_return;
3196*820c1a8dSHiroo HAYASHI }
3197*820c1a8dSHiroo HAYASHI if (token->type == OP_CHARSET_RANGE)
3198*820c1a8dSHiroo HAYASHI {
3199*820c1a8dSHiroo HAYASHI re_string_skip_bytes (regexp, token_len); /* Skip '-'. */
3200*820c1a8dSHiroo HAYASHI token_len2 = peek_token_bracket (&token2, regexp, syntax);
3201*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (token2.type == END_OF_RE))
3202*820c1a8dSHiroo HAYASHI {
3203*820c1a8dSHiroo HAYASHI *err = REG_EBRACK;
3204*820c1a8dSHiroo HAYASHI goto parse_bracket_exp_free_return;
3205*820c1a8dSHiroo HAYASHI }
3206*820c1a8dSHiroo HAYASHI if (token2.type == OP_CLOSE_BRACKET)
3207*820c1a8dSHiroo HAYASHI {
3208*820c1a8dSHiroo HAYASHI /* We treat the last '-' as a normal character. */
3209*820c1a8dSHiroo HAYASHI re_string_skip_bytes (regexp, -token_len);
3210*820c1a8dSHiroo HAYASHI token->type = CHARACTER;
3211*820c1a8dSHiroo HAYASHI }
3212*820c1a8dSHiroo HAYASHI else
3213*820c1a8dSHiroo HAYASHI is_range_exp = true;
3214*820c1a8dSHiroo HAYASHI }
3215*820c1a8dSHiroo HAYASHI }
3216*820c1a8dSHiroo HAYASHI
3217*820c1a8dSHiroo HAYASHI if (is_range_exp == true)
3218*820c1a8dSHiroo HAYASHI {
3219*820c1a8dSHiroo HAYASHI end_elem.opr.name = end_name_buf;
3220*820c1a8dSHiroo HAYASHI end_elem.type = COLL_SYM;
3221*820c1a8dSHiroo HAYASHI ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2,
3222*820c1a8dSHiroo HAYASHI dfa, syntax, true);
3223*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (ret != REG_NOERROR))
3224*820c1a8dSHiroo HAYASHI {
3225*820c1a8dSHiroo HAYASHI *err = ret;
3226*820c1a8dSHiroo HAYASHI goto parse_bracket_exp_free_return;
3227*820c1a8dSHiroo HAYASHI }
3228*820c1a8dSHiroo HAYASHI
3229*820c1a8dSHiroo HAYASHI token_len = peek_token_bracket (token, regexp, syntax);
3230*820c1a8dSHiroo HAYASHI
3231*820c1a8dSHiroo HAYASHI #ifdef _LIBC
3232*820c1a8dSHiroo HAYASHI *err = build_range_exp (sbcset, mbcset, &range_alloc,
3233*820c1a8dSHiroo HAYASHI &start_elem, &end_elem);
3234*820c1a8dSHiroo HAYASHI #else
3235*820c1a8dSHiroo HAYASHI # ifdef RE_ENABLE_I18N
3236*820c1a8dSHiroo HAYASHI *err = build_range_exp (syntax, sbcset,
3237*820c1a8dSHiroo HAYASHI dfa->mb_cur_max > 1 ? mbcset : NULL,
3238*820c1a8dSHiroo HAYASHI &range_alloc, &start_elem, &end_elem);
3239*820c1a8dSHiroo HAYASHI # else
3240*820c1a8dSHiroo HAYASHI *err = build_range_exp (syntax, sbcset, &start_elem, &end_elem);
3241*820c1a8dSHiroo HAYASHI # endif
3242*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
3243*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*err != REG_NOERROR))
3244*820c1a8dSHiroo HAYASHI goto parse_bracket_exp_free_return;
3245*820c1a8dSHiroo HAYASHI }
3246*820c1a8dSHiroo HAYASHI else
3247*820c1a8dSHiroo HAYASHI {
3248*820c1a8dSHiroo HAYASHI switch (start_elem.type)
3249*820c1a8dSHiroo HAYASHI {
3250*820c1a8dSHiroo HAYASHI case SB_CHAR:
3251*820c1a8dSHiroo HAYASHI bitset_set (sbcset, start_elem.opr.ch);
3252*820c1a8dSHiroo HAYASHI break;
3253*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3254*820c1a8dSHiroo HAYASHI case MB_CHAR:
3255*820c1a8dSHiroo HAYASHI /* Check whether the array has enough space. */
3256*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (mbchar_alloc == mbcset->nmbchars))
3257*820c1a8dSHiroo HAYASHI {
3258*820c1a8dSHiroo HAYASHI wchar_t *new_mbchars;
3259*820c1a8dSHiroo HAYASHI /* Not enough, realloc it. */
3260*820c1a8dSHiroo HAYASHI /* +1 in case of mbcset->nmbchars is 0. */
3261*820c1a8dSHiroo HAYASHI mbchar_alloc = 2 * mbcset->nmbchars + 1;
3262*820c1a8dSHiroo HAYASHI /* Use realloc since array is NULL if *alloc == 0. */
3263*820c1a8dSHiroo HAYASHI new_mbchars = re_realloc (mbcset->mbchars, wchar_t,
3264*820c1a8dSHiroo HAYASHI mbchar_alloc);
3265*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (new_mbchars == NULL))
3266*820c1a8dSHiroo HAYASHI goto parse_bracket_exp_espace;
3267*820c1a8dSHiroo HAYASHI mbcset->mbchars = new_mbchars;
3268*820c1a8dSHiroo HAYASHI }
3269*820c1a8dSHiroo HAYASHI mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch;
3270*820c1a8dSHiroo HAYASHI break;
3271*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
3272*820c1a8dSHiroo HAYASHI case EQUIV_CLASS:
3273*820c1a8dSHiroo HAYASHI *err = build_equiv_class (sbcset,
3274*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3275*820c1a8dSHiroo HAYASHI mbcset, &equiv_class_alloc,
3276*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
3277*820c1a8dSHiroo HAYASHI start_elem.opr.name);
3278*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*err != REG_NOERROR))
3279*820c1a8dSHiroo HAYASHI goto parse_bracket_exp_free_return;
3280*820c1a8dSHiroo HAYASHI break;
3281*820c1a8dSHiroo HAYASHI case COLL_SYM:
3282*820c1a8dSHiroo HAYASHI *err = build_collating_symbol (sbcset,
3283*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3284*820c1a8dSHiroo HAYASHI mbcset, &coll_sym_alloc,
3285*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
3286*820c1a8dSHiroo HAYASHI start_elem.opr.name);
3287*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*err != REG_NOERROR))
3288*820c1a8dSHiroo HAYASHI goto parse_bracket_exp_free_return;
3289*820c1a8dSHiroo HAYASHI break;
3290*820c1a8dSHiroo HAYASHI case CHAR_CLASS:
3291*820c1a8dSHiroo HAYASHI *err = build_charclass (regexp->trans, sbcset,
3292*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3293*820c1a8dSHiroo HAYASHI mbcset, &char_class_alloc,
3294*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
3295*820c1a8dSHiroo HAYASHI (const char *) start_elem.opr.name,
3296*820c1a8dSHiroo HAYASHI syntax);
3297*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*err != REG_NOERROR))
3298*820c1a8dSHiroo HAYASHI goto parse_bracket_exp_free_return;
3299*820c1a8dSHiroo HAYASHI break;
3300*820c1a8dSHiroo HAYASHI default:
3301*820c1a8dSHiroo HAYASHI DEBUG_ASSERT (false);
3302*820c1a8dSHiroo HAYASHI break;
3303*820c1a8dSHiroo HAYASHI }
3304*820c1a8dSHiroo HAYASHI }
3305*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (token->type == END_OF_RE))
3306*820c1a8dSHiroo HAYASHI {
3307*820c1a8dSHiroo HAYASHI *err = REG_EBRACK;
3308*820c1a8dSHiroo HAYASHI goto parse_bracket_exp_free_return;
3309*820c1a8dSHiroo HAYASHI }
3310*820c1a8dSHiroo HAYASHI if (token->type == OP_CLOSE_BRACKET)
3311*820c1a8dSHiroo HAYASHI break;
3312*820c1a8dSHiroo HAYASHI }
3313*820c1a8dSHiroo HAYASHI
3314*820c1a8dSHiroo HAYASHI re_string_skip_bytes (regexp, token_len); /* Skip a token. */
3315*820c1a8dSHiroo HAYASHI
3316*820c1a8dSHiroo HAYASHI /* If it is non-matching list. */
3317*820c1a8dSHiroo HAYASHI if (non_match)
3318*820c1a8dSHiroo HAYASHI bitset_not (sbcset);
3319*820c1a8dSHiroo HAYASHI
3320*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3321*820c1a8dSHiroo HAYASHI /* Ensure only single byte characters are set. */
3322*820c1a8dSHiroo HAYASHI if (dfa->mb_cur_max > 1)
3323*820c1a8dSHiroo HAYASHI bitset_mask (sbcset, dfa->sb_char);
3324*820c1a8dSHiroo HAYASHI
3325*820c1a8dSHiroo HAYASHI if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes
3326*820c1a8dSHiroo HAYASHI || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes
3327*820c1a8dSHiroo HAYASHI || mbcset->non_match)))
3328*820c1a8dSHiroo HAYASHI {
3329*820c1a8dSHiroo HAYASHI bin_tree_t *mbc_tree;
3330*820c1a8dSHiroo HAYASHI int sbc_idx;
3331*820c1a8dSHiroo HAYASHI /* Build a tree for complex bracket. */
3332*820c1a8dSHiroo HAYASHI dfa->has_mb_node = 1;
3333*820c1a8dSHiroo HAYASHI br_token.type = COMPLEX_BRACKET;
3334*820c1a8dSHiroo HAYASHI br_token.opr.mbcset = mbcset;
3335*820c1a8dSHiroo HAYASHI mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);
3336*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (mbc_tree == NULL))
3337*820c1a8dSHiroo HAYASHI goto parse_bracket_exp_espace;
3338*820c1a8dSHiroo HAYASHI for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx)
3339*820c1a8dSHiroo HAYASHI if (sbcset[sbc_idx])
3340*820c1a8dSHiroo HAYASHI break;
3341*820c1a8dSHiroo HAYASHI /* If there are no bits set in sbcset, there is no point
3342*820c1a8dSHiroo HAYASHI of having both SIMPLE_BRACKET and COMPLEX_BRACKET. */
3343*820c1a8dSHiroo HAYASHI if (sbc_idx < BITSET_WORDS)
3344*820c1a8dSHiroo HAYASHI {
3345*820c1a8dSHiroo HAYASHI /* Build a tree for simple bracket. */
3346*820c1a8dSHiroo HAYASHI br_token.type = SIMPLE_BRACKET;
3347*820c1a8dSHiroo HAYASHI br_token.opr.sbcset = sbcset;
3348*820c1a8dSHiroo HAYASHI work_tree = create_token_tree (dfa, NULL, NULL, &br_token);
3349*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (work_tree == NULL))
3350*820c1a8dSHiroo HAYASHI goto parse_bracket_exp_espace;
3351*820c1a8dSHiroo HAYASHI
3352*820c1a8dSHiroo HAYASHI /* Then join them by ALT node. */
3353*820c1a8dSHiroo HAYASHI work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT);
3354*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (work_tree == NULL))
3355*820c1a8dSHiroo HAYASHI goto parse_bracket_exp_espace;
3356*820c1a8dSHiroo HAYASHI }
3357*820c1a8dSHiroo HAYASHI else
3358*820c1a8dSHiroo HAYASHI {
3359*820c1a8dSHiroo HAYASHI re_free (sbcset);
3360*820c1a8dSHiroo HAYASHI work_tree = mbc_tree;
3361*820c1a8dSHiroo HAYASHI }
3362*820c1a8dSHiroo HAYASHI }
3363*820c1a8dSHiroo HAYASHI else
3364*820c1a8dSHiroo HAYASHI #endif /* not RE_ENABLE_I18N */
3365*820c1a8dSHiroo HAYASHI {
3366*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3367*820c1a8dSHiroo HAYASHI free_charset (mbcset);
3368*820c1a8dSHiroo HAYASHI #endif
3369*820c1a8dSHiroo HAYASHI /* Build a tree for simple bracket. */
3370*820c1a8dSHiroo HAYASHI br_token.type = SIMPLE_BRACKET;
3371*820c1a8dSHiroo HAYASHI br_token.opr.sbcset = sbcset;
3372*820c1a8dSHiroo HAYASHI work_tree = create_token_tree (dfa, NULL, NULL, &br_token);
3373*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (work_tree == NULL))
3374*820c1a8dSHiroo HAYASHI goto parse_bracket_exp_espace;
3375*820c1a8dSHiroo HAYASHI }
3376*820c1a8dSHiroo HAYASHI return work_tree;
3377*820c1a8dSHiroo HAYASHI
3378*820c1a8dSHiroo HAYASHI parse_bracket_exp_espace:
3379*820c1a8dSHiroo HAYASHI *err = REG_ESPACE;
3380*820c1a8dSHiroo HAYASHI parse_bracket_exp_free_return:
3381*820c1a8dSHiroo HAYASHI re_free (sbcset);
3382*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3383*820c1a8dSHiroo HAYASHI free_charset (mbcset);
3384*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
3385*820c1a8dSHiroo HAYASHI return NULL;
3386*820c1a8dSHiroo HAYASHI }
3387*820c1a8dSHiroo HAYASHI
3388*820c1a8dSHiroo HAYASHI /* Parse an element in the bracket expression. */
3389*820c1a8dSHiroo HAYASHI
3390*820c1a8dSHiroo HAYASHI static reg_errcode_t
parse_bracket_element(bracket_elem_t * elem,re_string_t * regexp,re_token_t * token,int token_len,re_dfa_t * dfa,reg_syntax_t syntax,bool accept_hyphen)3391*820c1a8dSHiroo HAYASHI parse_bracket_element (bracket_elem_t *elem, re_string_t *regexp,
3392*820c1a8dSHiroo HAYASHI re_token_t *token, int token_len, re_dfa_t *dfa,
3393*820c1a8dSHiroo HAYASHI reg_syntax_t syntax, bool accept_hyphen)
3394*820c1a8dSHiroo HAYASHI {
3395*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3396*820c1a8dSHiroo HAYASHI int cur_char_size;
3397*820c1a8dSHiroo HAYASHI cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp));
3398*820c1a8dSHiroo HAYASHI if (cur_char_size > 1)
3399*820c1a8dSHiroo HAYASHI {
3400*820c1a8dSHiroo HAYASHI elem->type = MB_CHAR;
3401*820c1a8dSHiroo HAYASHI elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp));
3402*820c1a8dSHiroo HAYASHI re_string_skip_bytes (regexp, cur_char_size);
3403*820c1a8dSHiroo HAYASHI return REG_NOERROR;
3404*820c1a8dSHiroo HAYASHI }
3405*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
3406*820c1a8dSHiroo HAYASHI re_string_skip_bytes (regexp, token_len); /* Skip a token. */
3407*820c1a8dSHiroo HAYASHI if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS
3408*820c1a8dSHiroo HAYASHI || token->type == OP_OPEN_EQUIV_CLASS)
3409*820c1a8dSHiroo HAYASHI return parse_bracket_symbol (elem, regexp, token);
3410*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (token->type == OP_CHARSET_RANGE) && !accept_hyphen)
3411*820c1a8dSHiroo HAYASHI {
3412*820c1a8dSHiroo HAYASHI /* A '-' must only appear as anything but a range indicator before
3413*820c1a8dSHiroo HAYASHI the closing bracket. Everything else is an error. */
3414*820c1a8dSHiroo HAYASHI re_token_t token2;
3415*820c1a8dSHiroo HAYASHI (void) peek_token_bracket (&token2, regexp, syntax);
3416*820c1a8dSHiroo HAYASHI if (token2.type != OP_CLOSE_BRACKET)
3417*820c1a8dSHiroo HAYASHI /* The actual error value is not standardized since this whole
3418*820c1a8dSHiroo HAYASHI case is undefined. But ERANGE makes good sense. */
3419*820c1a8dSHiroo HAYASHI return REG_ERANGE;
3420*820c1a8dSHiroo HAYASHI }
3421*820c1a8dSHiroo HAYASHI elem->type = SB_CHAR;
3422*820c1a8dSHiroo HAYASHI elem->opr.ch = token->opr.c;
3423*820c1a8dSHiroo HAYASHI return REG_NOERROR;
3424*820c1a8dSHiroo HAYASHI }
3425*820c1a8dSHiroo HAYASHI
3426*820c1a8dSHiroo HAYASHI /* Parse a bracket symbol in the bracket expression. Bracket symbols are
3427*820c1a8dSHiroo HAYASHI such as [:<character_class>:], [.<collating_element>.], and
3428*820c1a8dSHiroo HAYASHI [=<equivalent_class>=]. */
3429*820c1a8dSHiroo HAYASHI
3430*820c1a8dSHiroo HAYASHI static reg_errcode_t
parse_bracket_symbol(bracket_elem_t * elem,re_string_t * regexp,re_token_t * token)3431*820c1a8dSHiroo HAYASHI parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp,
3432*820c1a8dSHiroo HAYASHI re_token_t *token)
3433*820c1a8dSHiroo HAYASHI {
3434*820c1a8dSHiroo HAYASHI unsigned char ch, delim = token->opr.c;
3435*820c1a8dSHiroo HAYASHI int i = 0;
3436*820c1a8dSHiroo HAYASHI if (re_string_eoi(regexp))
3437*820c1a8dSHiroo HAYASHI return REG_EBRACK;
3438*820c1a8dSHiroo HAYASHI for (;; ++i)
3439*820c1a8dSHiroo HAYASHI {
3440*820c1a8dSHiroo HAYASHI if (i >= BRACKET_NAME_BUF_SIZE)
3441*820c1a8dSHiroo HAYASHI return REG_EBRACK;
3442*820c1a8dSHiroo HAYASHI if (token->type == OP_OPEN_CHAR_CLASS)
3443*820c1a8dSHiroo HAYASHI ch = re_string_fetch_byte_case (regexp);
3444*820c1a8dSHiroo HAYASHI else
3445*820c1a8dSHiroo HAYASHI ch = re_string_fetch_byte (regexp);
3446*820c1a8dSHiroo HAYASHI if (re_string_eoi(regexp))
3447*820c1a8dSHiroo HAYASHI return REG_EBRACK;
3448*820c1a8dSHiroo HAYASHI if (ch == delim && re_string_peek_byte (regexp, 0) == ']')
3449*820c1a8dSHiroo HAYASHI break;
3450*820c1a8dSHiroo HAYASHI elem->opr.name[i] = ch;
3451*820c1a8dSHiroo HAYASHI }
3452*820c1a8dSHiroo HAYASHI re_string_skip_bytes (regexp, 1);
3453*820c1a8dSHiroo HAYASHI elem->opr.name[i] = '\0';
3454*820c1a8dSHiroo HAYASHI switch (token->type)
3455*820c1a8dSHiroo HAYASHI {
3456*820c1a8dSHiroo HAYASHI case OP_OPEN_COLL_ELEM:
3457*820c1a8dSHiroo HAYASHI elem->type = COLL_SYM;
3458*820c1a8dSHiroo HAYASHI break;
3459*820c1a8dSHiroo HAYASHI case OP_OPEN_EQUIV_CLASS:
3460*820c1a8dSHiroo HAYASHI elem->type = EQUIV_CLASS;
3461*820c1a8dSHiroo HAYASHI break;
3462*820c1a8dSHiroo HAYASHI case OP_OPEN_CHAR_CLASS:
3463*820c1a8dSHiroo HAYASHI elem->type = CHAR_CLASS;
3464*820c1a8dSHiroo HAYASHI break;
3465*820c1a8dSHiroo HAYASHI default:
3466*820c1a8dSHiroo HAYASHI break;
3467*820c1a8dSHiroo HAYASHI }
3468*820c1a8dSHiroo HAYASHI return REG_NOERROR;
3469*820c1a8dSHiroo HAYASHI }
3470*820c1a8dSHiroo HAYASHI
3471*820c1a8dSHiroo HAYASHI /* Helper function for parse_bracket_exp.
3472*820c1a8dSHiroo HAYASHI Build the equivalence class which is represented by NAME.
3473*820c1a8dSHiroo HAYASHI The result are written to MBCSET and SBCSET.
3474*820c1a8dSHiroo HAYASHI EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes,
3475*820c1a8dSHiroo HAYASHI is a pointer argument since we may update it. */
3476*820c1a8dSHiroo HAYASHI
3477*820c1a8dSHiroo HAYASHI static reg_errcode_t
3478*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
build_equiv_class(bitset_t sbcset,re_charset_t * mbcset,Idx * equiv_class_alloc,const unsigned char * name)3479*820c1a8dSHiroo HAYASHI build_equiv_class (bitset_t sbcset, re_charset_t *mbcset,
3480*820c1a8dSHiroo HAYASHI Idx *equiv_class_alloc, const unsigned char *name)
3481*820c1a8dSHiroo HAYASHI #else /* not RE_ENABLE_I18N */
3482*820c1a8dSHiroo HAYASHI build_equiv_class (bitset_t sbcset, const unsigned char *name)
3483*820c1a8dSHiroo HAYASHI #endif /* not RE_ENABLE_I18N */
3484*820c1a8dSHiroo HAYASHI {
3485*820c1a8dSHiroo HAYASHI #ifdef _LIBC
3486*820c1a8dSHiroo HAYASHI uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);
3487*820c1a8dSHiroo HAYASHI if (nrules != 0)
3488*820c1a8dSHiroo HAYASHI {
3489*820c1a8dSHiroo HAYASHI const int32_t *table, *indirect;
3490*820c1a8dSHiroo HAYASHI const unsigned char *weights, *extra, *cp;
3491*820c1a8dSHiroo HAYASHI unsigned char char_buf[2];
3492*820c1a8dSHiroo HAYASHI int32_t idx1, idx2;
3493*820c1a8dSHiroo HAYASHI unsigned int ch;
3494*820c1a8dSHiroo HAYASHI size_t len;
3495*820c1a8dSHiroo HAYASHI /* Calculate the index for equivalence class. */
3496*820c1a8dSHiroo HAYASHI cp = name;
3497*820c1a8dSHiroo HAYASHI table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);
3498*820c1a8dSHiroo HAYASHI weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
3499*820c1a8dSHiroo HAYASHI _NL_COLLATE_WEIGHTMB);
3500*820c1a8dSHiroo HAYASHI extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,
3501*820c1a8dSHiroo HAYASHI _NL_COLLATE_EXTRAMB);
3502*820c1a8dSHiroo HAYASHI indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,
3503*820c1a8dSHiroo HAYASHI _NL_COLLATE_INDIRECTMB);
3504*820c1a8dSHiroo HAYASHI idx1 = findidx (table, indirect, extra, &cp, -1);
3505*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (idx1 == 0 || *cp != '\0'))
3506*820c1a8dSHiroo HAYASHI /* This isn't a valid character. */
3507*820c1a8dSHiroo HAYASHI return REG_ECOLLATE;
3508*820c1a8dSHiroo HAYASHI
3509*820c1a8dSHiroo HAYASHI /* Build single byte matching table for this equivalence class. */
3510*820c1a8dSHiroo HAYASHI len = weights[idx1 & 0xffffff];
3511*820c1a8dSHiroo HAYASHI for (ch = 0; ch < SBC_MAX; ++ch)
3512*820c1a8dSHiroo HAYASHI {
3513*820c1a8dSHiroo HAYASHI char_buf[0] = ch;
3514*820c1a8dSHiroo HAYASHI cp = char_buf;
3515*820c1a8dSHiroo HAYASHI idx2 = findidx (table, indirect, extra, &cp, 1);
3516*820c1a8dSHiroo HAYASHI /*
3517*820c1a8dSHiroo HAYASHI idx2 = table[ch];
3518*820c1a8dSHiroo HAYASHI */
3519*820c1a8dSHiroo HAYASHI if (idx2 == 0)
3520*820c1a8dSHiroo HAYASHI /* This isn't a valid character. */
3521*820c1a8dSHiroo HAYASHI continue;
3522*820c1a8dSHiroo HAYASHI /* Compare only if the length matches and the collation rule
3523*820c1a8dSHiroo HAYASHI index is the same. */
3524*820c1a8dSHiroo HAYASHI if (len == weights[idx2 & 0xffffff] && (idx1 >> 24) == (idx2 >> 24)
3525*820c1a8dSHiroo HAYASHI && memcmp (weights + (idx1 & 0xffffff) + 1,
3526*820c1a8dSHiroo HAYASHI weights + (idx2 & 0xffffff) + 1, len) == 0)
3527*820c1a8dSHiroo HAYASHI bitset_set (sbcset, ch);
3528*820c1a8dSHiroo HAYASHI }
3529*820c1a8dSHiroo HAYASHI /* Check whether the array has enough space. */
3530*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*equiv_class_alloc == mbcset->nequiv_classes))
3531*820c1a8dSHiroo HAYASHI {
3532*820c1a8dSHiroo HAYASHI /* Not enough, realloc it. */
3533*820c1a8dSHiroo HAYASHI /* +1 in case of mbcset->nequiv_classes is 0. */
3534*820c1a8dSHiroo HAYASHI Idx new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1;
3535*820c1a8dSHiroo HAYASHI /* Use realloc since the array is NULL if *alloc == 0. */
3536*820c1a8dSHiroo HAYASHI int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes,
3537*820c1a8dSHiroo HAYASHI int32_t,
3538*820c1a8dSHiroo HAYASHI new_equiv_class_alloc);
3539*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (new_equiv_classes == NULL))
3540*820c1a8dSHiroo HAYASHI return REG_ESPACE;
3541*820c1a8dSHiroo HAYASHI mbcset->equiv_classes = new_equiv_classes;
3542*820c1a8dSHiroo HAYASHI *equiv_class_alloc = new_equiv_class_alloc;
3543*820c1a8dSHiroo HAYASHI }
3544*820c1a8dSHiroo HAYASHI mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1;
3545*820c1a8dSHiroo HAYASHI }
3546*820c1a8dSHiroo HAYASHI else
3547*820c1a8dSHiroo HAYASHI #endif /* _LIBC */
3548*820c1a8dSHiroo HAYASHI {
3549*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (strlen ((const char *) name) != 1))
3550*820c1a8dSHiroo HAYASHI return REG_ECOLLATE;
3551*820c1a8dSHiroo HAYASHI bitset_set (sbcset, *name);
3552*820c1a8dSHiroo HAYASHI }
3553*820c1a8dSHiroo HAYASHI return REG_NOERROR;
3554*820c1a8dSHiroo HAYASHI }
3555*820c1a8dSHiroo HAYASHI
3556*820c1a8dSHiroo HAYASHI /* Helper function for parse_bracket_exp.
3557*820c1a8dSHiroo HAYASHI Build the character class which is represented by NAME.
3558*820c1a8dSHiroo HAYASHI The result are written to MBCSET and SBCSET.
3559*820c1a8dSHiroo HAYASHI CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes,
3560*820c1a8dSHiroo HAYASHI is a pointer argument since we may update it. */
3561*820c1a8dSHiroo HAYASHI
3562*820c1a8dSHiroo HAYASHI static reg_errcode_t
3563*820c1a8dSHiroo HAYASHI #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)3564*820c1a8dSHiroo HAYASHI build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
3565*820c1a8dSHiroo HAYASHI re_charset_t *mbcset, Idx *char_class_alloc,
3566*820c1a8dSHiroo HAYASHI const char *class_name, reg_syntax_t syntax)
3567*820c1a8dSHiroo HAYASHI #else /* not RE_ENABLE_I18N */
3568*820c1a8dSHiroo HAYASHI build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
3569*820c1a8dSHiroo HAYASHI const char *class_name, reg_syntax_t syntax)
3570*820c1a8dSHiroo HAYASHI #endif /* not RE_ENABLE_I18N */
3571*820c1a8dSHiroo HAYASHI {
3572*820c1a8dSHiroo HAYASHI int i;
3573*820c1a8dSHiroo HAYASHI const char *name = class_name;
3574*820c1a8dSHiroo HAYASHI
3575*820c1a8dSHiroo HAYASHI /* In case of REG_ICASE "upper" and "lower" match the both of
3576*820c1a8dSHiroo HAYASHI upper and lower cases. */
3577*820c1a8dSHiroo HAYASHI if ((syntax & RE_ICASE)
3578*820c1a8dSHiroo HAYASHI && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0))
3579*820c1a8dSHiroo HAYASHI name = "alpha";
3580*820c1a8dSHiroo HAYASHI
3581*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3582*820c1a8dSHiroo HAYASHI /* Check the space of the arrays. */
3583*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (*char_class_alloc == mbcset->nchar_classes))
3584*820c1a8dSHiroo HAYASHI {
3585*820c1a8dSHiroo HAYASHI /* Not enough, realloc it. */
3586*820c1a8dSHiroo HAYASHI /* +1 in case of mbcset->nchar_classes is 0. */
3587*820c1a8dSHiroo HAYASHI Idx new_char_class_alloc = 2 * mbcset->nchar_classes + 1;
3588*820c1a8dSHiroo HAYASHI /* Use realloc since array is NULL if *alloc == 0. */
3589*820c1a8dSHiroo HAYASHI wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t,
3590*820c1a8dSHiroo HAYASHI new_char_class_alloc);
3591*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (new_char_classes == NULL))
3592*820c1a8dSHiroo HAYASHI return REG_ESPACE;
3593*820c1a8dSHiroo HAYASHI mbcset->char_classes = new_char_classes;
3594*820c1a8dSHiroo HAYASHI *char_class_alloc = new_char_class_alloc;
3595*820c1a8dSHiroo HAYASHI }
3596*820c1a8dSHiroo HAYASHI mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name);
3597*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
3598*820c1a8dSHiroo HAYASHI
3599*820c1a8dSHiroo HAYASHI #define BUILD_CHARCLASS_LOOP(ctype_func) \
3600*820c1a8dSHiroo HAYASHI do { \
3601*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (trans != NULL)) \
3602*820c1a8dSHiroo HAYASHI { \
3603*820c1a8dSHiroo HAYASHI for (i = 0; i < SBC_MAX; ++i) \
3604*820c1a8dSHiroo HAYASHI if (ctype_func (i)) \
3605*820c1a8dSHiroo HAYASHI bitset_set (sbcset, trans[i]); \
3606*820c1a8dSHiroo HAYASHI } \
3607*820c1a8dSHiroo HAYASHI else \
3608*820c1a8dSHiroo HAYASHI { \
3609*820c1a8dSHiroo HAYASHI for (i = 0; i < SBC_MAX; ++i) \
3610*820c1a8dSHiroo HAYASHI if (ctype_func (i)) \
3611*820c1a8dSHiroo HAYASHI bitset_set (sbcset, i); \
3612*820c1a8dSHiroo HAYASHI } \
3613*820c1a8dSHiroo HAYASHI } while (0)
3614*820c1a8dSHiroo HAYASHI
3615*820c1a8dSHiroo HAYASHI if (strcmp (name, "alnum") == 0)
3616*820c1a8dSHiroo HAYASHI BUILD_CHARCLASS_LOOP (isalnum);
3617*820c1a8dSHiroo HAYASHI else if (strcmp (name, "cntrl") == 0)
3618*820c1a8dSHiroo HAYASHI BUILD_CHARCLASS_LOOP (iscntrl);
3619*820c1a8dSHiroo HAYASHI else if (strcmp (name, "lower") == 0)
3620*820c1a8dSHiroo HAYASHI BUILD_CHARCLASS_LOOP (islower);
3621*820c1a8dSHiroo HAYASHI else if (strcmp (name, "space") == 0)
3622*820c1a8dSHiroo HAYASHI BUILD_CHARCLASS_LOOP (isspace);
3623*820c1a8dSHiroo HAYASHI else if (strcmp (name, "alpha") == 0)
3624*820c1a8dSHiroo HAYASHI BUILD_CHARCLASS_LOOP (isalpha);
3625*820c1a8dSHiroo HAYASHI else if (strcmp (name, "digit") == 0)
3626*820c1a8dSHiroo HAYASHI BUILD_CHARCLASS_LOOP (isdigit);
3627*820c1a8dSHiroo HAYASHI else if (strcmp (name, "print") == 0)
3628*820c1a8dSHiroo HAYASHI BUILD_CHARCLASS_LOOP (isprint);
3629*820c1a8dSHiroo HAYASHI else if (strcmp (name, "upper") == 0)
3630*820c1a8dSHiroo HAYASHI BUILD_CHARCLASS_LOOP (isupper);
3631*820c1a8dSHiroo HAYASHI else if (strcmp (name, "blank") == 0)
3632*820c1a8dSHiroo HAYASHI BUILD_CHARCLASS_LOOP (isblank);
3633*820c1a8dSHiroo HAYASHI else if (strcmp (name, "graph") == 0)
3634*820c1a8dSHiroo HAYASHI BUILD_CHARCLASS_LOOP (isgraph);
3635*820c1a8dSHiroo HAYASHI else if (strcmp (name, "punct") == 0)
3636*820c1a8dSHiroo HAYASHI BUILD_CHARCLASS_LOOP (ispunct);
3637*820c1a8dSHiroo HAYASHI else if (strcmp (name, "xdigit") == 0)
3638*820c1a8dSHiroo HAYASHI BUILD_CHARCLASS_LOOP (isxdigit);
3639*820c1a8dSHiroo HAYASHI else
3640*820c1a8dSHiroo HAYASHI return REG_ECTYPE;
3641*820c1a8dSHiroo HAYASHI
3642*820c1a8dSHiroo HAYASHI return REG_NOERROR;
3643*820c1a8dSHiroo HAYASHI }
3644*820c1a8dSHiroo HAYASHI
3645*820c1a8dSHiroo HAYASHI static bin_tree_t *
build_charclass_op(re_dfa_t * dfa,RE_TRANSLATE_TYPE trans,const char * class_name,const char * extra,bool non_match,reg_errcode_t * err)3646*820c1a8dSHiroo HAYASHI build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,
3647*820c1a8dSHiroo HAYASHI const char *class_name,
3648*820c1a8dSHiroo HAYASHI const char *extra, bool non_match,
3649*820c1a8dSHiroo HAYASHI reg_errcode_t *err)
3650*820c1a8dSHiroo HAYASHI {
3651*820c1a8dSHiroo HAYASHI re_bitset_ptr_t sbcset;
3652*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3653*820c1a8dSHiroo HAYASHI re_charset_t *mbcset;
3654*820c1a8dSHiroo HAYASHI Idx alloc = 0;
3655*820c1a8dSHiroo HAYASHI #endif /* not RE_ENABLE_I18N */
3656*820c1a8dSHiroo HAYASHI reg_errcode_t ret;
3657*820c1a8dSHiroo HAYASHI bin_tree_t *tree;
3658*820c1a8dSHiroo HAYASHI
3659*820c1a8dSHiroo HAYASHI sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);
3660*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (sbcset == NULL))
3661*820c1a8dSHiroo HAYASHI {
3662*820c1a8dSHiroo HAYASHI *err = REG_ESPACE;
3663*820c1a8dSHiroo HAYASHI return NULL;
3664*820c1a8dSHiroo HAYASHI }
3665*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3666*820c1a8dSHiroo HAYASHI mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);
3667*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (mbcset == NULL))
3668*820c1a8dSHiroo HAYASHI {
3669*820c1a8dSHiroo HAYASHI re_free (sbcset);
3670*820c1a8dSHiroo HAYASHI *err = REG_ESPACE;
3671*820c1a8dSHiroo HAYASHI return NULL;
3672*820c1a8dSHiroo HAYASHI }
3673*820c1a8dSHiroo HAYASHI mbcset->non_match = non_match;
3674*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
3675*820c1a8dSHiroo HAYASHI
3676*820c1a8dSHiroo HAYASHI /* We don't care the syntax in this case. */
3677*820c1a8dSHiroo HAYASHI ret = build_charclass (trans, sbcset,
3678*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3679*820c1a8dSHiroo HAYASHI mbcset, &alloc,
3680*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
3681*820c1a8dSHiroo HAYASHI class_name, 0);
3682*820c1a8dSHiroo HAYASHI
3683*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (ret != REG_NOERROR))
3684*820c1a8dSHiroo HAYASHI {
3685*820c1a8dSHiroo HAYASHI re_free (sbcset);
3686*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3687*820c1a8dSHiroo HAYASHI free_charset (mbcset);
3688*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
3689*820c1a8dSHiroo HAYASHI *err = ret;
3690*820c1a8dSHiroo HAYASHI return NULL;
3691*820c1a8dSHiroo HAYASHI }
3692*820c1a8dSHiroo HAYASHI /* \w match '_' also. */
3693*820c1a8dSHiroo HAYASHI for (; *extra; extra++)
3694*820c1a8dSHiroo HAYASHI bitset_set (sbcset, *extra);
3695*820c1a8dSHiroo HAYASHI
3696*820c1a8dSHiroo HAYASHI /* If it is non-matching list. */
3697*820c1a8dSHiroo HAYASHI if (non_match)
3698*820c1a8dSHiroo HAYASHI bitset_not (sbcset);
3699*820c1a8dSHiroo HAYASHI
3700*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3701*820c1a8dSHiroo HAYASHI /* Ensure only single byte characters are set. */
3702*820c1a8dSHiroo HAYASHI if (dfa->mb_cur_max > 1)
3703*820c1a8dSHiroo HAYASHI bitset_mask (sbcset, dfa->sb_char);
3704*820c1a8dSHiroo HAYASHI #endif
3705*820c1a8dSHiroo HAYASHI
3706*820c1a8dSHiroo HAYASHI /* Build a tree for simple bracket. */
3707*820c1a8dSHiroo HAYASHI re_token_t br_token = { .type = SIMPLE_BRACKET, .opr.sbcset = sbcset };
3708*820c1a8dSHiroo HAYASHI tree = create_token_tree (dfa, NULL, NULL, &br_token);
3709*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (tree == NULL))
3710*820c1a8dSHiroo HAYASHI goto build_word_op_espace;
3711*820c1a8dSHiroo HAYASHI
3712*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3713*820c1a8dSHiroo HAYASHI if (dfa->mb_cur_max > 1)
3714*820c1a8dSHiroo HAYASHI {
3715*820c1a8dSHiroo HAYASHI bin_tree_t *mbc_tree;
3716*820c1a8dSHiroo HAYASHI /* Build a tree for complex bracket. */
3717*820c1a8dSHiroo HAYASHI br_token.type = COMPLEX_BRACKET;
3718*820c1a8dSHiroo HAYASHI br_token.opr.mbcset = mbcset;
3719*820c1a8dSHiroo HAYASHI dfa->has_mb_node = 1;
3720*820c1a8dSHiroo HAYASHI mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);
3721*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (mbc_tree == NULL))
3722*820c1a8dSHiroo HAYASHI goto build_word_op_espace;
3723*820c1a8dSHiroo HAYASHI /* Then join them by ALT node. */
3724*820c1a8dSHiroo HAYASHI tree = create_tree (dfa, tree, mbc_tree, OP_ALT);
3725*820c1a8dSHiroo HAYASHI if (__glibc_likely (mbc_tree != NULL))
3726*820c1a8dSHiroo HAYASHI return tree;
3727*820c1a8dSHiroo HAYASHI }
3728*820c1a8dSHiroo HAYASHI else
3729*820c1a8dSHiroo HAYASHI {
3730*820c1a8dSHiroo HAYASHI free_charset (mbcset);
3731*820c1a8dSHiroo HAYASHI return tree;
3732*820c1a8dSHiroo HAYASHI }
3733*820c1a8dSHiroo HAYASHI #else /* not RE_ENABLE_I18N */
3734*820c1a8dSHiroo HAYASHI return tree;
3735*820c1a8dSHiroo HAYASHI #endif /* not RE_ENABLE_I18N */
3736*820c1a8dSHiroo HAYASHI
3737*820c1a8dSHiroo HAYASHI build_word_op_espace:
3738*820c1a8dSHiroo HAYASHI re_free (sbcset);
3739*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3740*820c1a8dSHiroo HAYASHI free_charset (mbcset);
3741*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
3742*820c1a8dSHiroo HAYASHI *err = REG_ESPACE;
3743*820c1a8dSHiroo HAYASHI return NULL;
3744*820c1a8dSHiroo HAYASHI }
3745*820c1a8dSHiroo HAYASHI
3746*820c1a8dSHiroo HAYASHI /* This is intended for the expressions like "a{1,3}".
3747*820c1a8dSHiroo HAYASHI Fetch a number from 'input', and return the number.
3748*820c1a8dSHiroo HAYASHI Return -1 if the number field is empty like "{,1}".
3749*820c1a8dSHiroo HAYASHI Return RE_DUP_MAX + 1 if the number field is too large.
3750*820c1a8dSHiroo HAYASHI Return -2 if an error occurred. */
3751*820c1a8dSHiroo HAYASHI
3752*820c1a8dSHiroo HAYASHI static Idx
fetch_number(re_string_t * input,re_token_t * token,reg_syntax_t syntax)3753*820c1a8dSHiroo HAYASHI fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax)
3754*820c1a8dSHiroo HAYASHI {
3755*820c1a8dSHiroo HAYASHI Idx num = -1;
3756*820c1a8dSHiroo HAYASHI unsigned char c;
3757*820c1a8dSHiroo HAYASHI while (1)
3758*820c1a8dSHiroo HAYASHI {
3759*820c1a8dSHiroo HAYASHI fetch_token (token, input, syntax);
3760*820c1a8dSHiroo HAYASHI c = token->opr.c;
3761*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (token->type == END_OF_RE))
3762*820c1a8dSHiroo HAYASHI return -2;
3763*820c1a8dSHiroo HAYASHI if (token->type == OP_CLOSE_DUP_NUM || c == ',')
3764*820c1a8dSHiroo HAYASHI break;
3765*820c1a8dSHiroo HAYASHI num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2)
3766*820c1a8dSHiroo HAYASHI ? -2
3767*820c1a8dSHiroo HAYASHI : num == -1
3768*820c1a8dSHiroo HAYASHI ? c - '0'
3769*820c1a8dSHiroo HAYASHI : MIN (RE_DUP_MAX + 1, num * 10 + c - '0'));
3770*820c1a8dSHiroo HAYASHI }
3771*820c1a8dSHiroo HAYASHI return num;
3772*820c1a8dSHiroo HAYASHI }
3773*820c1a8dSHiroo HAYASHI
3774*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3775*820c1a8dSHiroo HAYASHI static void
free_charset(re_charset_t * cset)3776*820c1a8dSHiroo HAYASHI free_charset (re_charset_t *cset)
3777*820c1a8dSHiroo HAYASHI {
3778*820c1a8dSHiroo HAYASHI re_free (cset->mbchars);
3779*820c1a8dSHiroo HAYASHI # ifdef _LIBC
3780*820c1a8dSHiroo HAYASHI re_free (cset->coll_syms);
3781*820c1a8dSHiroo HAYASHI re_free (cset->equiv_classes);
3782*820c1a8dSHiroo HAYASHI # endif
3783*820c1a8dSHiroo HAYASHI re_free (cset->range_starts);
3784*820c1a8dSHiroo HAYASHI re_free (cset->range_ends);
3785*820c1a8dSHiroo HAYASHI re_free (cset->char_classes);
3786*820c1a8dSHiroo HAYASHI re_free (cset);
3787*820c1a8dSHiroo HAYASHI }
3788*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
3789*820c1a8dSHiroo HAYASHI
3790*820c1a8dSHiroo HAYASHI /* Functions for binary tree operation. */
3791*820c1a8dSHiroo HAYASHI
3792*820c1a8dSHiroo HAYASHI /* Create a tree node. */
3793*820c1a8dSHiroo HAYASHI
3794*820c1a8dSHiroo HAYASHI static bin_tree_t *
create_tree(re_dfa_t * dfa,bin_tree_t * left,bin_tree_t * right,re_token_type_t type)3795*820c1a8dSHiroo HAYASHI create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
3796*820c1a8dSHiroo HAYASHI re_token_type_t type)
3797*820c1a8dSHiroo HAYASHI {
3798*820c1a8dSHiroo HAYASHI re_token_t t = { .type = type };
3799*820c1a8dSHiroo HAYASHI return create_token_tree (dfa, left, right, &t);
3800*820c1a8dSHiroo HAYASHI }
3801*820c1a8dSHiroo HAYASHI
3802*820c1a8dSHiroo HAYASHI static bin_tree_t *
create_token_tree(re_dfa_t * dfa,bin_tree_t * left,bin_tree_t * right,const re_token_t * token)3803*820c1a8dSHiroo HAYASHI create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,
3804*820c1a8dSHiroo HAYASHI const re_token_t *token)
3805*820c1a8dSHiroo HAYASHI {
3806*820c1a8dSHiroo HAYASHI bin_tree_t *tree;
3807*820c1a8dSHiroo HAYASHI if (__glibc_unlikely (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE))
3808*820c1a8dSHiroo HAYASHI {
3809*820c1a8dSHiroo HAYASHI bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1);
3810*820c1a8dSHiroo HAYASHI
3811*820c1a8dSHiroo HAYASHI if (storage == NULL)
3812*820c1a8dSHiroo HAYASHI return NULL;
3813*820c1a8dSHiroo HAYASHI storage->next = dfa->str_tree_storage;
3814*820c1a8dSHiroo HAYASHI dfa->str_tree_storage = storage;
3815*820c1a8dSHiroo HAYASHI dfa->str_tree_storage_idx = 0;
3816*820c1a8dSHiroo HAYASHI }
3817*820c1a8dSHiroo HAYASHI tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++];
3818*820c1a8dSHiroo HAYASHI
3819*820c1a8dSHiroo HAYASHI tree->parent = NULL;
3820*820c1a8dSHiroo HAYASHI tree->left = left;
3821*820c1a8dSHiroo HAYASHI tree->right = right;
3822*820c1a8dSHiroo HAYASHI tree->token = *token;
3823*820c1a8dSHiroo HAYASHI tree->token.duplicated = 0;
3824*820c1a8dSHiroo HAYASHI tree->token.opt_subexp = 0;
3825*820c1a8dSHiroo HAYASHI tree->first = NULL;
3826*820c1a8dSHiroo HAYASHI tree->next = NULL;
3827*820c1a8dSHiroo HAYASHI tree->node_idx = -1;
3828*820c1a8dSHiroo HAYASHI
3829*820c1a8dSHiroo HAYASHI if (left != NULL)
3830*820c1a8dSHiroo HAYASHI left->parent = tree;
3831*820c1a8dSHiroo HAYASHI if (right != NULL)
3832*820c1a8dSHiroo HAYASHI right->parent = tree;
3833*820c1a8dSHiroo HAYASHI return tree;
3834*820c1a8dSHiroo HAYASHI }
3835*820c1a8dSHiroo HAYASHI
3836*820c1a8dSHiroo HAYASHI /* Mark the tree SRC as an optional subexpression.
3837*820c1a8dSHiroo HAYASHI To be called from preorder or postorder. */
3838*820c1a8dSHiroo HAYASHI
3839*820c1a8dSHiroo HAYASHI static reg_errcode_t
mark_opt_subexp(void * extra,bin_tree_t * node)3840*820c1a8dSHiroo HAYASHI mark_opt_subexp (void *extra, bin_tree_t *node)
3841*820c1a8dSHiroo HAYASHI {
3842*820c1a8dSHiroo HAYASHI Idx idx = (uintptr_t) extra;
3843*820c1a8dSHiroo HAYASHI if (node->token.type == SUBEXP && node->token.opr.idx == idx)
3844*820c1a8dSHiroo HAYASHI node->token.opt_subexp = 1;
3845*820c1a8dSHiroo HAYASHI
3846*820c1a8dSHiroo HAYASHI return REG_NOERROR;
3847*820c1a8dSHiroo HAYASHI }
3848*820c1a8dSHiroo HAYASHI
3849*820c1a8dSHiroo HAYASHI /* Free the allocated memory inside NODE. */
3850*820c1a8dSHiroo HAYASHI
3851*820c1a8dSHiroo HAYASHI static void
free_token(re_token_t * node)3852*820c1a8dSHiroo HAYASHI free_token (re_token_t *node)
3853*820c1a8dSHiroo HAYASHI {
3854*820c1a8dSHiroo HAYASHI #ifdef RE_ENABLE_I18N
3855*820c1a8dSHiroo HAYASHI if (node->type == COMPLEX_BRACKET && node->duplicated == 0)
3856*820c1a8dSHiroo HAYASHI free_charset (node->opr.mbcset);
3857*820c1a8dSHiroo HAYASHI else
3858*820c1a8dSHiroo HAYASHI #endif /* RE_ENABLE_I18N */
3859*820c1a8dSHiroo HAYASHI if (node->type == SIMPLE_BRACKET && node->duplicated == 0)
3860*820c1a8dSHiroo HAYASHI re_free (node->opr.sbcset);
3861*820c1a8dSHiroo HAYASHI }
3862*820c1a8dSHiroo HAYASHI
3863*820c1a8dSHiroo HAYASHI /* Worker function for tree walking. Free the allocated memory inside NODE
3864*820c1a8dSHiroo HAYASHI and its children. */
3865*820c1a8dSHiroo HAYASHI
3866*820c1a8dSHiroo HAYASHI static reg_errcode_t
free_tree(void * extra,bin_tree_t * node)3867*820c1a8dSHiroo HAYASHI free_tree (void *extra, bin_tree_t *node)
3868*820c1a8dSHiroo HAYASHI {
3869*820c1a8dSHiroo HAYASHI free_token (&node->token);
3870*820c1a8dSHiroo HAYASHI return REG_NOERROR;
3871*820c1a8dSHiroo HAYASHI }
3872*820c1a8dSHiroo HAYASHI
3873*820c1a8dSHiroo HAYASHI
3874*820c1a8dSHiroo HAYASHI /* Duplicate the node SRC, and return new node. This is a preorder
3875*820c1a8dSHiroo HAYASHI visit similar to the one implemented by the generic visitor, but
3876*820c1a8dSHiroo HAYASHI we need more infrastructure to maintain two parallel trees --- so,
3877*820c1a8dSHiroo HAYASHI it's easier to duplicate. */
3878*820c1a8dSHiroo HAYASHI
3879*820c1a8dSHiroo HAYASHI static bin_tree_t *
duplicate_tree(const bin_tree_t * root,re_dfa_t * dfa)3880*820c1a8dSHiroo HAYASHI duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa)
3881*820c1a8dSHiroo HAYASHI {
3882*820c1a8dSHiroo HAYASHI const bin_tree_t *node;
3883*820c1a8dSHiroo HAYASHI bin_tree_t *dup_root;
3884*820c1a8dSHiroo HAYASHI bin_tree_t **p_new = &dup_root, *dup_node = root->parent;
3885*820c1a8dSHiroo HAYASHI
3886*820c1a8dSHiroo HAYASHI for (node = root; ; )
3887*820c1a8dSHiroo HAYASHI {
3888*820c1a8dSHiroo HAYASHI /* Create a new tree and link it back to the current parent. */
3889*820c1a8dSHiroo HAYASHI *p_new = create_token_tree (dfa, NULL, NULL, &node->token);
3890*820c1a8dSHiroo HAYASHI if (*p_new == NULL)
3891*820c1a8dSHiroo HAYASHI return NULL;
3892*820c1a8dSHiroo HAYASHI (*p_new)->parent = dup_node;
3893*820c1a8dSHiroo HAYASHI (*p_new)->token.duplicated = 1;
3894*820c1a8dSHiroo HAYASHI dup_node = *p_new;
3895*820c1a8dSHiroo HAYASHI
3896*820c1a8dSHiroo HAYASHI /* Go to the left node, or up and to the right. */
3897*820c1a8dSHiroo HAYASHI if (node->left)
3898*820c1a8dSHiroo HAYASHI {
3899*820c1a8dSHiroo HAYASHI node = node->left;
3900*820c1a8dSHiroo HAYASHI p_new = &dup_node->left;
3901*820c1a8dSHiroo HAYASHI }
3902*820c1a8dSHiroo HAYASHI else
3903*820c1a8dSHiroo HAYASHI {
3904*820c1a8dSHiroo HAYASHI const bin_tree_t *prev = NULL;
3905*820c1a8dSHiroo HAYASHI while (node->right == prev || node->right == NULL)
3906*820c1a8dSHiroo HAYASHI {
3907*820c1a8dSHiroo HAYASHI prev = node;
3908*820c1a8dSHiroo HAYASHI node = node->parent;
3909*820c1a8dSHiroo HAYASHI dup_node = dup_node->parent;
3910*820c1a8dSHiroo HAYASHI if (!node)
3911*820c1a8dSHiroo HAYASHI return dup_root;
3912*820c1a8dSHiroo HAYASHI }
3913*820c1a8dSHiroo HAYASHI node = node->right;
3914*820c1a8dSHiroo HAYASHI p_new = &dup_node->right;
3915*820c1a8dSHiroo HAYASHI }
3916*820c1a8dSHiroo HAYASHI }
3917*820c1a8dSHiroo HAYASHI }
3918