xref: /Universal-ctags/gnulib/regcomp.c (revision 820c1a8d46849a90376d8eb15b319ac05439f656)
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 (&regexp, 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 (&regexp);
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 (&regexp, 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 (&regexp);
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 (&current_token, regexp, syntax | RE_CARET_ANCHORS_HERE);
2125*820c1a8dSHiroo HAYASHI   tree = parse_reg_exp (regexp, preg, &current_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