packages feed

regex-posix-clib (empty) → 2.7

raw patch · 9 files changed

+11819/−0 lines, 9 files

Files

+ LICENSE view
@@ -0,0 +1,502 @@+                  GNU LESSER GENERAL PUBLIC LICENSE+                       Version 2.1, February 1999++ Copyright (C) 1991, 1999 Free Software Foundation, Inc.+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA+ Everyone is permitted to copy and distribute verbatim copies+ of this license document, but changing it is not allowed.++[This is the first released version of the Lesser GPL.  It also counts+ as the successor of the GNU Library Public License, version 2, hence+ the version number 2.1.]++                            Preamble++  The licenses for most software are designed to take away your+freedom to share and change it.  By contrast, the GNU General Public+Licenses are intended to guarantee your freedom to share and change+free software--to make sure the software is free for all its users.++  This license, the Lesser General Public License, applies to some+specially designated software packages--typically libraries--of the+Free Software Foundation and other authors who decide to use it.  You+can use it too, but we suggest you first think carefully about whether+this license or the ordinary General Public License is the better+strategy to use in any particular case, based on the explanations below.++  When we speak of free software, we are referring to freedom of use,+not price.  Our General Public Licenses are designed to make sure that+you have the freedom to distribute copies of free software (and charge+for this service if you wish); that you receive source code or can get+it if you want it; that you can change the software and use pieces of+it in new free programs; and that you are informed that you can do+these things.++  To protect your rights, we need to make restrictions that forbid+distributors to deny you these rights or to ask you to surrender these+rights.  These restrictions translate to certain responsibilities for+you if you distribute copies of the library or if you modify it.++  For example, if you distribute copies of the library, whether gratis+or for a fee, you must give the recipients all the rights that we gave+you.  You must make sure that they, too, receive or can get the source+code.  If you link other code with the library, you must provide+complete object files to the recipients, so that they can relink them+with the library after making changes to the library and recompiling+it.  And you must show them these terms so they know their rights.++  We protect your rights with a two-step method: (1) we copyright the+library, and (2) we offer you this license, which gives you legal+permission to copy, distribute and/or modify the library.++  To protect each distributor, we want to make it very clear that+there is no warranty for the free library.  Also, if the library is+modified by someone else and passed on, the recipients should know+that what they have is not the original version, so that the original+author's reputation will not be affected by problems that might be+introduced by others.++  Finally, software patents pose a constant threat to the existence of+any free program.  We wish to make sure that a company cannot+effectively restrict the users of a free program by obtaining a+restrictive license from a patent holder.  Therefore, we insist that+any patent license obtained for a version of the library must be+consistent with the full freedom of use specified in this license.++  Most GNU software, including some libraries, is covered by the+ordinary GNU General Public License.  This license, the GNU Lesser+General Public License, applies to certain designated libraries, and+is quite different from the ordinary General Public License.  We use+this license for certain libraries in order to permit linking those+libraries into non-free programs.++  When a program is linked with a library, whether statically or using+a shared library, the combination of the two is legally speaking a+combined work, a derivative of the original library.  The ordinary+General Public License therefore permits such linking only if the+entire combination fits its criteria of freedom.  The Lesser General+Public License permits more lax criteria for linking other code with+the library.++  We call this license the "Lesser" General Public License because it+does Less to protect the user's freedom than the ordinary General+Public License.  It also provides other free software developers Less+of an advantage over competing non-free programs.  These disadvantages+are the reason we use the ordinary General Public License for many+libraries.  However, the Lesser license provides advantages in certain+special circumstances.++  For example, on rare occasions, there may be a special need to+encourage the widest possible use of a certain library, so that it becomes+a de-facto standard.  To achieve this, non-free programs must be+allowed to use the library.  A more frequent case is that a free+library does the same job as widely used non-free libraries.  In this+case, there is little to gain by limiting the free library to free+software only, so we use the Lesser General Public License.++  In other cases, permission to use a particular library in non-free+programs enables a greater number of people to use a large body of+free software.  For example, permission to use the GNU C Library in+non-free programs enables many more people to use the whole GNU+operating system, as well as its variant, the GNU/Linux operating+system.++  Although the Lesser General Public License is Less protective of the+users' freedom, it does ensure that the user of a program that is+linked with the Library has the freedom and the wherewithal to run+that program using a modified version of the Library.++  The precise terms and conditions for copying, distribution and+modification follow.  Pay close attention to the difference between a+"work based on the library" and a "work that uses the library".  The+former contains code derived from the library, whereas the latter must+be combined with the library in order to run.++                  GNU LESSER GENERAL PUBLIC LICENSE+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION++  0. This License Agreement applies to any software library or other+program which contains a notice placed by the copyright holder or+other authorized party saying it may be distributed under the terms of+this Lesser General Public License (also called "this License").+Each licensee is addressed as "you".++  A "library" means a collection of software functions and/or data+prepared so as to be conveniently linked with application programs+(which use some of those functions and data) to form executables.++  The "Library", below, refers to any such software library or work+which has been distributed under these terms.  A "work based on the+Library" means either the Library or any derivative work under+copyright law: that is to say, a work containing the Library or a+portion of it, either verbatim or with modifications and/or translated+straightforwardly into another language.  (Hereinafter, translation is+included without limitation in the term "modification".)++  "Source code" for a work means the preferred form of the work for+making modifications to it.  For a library, complete source code means+all the source code for all modules it contains, plus any associated+interface definition files, plus the scripts used to control compilation+and installation of the library.++  Activities other than copying, distribution and modification are not+covered by this License; they are outside its scope.  The act of+running a program using the Library is not restricted, and output from+such a program is covered only if its contents constitute a work based+on the Library (independent of the use of the Library in a tool for+writing it).  Whether that is true depends on what the Library does+and what the program that uses the Library does.++  1. You may copy and distribute verbatim copies of the Library's+complete source code as you receive it, in any medium, provided that+you conspicuously and appropriately publish on each copy an+appropriate copyright notice and disclaimer of warranty; keep intact+all the notices that refer to this License and to the absence of any+warranty; and distribute a copy of this License along with the+Library.++  You may charge a fee for the physical act of transferring a copy,+and you may at your option offer warranty protection in exchange for a+fee.++  2. You may modify your copy or copies of the Library or any portion+of it, thus forming a work based on the Library, and copy and+distribute such modifications or work under the terms of Section 1+above, provided that you also meet all of these conditions:++    a) The modified work must itself be a software library.++    b) You must cause the files modified to carry prominent notices+    stating that you changed the files and the date of any change.++    c) You must cause the whole of the work to be licensed at no+    charge to all third parties under the terms of this License.++    d) If a facility in the modified Library refers to a function or a+    table of data to be supplied by an application program that uses+    the facility, other than as an argument passed when the facility+    is invoked, then you must make a good faith effort to ensure that,+    in the event an application does not supply such function or+    table, the facility still operates, and performs whatever part of+    its purpose remains meaningful.++    (For example, a function in a library to compute square roots has+    a purpose that is entirely well-defined independent of the+    application.  Therefore, Subsection 2d requires that any+    application-supplied function or table used by this function must+    be optional: if the application does not supply it, the square+    root function must still compute square roots.)++These requirements apply to the modified work as a whole.  If+identifiable sections of that work are not derived from the Library,+and can be reasonably considered independent and separate works in+themselves, then this License, and its terms, do not apply to those+sections when you distribute them as separate works.  But when you+distribute the same sections as part of a whole which is a work based+on the Library, the distribution of the whole must be on the terms of+this License, whose permissions for other licensees extend to the+entire whole, and thus to each and every part regardless of who wrote+it.++Thus, it is not the intent of this section to claim rights or contest+your rights to work written entirely by you; rather, the intent is to+exercise the right to control the distribution of derivative or+collective works based on the Library.++In addition, mere aggregation of another work not based on the Library+with the Library (or with a work based on the Library) on a volume of+a storage or distribution medium does not bring the other work under+the scope of this License.++  3. You may opt to apply the terms of the ordinary GNU General Public+License instead of this License to a given copy of the Library.  To do+this, you must alter all the notices that refer to this License, so+that they refer to the ordinary GNU General Public License, version 2,+instead of to this License.  (If a newer version than version 2 of the+ordinary GNU General Public License has appeared, then you can specify+that version instead if you wish.)  Do not make any other change in+these notices.++  Once this change is made in a given copy, it is irreversible for+that copy, so the ordinary GNU General Public License applies to all+subsequent copies and derivative works made from that copy.++  This option is useful when you wish to copy part of the code of+the Library into a program that is not a library.++  4. You may copy and distribute the Library (or a portion or+derivative of it, under Section 2) in object code or executable form+under the terms of Sections 1 and 2 above provided that you accompany+it with the complete corresponding machine-readable source code, which+must be distributed under the terms of Sections 1 and 2 above on a+medium customarily used for software interchange.++  If distribution of object code is made by offering access to copy+from a designated place, then offering equivalent access to copy the+source code from the same place satisfies the requirement to+distribute the source code, even though third parties are not+compelled to copy the source along with the object code.++  5. A program that contains no derivative of any portion of the+Library, but is designed to work with the Library by being compiled or+linked with it, is called a "work that uses the Library".  Such a+work, in isolation, is not a derivative work of the Library, and+therefore falls outside the scope of this License.++  However, linking a "work that uses the Library" with the Library+creates an executable that is a derivative of the Library (because it+contains portions of the Library), rather than a "work that uses the+library".  The executable is therefore covered by this License.+Section 6 states terms for distribution of such executables.++  When a "work that uses the Library" uses material from a header file+that is part of the Library, the object code for the work may be a+derivative work of the Library even though the source code is not.+Whether this is true is especially significant if the work can be+linked without the Library, or if the work is itself a library.  The+threshold for this to be true is not precisely defined by law.++  If such an object file uses only numerical parameters, data+structure layouts and accessors, and small macros and small inline+functions (ten lines or less in length), then the use of the object+file is unrestricted, regardless of whether it is legally a derivative+work.  (Executables containing this object code plus portions of the+Library will still fall under Section 6.)++  Otherwise, if the work is a derivative of the Library, you may+distribute the object code for the work under the terms of Section 6.+Any executables containing that work also fall under Section 6,+whether or not they are linked directly with the Library itself.++  6. As an exception to the Sections above, you may also combine or+link a "work that uses the Library" with the Library to produce a+work containing portions of the Library, and distribute that work+under terms of your choice, provided that the terms permit+modification of the work for the customer's own use and reverse+engineering for debugging such modifications.++  You must give prominent notice with each copy of the work that the+Library is used in it and that the Library and its use are covered by+this License.  You must supply a copy of this License.  If the work+during execution displays copyright notices, you must include the+copyright notice for the Library among them, as well as a reference+directing the user to the copy of this License.  Also, you must do one+of these things:++    a) Accompany the work with the complete corresponding+    machine-readable source code for the Library including whatever+    changes were used in the work (which must be distributed under+    Sections 1 and 2 above); and, if the work is an executable linked+    with the Library, with the complete machine-readable "work that+    uses the Library", as object code and/or source code, so that the+    user can modify the Library and then relink to produce a modified+    executable containing the modified Library.  (It is understood+    that the user who changes the contents of definitions files in the+    Library will not necessarily be able to recompile the application+    to use the modified definitions.)++    b) Use a suitable shared library mechanism for linking with the+    Library.  A suitable mechanism is one that (1) uses at run time a+    copy of the library already present on the user's computer system,+    rather than copying library functions into the executable, and (2)+    will operate properly with a modified version of the library, if+    the user installs one, as long as the modified version is+    interface-compatible with the version that the work was made with.++    c) Accompany the work with a written offer, valid for at+    least three years, to give the same user the materials+    specified in Subsection 6a, above, for a charge no more+    than the cost of performing this distribution.++    d) If distribution of the work is made by offering access to copy+    from a designated place, offer equivalent access to copy the above+    specified materials from the same place.++    e) Verify that the user has already received a copy of these+    materials or that you have already sent this user a copy.++  For an executable, the required form of the "work that uses the+Library" must include any data and utility programs needed for+reproducing the executable from it.  However, as a special exception,+the materials to be distributed need not include anything that is+normally distributed (in either source or binary form) with the major+components (compiler, kernel, and so on) of the operating system on+which the executable runs, unless that component itself accompanies+the executable.++  It may happen that this requirement contradicts the license+restrictions of other proprietary libraries that do not normally+accompany the operating system.  Such a contradiction means you cannot+use both them and the Library together in an executable that you+distribute.++  7. You may place library facilities that are a work based on the+Library side-by-side in a single library together with other library+facilities not covered by this License, and distribute such a combined+library, provided that the separate distribution of the work based on+the Library and of the other library facilities is otherwise+permitted, and provided that you do these two things:++    a) Accompany the combined library with a copy of the same work+    based on the Library, uncombined with any other library+    facilities.  This must be distributed under the terms of the+    Sections above.++    b) Give prominent notice with the combined library of the fact+    that part of it is a work based on the Library, and explaining+    where to find the accompanying uncombined form of the same work.++  8. You may not copy, modify, sublicense, link with, or distribute+the Library except as expressly provided under this License.  Any+attempt otherwise to copy, modify, sublicense, link with, or+distribute the Library is void, and will automatically terminate your+rights under this License.  However, parties who have received copies,+or rights, from you under this License will not have their licenses+terminated so long as such parties remain in full compliance.++  9. You are not required to accept this License, since you have not+signed it.  However, nothing else grants you permission to modify or+distribute the Library or its derivative works.  These actions are+prohibited by law if you do not accept this License.  Therefore, by+modifying or distributing the Library (or any work based on the+Library), you indicate your acceptance of this License to do so, and+all its terms and conditions for copying, distributing or modifying+the Library or works based on it.++  10. Each time you redistribute the Library (or any work based on the+Library), the recipient automatically receives a license from the+original licensor to copy, distribute, link with or modify the Library+subject to these terms and conditions.  You may not impose any further+restrictions on the recipients' exercise of the rights granted herein.+You are not responsible for enforcing compliance by third parties with+this License.++  11. If, as a consequence of a court judgment or allegation of patent+infringement or for any other reason (not limited to patent issues),+conditions are imposed on you (whether by court order, agreement or+otherwise) that contradict the conditions of this License, they do not+excuse you from the conditions of this License.  If you cannot+distribute so as to satisfy simultaneously your obligations under this+License and any other pertinent obligations, then as a consequence you+may not distribute the Library at all.  For example, if a patent+license would not permit royalty-free redistribution of the Library by+all those who receive copies directly or indirectly through you, then+the only way you could satisfy both it and this License would be to+refrain entirely from distribution of the Library.++If any portion of this section is held invalid or unenforceable under any+particular circumstance, the balance of the section is intended to apply,+and the section as a whole is intended to apply in other circumstances.++It is not the purpose of this section to induce you to infringe any+patents or other property right claims or to contest validity of any+such claims; this section has the sole purpose of protecting the+integrity of the free software distribution system which is+implemented by public license practices.  Many people have made+generous contributions to the wide range of software distributed+through that system in reliance on consistent application of that+system; it is up to the author/donor to decide if he or she is willing+to distribute software through any other system and a licensee cannot+impose that choice.++This section is intended to make thoroughly clear what is believed to+be a consequence of the rest of this License.++  12. If the distribution and/or use of the Library is restricted in+certain countries either by patents or by copyrighted interfaces, the+original copyright holder who places the Library under this License may add+an explicit geographical distribution limitation excluding those countries,+so that distribution is permitted only in or among countries not thus+excluded.  In such case, this License incorporates the limitation as if+written in the body of this License.++  13. The Free Software Foundation may publish revised and/or new+versions of the Lesser General Public License from time to time.+Such new versions will be similar in spirit to the present version,+but may differ in detail to address new problems or concerns.++Each version is given a distinguishing version number.  If the Library+specifies a version number of this License which applies to it and+"any later version", you have the option of following the terms and+conditions either of that version or of any later version published by+the Free Software Foundation.  If the Library does not specify a+license version number, you may choose any version ever published by+the Free Software Foundation.++  14. If you wish to incorporate parts of the Library into other free+programs whose distribution conditions are incompatible with these,+write to the author to ask for permission.  For software which is+copyrighted by the Free Software Foundation, write to the Free+Software Foundation; we sometimes make exceptions for this.  Our+decision will be guided by the two goals of preserving the free status+of all derivatives of our free software and of promoting the sharing+and reuse of software generally.++                            NO WARRANTY++  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.++  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH+DAMAGES.++                     END OF TERMS AND CONDITIONS++           How to Apply These Terms to Your New Libraries++  If you develop a new library, and you want it to be of the greatest+possible use to the public, we recommend making it free software that+everyone can redistribute and change.  You can do so by permitting+redistribution under these terms (or, alternatively, under the terms of the+ordinary General Public License).++  To apply these terms, attach the following notices to the library.  It is+safest to attach them to the start of each source file to most effectively+convey the exclusion of warranty; and each file should have at least the+"copyright" line and a pointer to where the full notice is found.++    <one line to give the library's name and a brief idea of what it does.>+    Copyright (C) <year>  <name of author>++    This library is free software; you can redistribute it and/or+    modify it under the terms of the GNU Lesser General Public+    License as published by the Free Software Foundation; either+    version 2.1 of the License, or (at your option) any later version.++    This library is distributed in the hope that it will be useful,+    but WITHOUT ANY WARRANTY; without even the implied warranty of+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU+    Lesser General Public License for more details.++    You should have received a copy of the GNU Lesser General Public+    License along with this library; if not, write to the Free Software+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA++Also add information on how to contact you by electronic and paper mail.++You should also get your employer (if you work as a programmer) or your+school, if any, to sign a "copyright disclaimer" for the library, if+necessary.  Here is a sample; alter the names:++  Yoyodyne, Inc., hereby disclaims all copyright interest in the+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.++  <signature of Ty Coon>, 1 April 1990+  Ty Coon, President of Vice++That's all there is to it!
+ cbits/re_comp.h view
@@ -0,0 +1,26 @@+/*  Copyright (C) 1996 Free Software Foundation, Inc.+   This file is part of the GNU C Library.++   The GNU C Library is free software; you can redistribute it and/or+   modify it under the terms of the GNU Lesser General Public+   License as published by the Free Software Foundation; either+   version 2.1 of the License, or (at your option) any later version.++   The GNU C Library is distributed in the hope that it will be useful,+   but WITHOUT ANY WARRANTY; without even the implied warranty of+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU+   Lesser General Public License for more details.++   You should have received a copy of the GNU Lesser General Public+   License along with the GNU C Library; if not, write to the Free+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA+   02111-1307 USA.  */++#ifndef _RE_COMP_H+#define _RE_COMP_H	1++/* This is only a wrapper around the <regex.h> file.  XPG4.2 mentions+   this name.  */+#include <regex.h>++#endif /* re_comp.h */
+ cbits/regcomp.c view
@@ -0,0 +1,3801 @@+/* Extended regular expression matching and search library.+   Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc.+   This file is part of the GNU C Library.+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.++   The GNU C Library is free software; you can redistribute it and/or+   modify it under the terms of the GNU Lesser General Public+   License as published by the Free Software Foundation; either+   version 2.1 of the License, or (at your option) any later version.++   The GNU C Library is distributed in the hope that it will be useful,+   but WITHOUT ANY WARRANTY; without even the implied warranty of+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU+   Lesser General Public License for more details.++   You should have received a copy of the GNU Lesser General Public+   License along with the GNU C Library; if not, write to the Free+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA+   02111-1307 USA.  */++static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern,+					  size_t length, reg_syntax_t syntax);+static void re_compile_fastmap_iter (regex_t *bufp,+				     const re_dfastate_t *init_state,+				     char *fastmap);+static reg_errcode_t init_dfa (re_dfa_t *dfa, size_t pat_len);+#ifdef RE_ENABLE_I18N+static void free_charset (re_charset_t *cset);+#endif /* RE_ENABLE_I18N */+static void free_workarea_compile (regex_t *preg);+static reg_errcode_t create_initial_state (re_dfa_t *dfa);+#ifdef RE_ENABLE_I18N+static void optimize_utf8 (re_dfa_t *dfa);+#endif+static reg_errcode_t analyze (regex_t *preg);+static reg_errcode_t preorder (bin_tree_t *root,+			       reg_errcode_t (fn (void *, bin_tree_t *)),+			       void *extra);+static reg_errcode_t postorder (bin_tree_t *root,+				reg_errcode_t (fn (void *, bin_tree_t *)),+				void *extra);+static reg_errcode_t optimize_subexps (void *extra, bin_tree_t *node);+static reg_errcode_t lower_subexps (void *extra, bin_tree_t *node);+static bin_tree_t *lower_subexp (reg_errcode_t *err, regex_t *preg,+				 bin_tree_t *node);+static reg_errcode_t calc_first (void *extra, bin_tree_t *node);+static reg_errcode_t calc_next (void *extra, bin_tree_t *node);+static reg_errcode_t link_nfa_nodes (void *extra, bin_tree_t *node);+static int duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint);+static int search_duplicated_node (const re_dfa_t *dfa, int org_node,+				   unsigned int constraint);+static reg_errcode_t calc_eclosure (re_dfa_t *dfa);+static reg_errcode_t calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa,+					 int node, int root);+static reg_errcode_t calc_inveclosure (re_dfa_t *dfa);+static int fetch_number (re_string_t *input, re_token_t *token,+			 reg_syntax_t syntax);+static int peek_token (re_token_t *token, re_string_t *input,+			reg_syntax_t syntax) internal_function;+static bin_tree_t *parse (re_string_t *regexp, regex_t *preg,+			  reg_syntax_t syntax, reg_errcode_t *err);+static bin_tree_t *parse_reg_exp (re_string_t *regexp, regex_t *preg,+				  re_token_t *token, reg_syntax_t syntax,+				  int nest, reg_errcode_t *err);+static bin_tree_t *parse_branch (re_string_t *regexp, regex_t *preg,+				 re_token_t *token, reg_syntax_t syntax,+				 int nest, reg_errcode_t *err);+static bin_tree_t *parse_expression (re_string_t *regexp, regex_t *preg,+				     re_token_t *token, reg_syntax_t syntax,+				     int nest, reg_errcode_t *err);+static bin_tree_t *parse_sub_exp (re_string_t *regexp, regex_t *preg,+				  re_token_t *token, reg_syntax_t syntax,+				  int nest, reg_errcode_t *err);+static bin_tree_t *parse_dup_op (bin_tree_t *dup_elem, re_string_t *regexp,+				 re_dfa_t *dfa, re_token_t *token,+				 reg_syntax_t syntax, reg_errcode_t *err);+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);+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,+					    int accept_hyphen);+static reg_errcode_t parse_bracket_symbol (bracket_elem_t *elem,+					  re_string_t *regexp,+					  re_token_t *token);+#ifdef RE_ENABLE_I18N+static reg_errcode_t build_equiv_class (bitset_t sbcset,+					re_charset_t *mbcset,+					int *equiv_class_alloc,+					const unsigned char *name);+static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans,+				      bitset_t sbcset,+				      re_charset_t *mbcset,+				      int *char_class_alloc,+				      const unsigned char *class_name,+				      reg_syntax_t syntax);+#else  /* not RE_ENABLE_I18N */+static reg_errcode_t build_equiv_class (bitset_t sbcset,+					const unsigned char *name);+static reg_errcode_t build_charclass (RE_TRANSLATE_TYPE trans,+				      bitset_t sbcset,+				      const unsigned char *class_name,+				      reg_syntax_t syntax);+#endif /* not RE_ENABLE_I18N */+static bin_tree_t *build_charclass_op (re_dfa_t *dfa,+				       RE_TRANSLATE_TYPE trans,+				       const unsigned char *class_name,+				       const unsigned char *extra,+				       int non_match, reg_errcode_t *err);+static bin_tree_t *create_tree (re_dfa_t *dfa,+				bin_tree_t *left, bin_tree_t *right,+				re_token_type_t type);+static bin_tree_t *create_token_tree (re_dfa_t *dfa,+				      bin_tree_t *left, bin_tree_t *right,+				      const re_token_t *token);+static bin_tree_t *duplicate_tree (const bin_tree_t *src, re_dfa_t *dfa);+static void free_token (re_token_t *node);+static reg_errcode_t free_tree (void *extra, bin_tree_t *node);+static reg_errcode_t mark_opt_subexp (void *extra, bin_tree_t *node);++/* This table gives an error message for each of the error codes listed+   in regex.h.  Obviously the order here has to be same as there.+   POSIX doesn't require that we do anything for REG_NOERROR,+   but why not be nice?  */++const char __re_error_msgid[] attribute_hidden =+  {+#define REG_NOERROR_IDX	0+    gettext_noop ("Success")	/* REG_NOERROR */+    "\0"+#define REG_NOMATCH_IDX (REG_NOERROR_IDX + sizeof "Success")+    gettext_noop ("No match")	/* REG_NOMATCH */+    "\0"+#define REG_BADPAT_IDX	(REG_NOMATCH_IDX + sizeof "No match")+    gettext_noop ("Invalid regular expression") /* REG_BADPAT */+    "\0"+#define REG_ECOLLATE_IDX (REG_BADPAT_IDX + sizeof "Invalid regular expression")+    gettext_noop ("Invalid collation character") /* REG_ECOLLATE */+    "\0"+#define REG_ECTYPE_IDX	(REG_ECOLLATE_IDX + sizeof "Invalid collation character")+    gettext_noop ("Invalid character class name") /* REG_ECTYPE */+    "\0"+#define REG_EESCAPE_IDX	(REG_ECTYPE_IDX + sizeof "Invalid character class name")+    gettext_noop ("Trailing backslash") /* REG_EESCAPE */+    "\0"+#define REG_ESUBREG_IDX	(REG_EESCAPE_IDX + sizeof "Trailing backslash")+    gettext_noop ("Invalid back reference") /* REG_ESUBREG */+    "\0"+#define REG_EBRACK_IDX	(REG_ESUBREG_IDX + sizeof "Invalid back reference")+    gettext_noop ("Unmatched [ or [^")	/* REG_EBRACK */+    "\0"+#define REG_EPAREN_IDX	(REG_EBRACK_IDX + sizeof "Unmatched [ or [^")+    gettext_noop ("Unmatched ( or \\(") /* REG_EPAREN */+    "\0"+#define REG_EBRACE_IDX	(REG_EPAREN_IDX + sizeof "Unmatched ( or \\(")+    gettext_noop ("Unmatched \\{") /* REG_EBRACE */+    "\0"+#define REG_BADBR_IDX	(REG_EBRACE_IDX + sizeof "Unmatched \\{")+    gettext_noop ("Invalid content of \\{\\}") /* REG_BADBR */+    "\0"+#define REG_ERANGE_IDX	(REG_BADBR_IDX + sizeof "Invalid content of \\{\\}")+    gettext_noop ("Invalid range end")	/* REG_ERANGE */+    "\0"+#define REG_ESPACE_IDX	(REG_ERANGE_IDX + sizeof "Invalid range end")+    gettext_noop ("Memory exhausted") /* REG_ESPACE */+    "\0"+#define REG_BADRPT_IDX	(REG_ESPACE_IDX + sizeof "Memory exhausted")+    gettext_noop ("Invalid preceding regular expression") /* REG_BADRPT */+    "\0"+#define REG_EEND_IDX	(REG_BADRPT_IDX + sizeof "Invalid preceding regular expression")+    gettext_noop ("Premature end of regular expression") /* REG_EEND */+    "\0"+#define REG_ESIZE_IDX	(REG_EEND_IDX + sizeof "Premature end of regular expression")+    gettext_noop ("Regular expression too big") /* REG_ESIZE */+    "\0"+#define REG_ERPAREN_IDX	(REG_ESIZE_IDX + sizeof "Regular expression too big")+    gettext_noop ("Unmatched ) or \\)") /* REG_ERPAREN */+  };++const size_t __re_error_msgid_idx[] attribute_hidden =+  {+    REG_NOERROR_IDX,+    REG_NOMATCH_IDX,+    REG_BADPAT_IDX,+    REG_ECOLLATE_IDX,+    REG_ECTYPE_IDX,+    REG_EESCAPE_IDX,+    REG_ESUBREG_IDX,+    REG_EBRACK_IDX,+    REG_EPAREN_IDX,+    REG_EBRACE_IDX,+    REG_BADBR_IDX,+    REG_ERANGE_IDX,+    REG_ESPACE_IDX,+    REG_BADRPT_IDX,+    REG_EEND_IDX,+    REG_ESIZE_IDX,+    REG_ERPAREN_IDX+  };++/* Entry points for GNU code.  */++/* re_compile_pattern is the GNU regular expression compiler: it+   compiles PATTERN (of length LENGTH) and puts the result in BUFP.+   Returns 0 if the pattern was valid, otherwise an error string.++   Assumes the `allocated' (and perhaps `buffer') and `translate' fields+   are set in BUFP on entry.  */++const char *+re_compile_pattern (pattern, length, bufp)+    const char *pattern;+    size_t length;+    struct re_pattern_buffer *bufp;+{+  reg_errcode_t ret;++  /* And GNU code determines whether or not to get register information+     by passing null for the REGS argument to re_match, etc., not by+     setting no_sub, unless RE_NO_SUB is set.  */+  bufp->no_sub = !!(re_syntax_options & RE_NO_SUB);++  /* Match anchors at newline.  */+  bufp->newline_anchor = 1;++  ret = re_compile_internal (bufp, pattern, length, re_syntax_options);++  if (!ret)+    return NULL;+  return gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);+}+#ifdef _LIBC+weak_alias (__re_compile_pattern, re_compile_pattern)+#endif++/* Set by `re_set_syntax' to the current regexp syntax to recognize.  Can+   also be assigned to arbitrarily: each pattern buffer stores its own+   syntax, so it can be changed between regex compilations.  */+/* This has no initializer because initialized variables in Emacs+   become read-only after dumping.  */+reg_syntax_t re_syntax_options;+++/* Specify the precise syntax of regexps for compilation.  This provides+   for compatibility for various utilities which historically have+   different, incompatible syntaxes.++   The argument SYNTAX is a bit mask comprised of the various bits+   defined in regex.h.  We return the old syntax.  */++reg_syntax_t+re_set_syntax (syntax)+    reg_syntax_t syntax;+{+  reg_syntax_t ret = re_syntax_options;++  re_syntax_options = syntax;+  return ret;+}+#ifdef _LIBC+weak_alias (__re_set_syntax, re_set_syntax)+#endif++int+re_compile_fastmap (bufp)+    struct re_pattern_buffer *bufp;+{+  re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;+  char *fastmap = bufp->fastmap;++  memset (fastmap, '\0', sizeof (char) * SBC_MAX);+  re_compile_fastmap_iter (bufp, dfa->init_state, fastmap);+  if (dfa->init_state != dfa->init_state_word)+    re_compile_fastmap_iter (bufp, dfa->init_state_word, fastmap);+  if (dfa->init_state != dfa->init_state_nl)+    re_compile_fastmap_iter (bufp, dfa->init_state_nl, fastmap);+  if (dfa->init_state != dfa->init_state_begbuf)+    re_compile_fastmap_iter (bufp, dfa->init_state_begbuf, fastmap);+  bufp->fastmap_accurate = 1;+  return 0;+}+#ifdef _LIBC+weak_alias (__re_compile_fastmap, re_compile_fastmap)+#endif++static inline void+__attribute ((always_inline))+re_set_fastmap (char *fastmap, int icase, int ch)+{+  fastmap[ch] = 1;+  if (icase)+    fastmap[tolower (ch)] = 1;+}++/* Helper function for re_compile_fastmap.+   Compile fastmap for the initial_state INIT_STATE.  */++static void+re_compile_fastmap_iter (regex_t *bufp, const re_dfastate_t *init_state,+			 char *fastmap)+{+  re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;+  int node_cnt;+  int icase = (dfa->mb_cur_max == 1 && (bufp->syntax & RE_ICASE));+  for (node_cnt = 0; node_cnt < init_state->nodes.nelem; ++node_cnt)+    {+      int node = init_state->nodes.elems[node_cnt];+      re_token_type_t type = dfa->nodes[node].type;++      if (type == CHARACTER)+	{+	  re_set_fastmap (fastmap, icase, dfa->nodes[node].opr.c);+#ifdef RE_ENABLE_I18N+	  if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)+	    {+	      unsigned char *buf = alloca (dfa->mb_cur_max), *p;+	      wchar_t wc;+	      mbstate_t state;++	      p = buf;+	      *p++ = dfa->nodes[node].opr.c;+	      while (++node < dfa->nodes_len+		     &&	dfa->nodes[node].type == CHARACTER+		     && dfa->nodes[node].mb_partial)+		*p++ = dfa->nodes[node].opr.c;+	      memset (&state, '\0', sizeof (state));+	      if (mbrtowc (&wc, (const char *) buf, p - buf,+			   &state) == p - buf+		  && (__wcrtomb ((char *) buf, towlower (wc), &state)+		      != (size_t) -1))+		re_set_fastmap (fastmap, 0, buf[0]);+	    }+#endif+	}+      else if (type == SIMPLE_BRACKET)+	{+	  int i, ch;+	  for (i = 0, ch = 0; i < BITSET_WORDS; ++i)+	    {+	      int j;+	      bitset_word_t w = dfa->nodes[node].opr.sbcset[i];+	      for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)+		if (w & ((bitset_word_t) 1 << j))+		  re_set_fastmap (fastmap, icase, ch);+	    }+	}+#ifdef RE_ENABLE_I18N+      else if (type == COMPLEX_BRACKET)+	{+	  int i;+	  re_charset_t *cset = dfa->nodes[node].opr.mbcset;+	  if (cset->non_match || cset->ncoll_syms || cset->nequiv_classes+	      || cset->nranges || cset->nchar_classes)+	    {+# ifdef _LIBC+	      if (_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES) != 0)+		{+		  /* In this case we want to catch the bytes which are+		     the first byte of any collation elements.+		     e.g. In da_DK, we want to catch 'a' since "aa"+			  is a valid collation element, and don't catch+			  'b' since 'b' is the only collation element+			  which starts from 'b'.  */+		  const int32_t *table = (const int32_t *)+		    _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);+		  for (i = 0; i < SBC_MAX; ++i)+		    if (table[i] < 0)+		      re_set_fastmap (fastmap, icase, i);+		}+# else+	      if (dfa->mb_cur_max > 1)+		for (i = 0; i < SBC_MAX; ++i)+		  if (__btowc (i) == WEOF)+		    re_set_fastmap (fastmap, icase, i);+# endif /* not _LIBC */+	    }+	  for (i = 0; i < cset->nmbchars; ++i)+	    {+	      char buf[256];+	      mbstate_t state;+	      memset (&state, '\0', sizeof (state));+	      if (__wcrtomb (buf, cset->mbchars[i], &state) != (size_t) -1)+		re_set_fastmap (fastmap, icase, *(unsigned char *) buf);+	      if ((bufp->syntax & RE_ICASE) && dfa->mb_cur_max > 1)+		{+		  if (__wcrtomb (buf, towlower (cset->mbchars[i]), &state)+		      != (size_t) -1)+		    re_set_fastmap (fastmap, 0, *(unsigned char *) buf);+		}+	    }+	}+#endif /* RE_ENABLE_I18N */+      else if (type == OP_PERIOD+#ifdef RE_ENABLE_I18N+	       || type == OP_UTF8_PERIOD+#endif /* RE_ENABLE_I18N */+	       || type == END_OF_RE)+	{+	  memset (fastmap, '\1', sizeof (char) * SBC_MAX);+	  if (type == END_OF_RE)+	    bufp->can_be_null = 1;+	  return;+	}+    }+}++/* Entry point for POSIX code.  */+/* regcomp takes a regular expression as a string and compiles it.++   PREG is a regex_t *.  We do not expect any fields to be initialized,+   since POSIX says we shouldn't.  Thus, we set++     `buffer' to the compiled pattern;+     `used' to the length of the compiled pattern;+     `syntax' to RE_SYNTAX_POSIX_EXTENDED if the+       REG_EXTENDED bit in CFLAGS is set; otherwise, to+       RE_SYNTAX_POSIX_BASIC;+     `newline_anchor' to REG_NEWLINE being set in CFLAGS;+     `fastmap' to an allocated space for the fastmap;+     `fastmap_accurate' to zero;+     `re_nsub' to the number of subexpressions in PATTERN.++   PATTERN is the address of the pattern string.++   CFLAGS is a series of bits which affect compilation.++     If REG_EXTENDED is set, we use POSIX extended syntax; otherwise, we+     use POSIX basic syntax.++     If REG_NEWLINE is set, then . and [^...] don't match newline.+     Also, regexec will try a match beginning after every newline.++     If REG_ICASE is set, then we considers upper- and lowercase+     versions of letters to be equivalent when matching.++     If REG_NOSUB is set, then when PREG is passed to regexec, that+     routine will report only success or failure, and nothing about the+     registers.++   It returns 0 if it succeeds, nonzero if it doesn't.  (See regex.h for+   the return codes and their meanings.)  */++int+regcomp (preg, pattern, cflags)+    regex_t *__restrict preg;+    const char *__restrict pattern;+    int cflags;+{+  reg_errcode_t ret;+  reg_syntax_t syntax = ((cflags & REG_EXTENDED) ? RE_SYNTAX_POSIX_EXTENDED+			 : RE_SYNTAX_POSIX_BASIC);++  preg->buffer = NULL;+  preg->allocated = 0;+  preg->used = 0;++  /* Try to allocate space for the fastmap.  */+  preg->fastmap = re_malloc (char, SBC_MAX);+  if (BE (preg->fastmap == NULL, 0))+    return REG_ESPACE;++  syntax |= (cflags & REG_ICASE) ? RE_ICASE : 0;++  /* If REG_NEWLINE is set, newlines are treated differently.  */+  if (cflags & REG_NEWLINE)+    { /* REG_NEWLINE implies neither . nor [^...] match newline.  */+      syntax &= ~RE_DOT_NEWLINE;+      syntax |= RE_HAT_LISTS_NOT_NEWLINE;+      /* It also changes the matching behavior.  */+      preg->newline_anchor = 1;+    }+  else+    preg->newline_anchor = 0;+  preg->no_sub = !!(cflags & REG_NOSUB);+  preg->translate = NULL;++  ret = re_compile_internal (preg, pattern, strlen (pattern), syntax);++  /* POSIX doesn't distinguish between an unmatched open-group and an+     unmatched close-group: both are REG_EPAREN.  */+  if (ret == REG_ERPAREN)+    ret = REG_EPAREN;++  /* We have already checked preg->fastmap != NULL.  */+  if (BE (ret == REG_NOERROR, 1))+    /* Compute the fastmap now, since regexec cannot modify the pattern+       buffer.  This function never fails in this implementation.  */+    (void) re_compile_fastmap (preg);+  else+    {+      /* Some error occurred while compiling the expression.  */+      re_free (preg->fastmap);+      preg->fastmap = NULL;+    }++  return (int) ret;+}+#ifdef _LIBC+weak_alias (__regcomp, regcomp)+#endif++/* Returns a message corresponding to an error code, ERRCODE, returned+   from either regcomp or regexec.   We don't use PREG here.  */++size_t+regerror (errcode, preg, errbuf, errbuf_size)+    int errcode;+    const regex_t *__restrict preg;+    char *__restrict errbuf;+    size_t errbuf_size;+{+  const char *msg;+  size_t msg_size;++  if (BE (errcode < 0+	  || errcode >= (int) (sizeof (__re_error_msgid_idx)+			       / sizeof (__re_error_msgid_idx[0])), 0))+    /* Only error codes returned by the rest of the code should be passed+       to this routine.  If we are given anything else, or if other regex+       code generates an invalid error code, then the program has a bug.+       Dump core so we can fix it.  */+    abort ();++  msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]);++  msg_size = strlen (msg) + 1; /* Includes the null.  */++  if (BE (errbuf_size != 0, 1))+    {+      if (BE (msg_size > errbuf_size, 0))+	{+#if defined HAVE_MEMPCPY || defined _LIBC+	  *((char *) __mempcpy (errbuf, msg, errbuf_size - 1)) = '\0';+#else+	  memcpy (errbuf, msg, errbuf_size - 1);+	  errbuf[errbuf_size - 1] = 0;+#endif+	}+      else+	memcpy (errbuf, msg, msg_size);+    }++  return msg_size;+}+#ifdef _LIBC+weak_alias (__regerror, regerror)+#endif+++#ifdef RE_ENABLE_I18N+/* This static array is used for the map to single-byte characters when+   UTF-8 is used.  Otherwise we would allocate memory just to initialize+   it the same all the time.  UTF-8 is the preferred encoding so this is+   a worthwhile optimization.  */+static const bitset_t utf8_sb_map =+{+  /* Set the first 128 bits.  */+  [0 ... 0x80 / BITSET_WORD_BITS - 1] = BITSET_WORD_MAX+};+#endif+++static void+free_dfa_content (re_dfa_t *dfa)+{+  int i, j;++  if (dfa->nodes)+    for (i = 0; i < dfa->nodes_len; ++i)+      free_token (dfa->nodes + i);+  re_free (dfa->nexts);+  for (i = 0; i < dfa->nodes_len; ++i)+    {+      if (dfa->eclosures != NULL)+	re_node_set_free (dfa->eclosures + i);+      if (dfa->inveclosures != NULL)+	re_node_set_free (dfa->inveclosures + i);+      if (dfa->edests != NULL)+	re_node_set_free (dfa->edests + i);+    }+  re_free (dfa->edests);+  re_free (dfa->eclosures);+  re_free (dfa->inveclosures);+  re_free (dfa->nodes);++  if (dfa->state_table)+    for (i = 0; i <= dfa->state_hash_mask; ++i)+      {+	struct re_state_table_entry *entry = dfa->state_table + i;+	for (j = 0; j < entry->num; ++j)+	  {+	    re_dfastate_t *state = entry->array[j];+	    free_state (state);+	  }+        re_free (entry->array);+      }+  re_free (dfa->state_table);+#ifdef RE_ENABLE_I18N+  if (dfa->sb_char != utf8_sb_map)+    re_free (dfa->sb_char);+#endif+  re_free (dfa->subexp_map);+#ifdef DEBUG+  re_free (dfa->re_str);+#endif++  re_free (dfa);+}+++/* Free dynamically allocated space used by PREG.  */++void+regfree (preg)+    regex_t *preg;+{+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;+  if (BE (dfa != NULL, 1))+    free_dfa_content (dfa);+  preg->buffer = NULL;+  preg->allocated = 0;++  re_free (preg->fastmap);+  preg->fastmap = NULL;++  re_free (preg->translate);+  preg->translate = NULL;+}+#ifdef _LIBC+weak_alias (__regfree, regfree)+#endif++/* Entry points compatible with 4.2 BSD regex library.  We don't define+   them unless specifically requested.  */++#if defined _REGEX_RE_COMP || defined _LIBC++/* BSD has one and only one pattern buffer.  */+static struct re_pattern_buffer re_comp_buf;++char *+# ifdef _LIBC+/* Make these definitions weak in libc, so POSIX programs can redefine+   these names if they don't use our functions, and still use+   regcomp/regexec above without link errors.  */+weak_function+# endif+re_comp (s)+     const char *s;+{+  reg_errcode_t ret;+  char *fastmap;++  if (!s)+    {+      if (!re_comp_buf.buffer)+	return gettext ("No previous regular expression");+      return 0;+    }++  if (re_comp_buf.buffer)+    {+      fastmap = re_comp_buf.fastmap;+      re_comp_buf.fastmap = NULL;+      __regfree (&re_comp_buf);+      memset (&re_comp_buf, '\0', sizeof (re_comp_buf));+      re_comp_buf.fastmap = fastmap;+    }++  if (re_comp_buf.fastmap == NULL)+    {+      re_comp_buf.fastmap = (char *) malloc (SBC_MAX);+      if (re_comp_buf.fastmap == NULL)+	return (char *) gettext (__re_error_msgid+				 + __re_error_msgid_idx[(int) REG_ESPACE]);+    }++  /* Since `re_exec' always passes NULL for the `regs' argument, we+     don't need to initialize the pattern buffer fields which affect it.  */++  /* Match anchors at newlines.  */+  re_comp_buf.newline_anchor = 1;++  ret = re_compile_internal (&re_comp_buf, s, strlen (s), re_syntax_options);++  if (!ret)+    return NULL;++  /* Yes, we're discarding `const' here if !HAVE_LIBINTL.  */+  return (char *) gettext (__re_error_msgid + __re_error_msgid_idx[(int) ret]);+}++#ifdef _LIBC+libc_freeres_fn (free_mem)+{+  __regfree (&re_comp_buf);+}+#endif++#endif /* _REGEX_RE_COMP */++/* Internal entry point.+   Compile the regular expression PATTERN, whose length is LENGTH.+   SYNTAX indicate regular expression's syntax.  */++static reg_errcode_t+re_compile_internal (regex_t *preg, const char * pattern, size_t length,+		     reg_syntax_t syntax)+{+  reg_errcode_t err = REG_NOERROR;+  re_dfa_t *dfa;+  re_string_t regexp;++  /* Initialize the pattern buffer.  */+  preg->fastmap_accurate = 0;+  preg->syntax = syntax;+  preg->not_bol = preg->not_eol = 0;+  preg->used = 0;+  preg->re_nsub = 0;+  preg->can_be_null = 0;+  preg->regs_allocated = REGS_UNALLOCATED;++  /* Initialize the dfa.  */+  dfa = (re_dfa_t *) preg->buffer;+  if (BE (preg->allocated < sizeof (re_dfa_t), 0))+    {+      /* If zero allocated, but buffer is non-null, try to realloc+	 enough space.  This loses if buffer's address is bogus, but+	 that is the user's responsibility.  If ->buffer is NULL this+	 is a simple allocation.  */+      dfa = re_realloc (preg->buffer, re_dfa_t, 1);+      if (dfa == NULL)+	return REG_ESPACE;+      preg->allocated = sizeof (re_dfa_t);+      preg->buffer = (unsigned char *) dfa;+    }+  preg->used = sizeof (re_dfa_t);++  err = init_dfa (dfa, length);+  if (BE (err != REG_NOERROR, 0))+    {+      free_dfa_content (dfa);+      preg->buffer = NULL;+      preg->allocated = 0;+      return err;+    }+#ifdef DEBUG+  /* Note: length+1 will not overflow since it is checked in init_dfa.  */+  dfa->re_str = re_malloc (char, length + 1);+  strncpy (dfa->re_str, pattern, length + 1);+#endif++  __libc_lock_init (dfa->lock);++  err = re_string_construct (&regexp, pattern, length, preg->translate,+			     syntax & RE_ICASE, dfa);+  if (BE (err != REG_NOERROR, 0))+    {+    re_compile_internal_free_return:+      free_workarea_compile (preg);+      re_string_destruct (&regexp);+      free_dfa_content (dfa);+      preg->buffer = NULL;+      preg->allocated = 0;+      return err;+    }++  /* Parse the regular expression, and build a structure tree.  */+  preg->re_nsub = 0;+  dfa->str_tree = parse (&regexp, preg, syntax, &err);+  if (BE (dfa->str_tree == NULL, 0))+    goto re_compile_internal_free_return;++  /* Analyze the tree and create the nfa.  */+  err = analyze (preg);+  if (BE (err != REG_NOERROR, 0))+    goto re_compile_internal_free_return;++#ifdef RE_ENABLE_I18N+  /* If possible, do searching in single byte encoding to speed things up.  */+  if (dfa->is_utf8 && !(syntax & RE_ICASE) && preg->translate == NULL)+    optimize_utf8 (dfa);+#endif++  /* Then create the initial state of the dfa.  */+  err = create_initial_state (dfa);++  /* Release work areas.  */+  free_workarea_compile (preg);+  re_string_destruct (&regexp);++  if (BE (err != REG_NOERROR, 0))+    {+      free_dfa_content (dfa);+      preg->buffer = NULL;+      preg->allocated = 0;+    }++  return err;+}++/* Initialize DFA.  We use the length of the regular expression PAT_LEN+   as the initial length of some arrays.  */++static reg_errcode_t+init_dfa (re_dfa_t *dfa, size_t pat_len)+{+  unsigned int table_size;+#ifndef _LIBC+  char *codeset_name;+#endif++  memset (dfa, '\0', sizeof (re_dfa_t));++  /* Force allocation of str_tree_storage the first time.  */+  dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;++  /* Avoid overflows.  */+  if (pat_len == SIZE_MAX)+    return REG_ESPACE;++  dfa->nodes_alloc = pat_len + 1;+  dfa->nodes = re_malloc (re_token_t, dfa->nodes_alloc);++  /*  table_size = 2 ^ ceil(log pat_len) */+  for (table_size = 1; ; table_size <<= 1)+    if (table_size > pat_len)+      break;++  dfa->state_table = calloc (sizeof (struct re_state_table_entry), table_size);+  dfa->state_hash_mask = table_size - 1;++  dfa->mb_cur_max = MB_CUR_MAX;+#ifdef _LIBC+  if (dfa->mb_cur_max == 6+      && strcmp (_NL_CURRENT (LC_CTYPE, _NL_CTYPE_CODESET_NAME), "UTF-8") == 0)+    dfa->is_utf8 = 1;+  dfa->map_notascii = (_NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_TO_NONASCII)+		       != 0);+#else+# ifdef HAVE_LANGINFO_CODESET+  codeset_name = nl_langinfo (CODESET);+# else+  codeset_name = getenv ("LC_ALL");+  if (codeset_name == NULL || codeset_name[0] == '\0')+    codeset_name = getenv ("LC_CTYPE");+  if (codeset_name == NULL || codeset_name[0] == '\0')+    codeset_name = getenv ("LANG");+  if (codeset_name == NULL)+    codeset_name = "";+  else if (strchr (codeset_name, '.') !=  NULL)+    codeset_name = strchr (codeset_name, '.') + 1;+# endif++  if (strcasecmp (codeset_name, "UTF-8") == 0+      || strcasecmp (codeset_name, "UTF8") == 0)+    dfa->is_utf8 = 1;++  /* We check exhaustively in the loop below if this charset is a+     superset of ASCII.  */+  dfa->map_notascii = 0;+#endif++#ifdef RE_ENABLE_I18N+  if (dfa->mb_cur_max > 1)+    {+      if (dfa->is_utf8)+	dfa->sb_char = (re_bitset_ptr_t) utf8_sb_map;+      else+	{+	  int i, j, ch;++	  dfa->sb_char = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);+	  if (BE (dfa->sb_char == NULL, 0))+	    return REG_ESPACE;++	  /* Set the bits corresponding to single byte chars.  */+	  for (i = 0, ch = 0; i < BITSET_WORDS; ++i)+	    for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)+	      {+		wint_t wch = __btowc (ch);+		if (wch != WEOF)+		  dfa->sb_char[i] |= (bitset_word_t) 1 << j;+# ifndef _LIBC+		if (isascii (ch) && wch != ch)+		  dfa->map_notascii = 1;+# endif+	      }+	}+    }+#endif++  if (BE (dfa->nodes == NULL || dfa->state_table == NULL, 0))+    return REG_ESPACE;+  return REG_NOERROR;+}++/* Initialize WORD_CHAR table, which indicate which character is+   "word".  In this case "word" means that it is the word construction+   character used by some operators like "\<", "\>", etc.  */++static void+internal_function+init_word_char (re_dfa_t *dfa)+{+  int i, j, ch;+  dfa->word_ops_used = 1;+  for (i = 0, ch = 0; i < BITSET_WORDS; ++i)+    for (j = 0; j < BITSET_WORD_BITS; ++j, ++ch)+      if (isalnum (ch) || ch == '_')+	dfa->word_char[i] |= (bitset_word_t) 1 << j;+}++/* Free the work area which are only used while compiling.  */++static void+free_workarea_compile (regex_t *preg)+{+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;+  bin_tree_storage_t *storage, *next;+  for (storage = dfa->str_tree_storage; storage; storage = next)+    {+      next = storage->next;+      re_free (storage);+    }+  dfa->str_tree_storage = NULL;+  dfa->str_tree_storage_idx = BIN_TREE_STORAGE_SIZE;+  dfa->str_tree = NULL;+  re_free (dfa->org_indices);+  dfa->org_indices = NULL;+}++/* Create initial states for all contexts.  */++static reg_errcode_t+create_initial_state (re_dfa_t *dfa)+{+  int first, i;+  reg_errcode_t err;+  re_node_set init_nodes;++  /* Initial states have the epsilon closure of the node which is+     the first node of the regular expression.  */+  first = dfa->str_tree->first->node_idx;+  dfa->init_node = first;+  err = re_node_set_init_copy (&init_nodes, dfa->eclosures + first);+  if (BE (err != REG_NOERROR, 0))+    return err;++  /* The back-references which are in initial states can epsilon transit,+     since in this case all of the subexpressions can be null.+     Then we add epsilon closures of the nodes which are the next nodes of+     the back-references.  */+  if (dfa->nbackref > 0)+    for (i = 0; i < init_nodes.nelem; ++i)+      {+	int node_idx = init_nodes.elems[i];+	re_token_type_t type = dfa->nodes[node_idx].type;++	int clexp_idx;+	if (type != OP_BACK_REF)+	  continue;+	for (clexp_idx = 0; clexp_idx < init_nodes.nelem; ++clexp_idx)+	  {+	    re_token_t *clexp_node;+	    clexp_node = dfa->nodes + init_nodes.elems[clexp_idx];+	    if (clexp_node->type == OP_CLOSE_SUBEXP+		&& clexp_node->opr.idx == dfa->nodes[node_idx].opr.idx)+	      break;+	  }+	if (clexp_idx == init_nodes.nelem)+	  continue;++	if (type == OP_BACK_REF)+	  {+	    int dest_idx = dfa->edests[node_idx].elems[0];+	    if (!re_node_set_contains (&init_nodes, dest_idx))+	      {+		re_node_set_merge (&init_nodes, dfa->eclosures + dest_idx);+		i = 0;+	      }+	  }+      }++  /* It must be the first time to invoke acquire_state.  */+  dfa->init_state = re_acquire_state_context (&err, dfa, &init_nodes, 0);+  /* We don't check ERR here, since the initial state must not be NULL.  */+  if (BE (dfa->init_state == NULL, 0))+    return err;+  if (dfa->init_state->has_constraint)+    {+      dfa->init_state_word = re_acquire_state_context (&err, dfa, &init_nodes,+						       CONTEXT_WORD);+      dfa->init_state_nl = re_acquire_state_context (&err, dfa, &init_nodes,+						     CONTEXT_NEWLINE);+      dfa->init_state_begbuf = re_acquire_state_context (&err, dfa,+							 &init_nodes,+							 CONTEXT_NEWLINE+							 | CONTEXT_BEGBUF);+      if (BE (dfa->init_state_word == NULL || dfa->init_state_nl == NULL+	      || dfa->init_state_begbuf == NULL, 0))+	return err;+    }+  else+    dfa->init_state_word = dfa->init_state_nl+      = dfa->init_state_begbuf = dfa->init_state;++  re_node_set_free (&init_nodes);+  return REG_NOERROR;+}++#ifdef RE_ENABLE_I18N+/* If it is possible to do searching in single byte encoding instead of UTF-8+   to speed things up, set dfa->mb_cur_max to 1, clear is_utf8 and change+   DFA nodes where needed.  */++static void+optimize_utf8 (re_dfa_t *dfa)+{+  int node, i, mb_chars = 0, has_period = 0;++  for (node = 0; node < dfa->nodes_len; ++node)+    switch (dfa->nodes[node].type)+      {+      case CHARACTER:+	if (dfa->nodes[node].opr.c >= 0x80)+	  mb_chars = 1;+	break;+      case ANCHOR:+	switch (dfa->nodes[node].opr.idx)+	  {+	  case LINE_FIRST:+	  case LINE_LAST:+	  case BUF_FIRST:+	  case BUF_LAST:+	    break;+	  default:+	    /* Word anchors etc. cannot be handled.  */+	    return;+	  }+	break;+      case OP_PERIOD:+        has_period = 1;+        break;+      case OP_BACK_REF:+      case OP_ALT:+      case END_OF_RE:+      case OP_DUP_ASTERISK:+      case OP_OPEN_SUBEXP:+      case OP_CLOSE_SUBEXP:+	break;+      case COMPLEX_BRACKET:+	return;+      case SIMPLE_BRACKET:+	/* Just double check.  The non-ASCII range starts at 0x80.  */+	assert (0x80 % BITSET_WORD_BITS == 0);+        for (i = 0x80 / BITSET_WORD_BITS; i < BITSET_WORDS; ++i)+	  if (dfa->nodes[node].opr.sbcset[i])+	    return;+	break;+      default:+	abort ();+      }++  if (mb_chars || has_period)+    for (node = 0; node < dfa->nodes_len; ++node)+      {+	if (dfa->nodes[node].type == CHARACTER+	    && dfa->nodes[node].opr.c >= 0x80)+	  dfa->nodes[node].mb_partial = 0;+	else if (dfa->nodes[node].type == OP_PERIOD)+	  dfa->nodes[node].type = OP_UTF8_PERIOD;+      }++  /* The search can be in single byte locale.  */+  dfa->mb_cur_max = 1;+  dfa->is_utf8 = 0;+  dfa->has_mb_node = dfa->nbackref > 0 || has_period;+}+#endif++/* Analyze the structure tree, and calculate "first", "next", "edest",+   "eclosure", and "inveclosure".  */++static reg_errcode_t+analyze (regex_t *preg)+{+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;+  reg_errcode_t ret;++  /* Allocate arrays.  */+  dfa->nexts = re_malloc (int, dfa->nodes_alloc);+  dfa->org_indices = re_malloc (int, dfa->nodes_alloc);+  dfa->edests = re_malloc (re_node_set, dfa->nodes_alloc);+  dfa->eclosures = re_malloc (re_node_set, dfa->nodes_alloc);+  if (BE (dfa->nexts == NULL || dfa->org_indices == NULL || dfa->edests == NULL+	  || dfa->eclosures == NULL, 0))+    return REG_ESPACE;++  dfa->subexp_map = re_malloc (int, preg->re_nsub);+  if (dfa->subexp_map != NULL)+    {+      int i;+      for (i = 0; i < preg->re_nsub; i++)+	dfa->subexp_map[i] = i;+      preorder (dfa->str_tree, optimize_subexps, dfa);+      for (i = 0; i < preg->re_nsub; i++)+	if (dfa->subexp_map[i] != i)+	  break;+      if (i == preg->re_nsub)+	{+	  free (dfa->subexp_map);+	  dfa->subexp_map = NULL;+	}+    }++  ret = postorder (dfa->str_tree, lower_subexps, preg);+  if (BE (ret != REG_NOERROR, 0))+    return ret;+  ret = postorder (dfa->str_tree, calc_first, dfa);+  if (BE (ret != REG_NOERROR, 0))+    return ret;+  preorder (dfa->str_tree, calc_next, dfa);+  ret = preorder (dfa->str_tree, link_nfa_nodes, dfa);+  if (BE (ret != REG_NOERROR, 0))+    return ret;+  ret = calc_eclosure (dfa);+  if (BE (ret != REG_NOERROR, 0))+    return ret;++  /* We only need this during the prune_impossible_nodes pass in regexec.c;+     skip it if p_i_n will not run, as calc_inveclosure can be quadratic.  */+  if ((!preg->no_sub && preg->re_nsub > 0 && dfa->has_plural_match)+      || dfa->nbackref)+    {+      dfa->inveclosures = re_malloc (re_node_set, dfa->nodes_len);+      if (BE (dfa->inveclosures == NULL, 0))+        return REG_ESPACE;+      ret = calc_inveclosure (dfa);+    }++  return ret;+}++/* Our parse trees are very unbalanced, so we cannot use a stack to+   implement parse tree visits.  Instead, we use parent pointers and+   some hairy code in these two functions.  */+static reg_errcode_t+postorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)),+	   void *extra)+{+  bin_tree_t *node, *prev;++  for (node = root; ; )+    {+      /* Descend down the tree, preferably to the left (or to the right+	 if that's the only child).  */+      while (node->left || node->right)+	if (node->left)+          node = node->left;+        else+          node = node->right;++      do+	{+	  reg_errcode_t err = fn (extra, node);+	  if (BE (err != REG_NOERROR, 0))+	    return err;+          if (node->parent == NULL)+	    return REG_NOERROR;+	  prev = node;+	  node = node->parent;+	}+      /* Go up while we have a node that is reached from the right.  */+      while (node->right == prev || node->right == NULL);+      node = node->right;+    }+}++static reg_errcode_t+preorder (bin_tree_t *root, reg_errcode_t (fn (void *, bin_tree_t *)),+	  void *extra)+{+  bin_tree_t *node;++  for (node = root; ; )+    {+      reg_errcode_t err = fn (extra, node);+      if (BE (err != REG_NOERROR, 0))+	return err;++      /* Go to the left node, or up and to the right.  */+      if (node->left)+	node = node->left;+      else+	{+	  bin_tree_t *prev = NULL;+	  while (node->right == prev || node->right == NULL)+	    {+	      prev = node;+	      node = node->parent;+	      if (!node)+	        return REG_NOERROR;+	    }+	  node = node->right;+	}+    }+}++/* Optimization pass: if a SUBEXP is entirely contained, strip it and tell+   re_search_internal to map the inner one's opr.idx to this one's.  Adjust+   backreferences as well.  Requires a preorder visit.  */+static reg_errcode_t+optimize_subexps (void *extra, bin_tree_t *node)+{+  re_dfa_t *dfa = (re_dfa_t *) extra;++  if (node->token.type == OP_BACK_REF && dfa->subexp_map)+    {+      int idx = node->token.opr.idx;+      node->token.opr.idx = dfa->subexp_map[idx];+      dfa->used_bkref_map |= 1 << node->token.opr.idx;+    }++  else if (node->token.type == SUBEXP+           && node->left && node->left->token.type == SUBEXP)+    {+      int other_idx = node->left->token.opr.idx;++      node->left = node->left->left;+      if (node->left)+        node->left->parent = node;++      dfa->subexp_map[other_idx] = dfa->subexp_map[node->token.opr.idx];+      if (other_idx < BITSET_WORD_BITS)+	  dfa->used_bkref_map &= ~((bitset_word_t) 1 << other_idx);+    }++  return REG_NOERROR;+}++/* Lowering pass: Turn each SUBEXP node into the appropriate concatenation+   of OP_OPEN_SUBEXP, the body of the SUBEXP (if any) and OP_CLOSE_SUBEXP.  */+static reg_errcode_t+lower_subexps (void *extra, bin_tree_t *node)+{+  regex_t *preg = (regex_t *) extra;+  reg_errcode_t err = REG_NOERROR;++  if (node->left && node->left->token.type == SUBEXP)+    {+      node->left = lower_subexp (&err, preg, node->left);+      if (node->left)+	node->left->parent = node;+    }+  if (node->right && node->right->token.type == SUBEXP)+    {+      node->right = lower_subexp (&err, preg, node->right);+      if (node->right)+	node->right->parent = node;+    }++  return err;+}++static bin_tree_t *+lower_subexp (reg_errcode_t *err, regex_t *preg, bin_tree_t *node)+{+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;+  bin_tree_t *body = node->left;+  bin_tree_t *op, *cls, *tree1, *tree;++  if (preg->no_sub+      /* We do not optimize empty subexpressions, because otherwise we may+	 have bad CONCAT nodes with NULL children.  This is obviously not+	 very common, so we do not lose much.  An example that triggers+	 this case is the sed "script" /\(\)/x.  */+      && node->left != NULL+      && (node->token.opr.idx >= BITSET_WORD_BITS+	  || !(dfa->used_bkref_map+	       & ((bitset_word_t) 1 << node->token.opr.idx))))+    return node->left;++  /* Convert the SUBEXP node to the concatenation of an+     OP_OPEN_SUBEXP, the contents, and an OP_CLOSE_SUBEXP.  */+  op = create_tree (dfa, NULL, NULL, OP_OPEN_SUBEXP);+  cls = create_tree (dfa, NULL, NULL, OP_CLOSE_SUBEXP);+  tree1 = body ? create_tree (dfa, body, cls, CONCAT) : cls;+  tree = create_tree (dfa, op, tree1, CONCAT);+  if (BE (tree == NULL || tree1 == NULL || op == NULL || cls == NULL, 0))+    {+      *err = REG_ESPACE;+      return NULL;+    }++  op->token.opr.idx = cls->token.opr.idx = node->token.opr.idx;+  op->token.opt_subexp = cls->token.opt_subexp = node->token.opt_subexp;+  return tree;+}++/* Pass 1 in building the NFA: compute FIRST and create unlinked automaton+   nodes.  Requires a postorder visit.  */+static reg_errcode_t+calc_first (void *extra, bin_tree_t *node)+{+  re_dfa_t *dfa = (re_dfa_t *) extra;+  if (node->token.type == CONCAT)+    {+      node->first = node->left->first;+      node->node_idx = node->left->node_idx;+    }+  else+    {+      node->first = node;+      node->node_idx = re_dfa_add_node (dfa, node->token);+      if (BE (node->node_idx == -1, 0))+        return REG_ESPACE;+    }+  return REG_NOERROR;+}++/* Pass 2: compute NEXT on the tree.  Preorder visit.  */+static reg_errcode_t+calc_next (void *extra, bin_tree_t *node)+{+  switch (node->token.type)+    {+    case OP_DUP_ASTERISK:+      node->left->next = node;+      break;+    case CONCAT:+      node->left->next = node->right->first;+      node->right->next = node->next;+      break;+    default:+      if (node->left)+	node->left->next = node->next;+      if (node->right)+        node->right->next = node->next;+      break;+    }+  return REG_NOERROR;+}++/* Pass 3: link all DFA nodes to their NEXT node (any order will do).  */+static reg_errcode_t+link_nfa_nodes (void *extra, bin_tree_t *node)+{+  re_dfa_t *dfa = (re_dfa_t *) extra;+  int idx = node->node_idx;+  reg_errcode_t err = REG_NOERROR;++  switch (node->token.type)+    {+    case CONCAT:+      break;++    case END_OF_RE:+      assert (node->next == NULL);+      break;++    case OP_DUP_ASTERISK:+    case OP_ALT:+      {+	int left, right;+	dfa->has_plural_match = 1;+	if (node->left != NULL)+	  left = node->left->first->node_idx;+	else+	  left = node->next->node_idx;+	if (node->right != NULL)+	  right = node->right->first->node_idx;+	else+	  right = node->next->node_idx;+	assert (left > -1);+	assert (right > -1);+	err = re_node_set_init_2 (dfa->edests + idx, left, right);+      }+      break;++    case ANCHOR:+    case OP_OPEN_SUBEXP:+    case OP_CLOSE_SUBEXP:+      err = re_node_set_init_1 (dfa->edests + idx, node->next->node_idx);+      break;++    case OP_BACK_REF:+      dfa->nexts[idx] = node->next->node_idx;+      if (node->token.type == OP_BACK_REF)+	re_node_set_init_1 (dfa->edests + idx, dfa->nexts[idx]);+      break;++    default:+      assert (!IS_EPSILON_NODE (node->token.type));+      dfa->nexts[idx] = node->next->node_idx;+      break;+    }++  return err;+}++/* Duplicate the epsilon closure of the node ROOT_NODE.+   Note that duplicated nodes have constraint INIT_CONSTRAINT in addition+   to their own constraint.  */++static reg_errcode_t+internal_function+duplicate_node_closure (re_dfa_t *dfa, int top_org_node, int top_clone_node,+			int root_node, unsigned int init_constraint)+{+  int org_node, clone_node, ret;+  unsigned int constraint = init_constraint;+  for (org_node = top_org_node, clone_node = top_clone_node;;)+    {+      int org_dest, clone_dest;+      if (dfa->nodes[org_node].type == OP_BACK_REF)+	{+	  /* If the back reference epsilon-transit, its destination must+	     also have the constraint.  Then duplicate the epsilon closure+	     of the destination of the back reference, and store it in+	     edests of the back reference.  */+	  org_dest = dfa->nexts[org_node];+	  re_node_set_empty (dfa->edests + clone_node);+	  clone_dest = duplicate_node (dfa, org_dest, constraint);+	  if (BE (clone_dest == -1, 0))+	    return REG_ESPACE;+	  dfa->nexts[clone_node] = dfa->nexts[org_node];+	  ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);+	  if (BE (ret < 0, 0))+	    return REG_ESPACE;+	}+      else if (dfa->edests[org_node].nelem == 0)+	{+	  /* In case of the node can't epsilon-transit, don't duplicate the+	     destination and store the original destination as the+	     destination of the node.  */+	  dfa->nexts[clone_node] = dfa->nexts[org_node];+	  break;+	}+      else if (dfa->edests[org_node].nelem == 1)+	{+	  /* In case of the node can epsilon-transit, and it has only one+	     destination.  */+	  org_dest = dfa->edests[org_node].elems[0];+	  re_node_set_empty (dfa->edests + clone_node);+	  if (dfa->nodes[org_node].type == ANCHOR)+	    {+	      /* In case of the node has another constraint, append it.  */+	      if (org_node == root_node && clone_node != org_node)+		{+		  /* ...but if the node is root_node itself, it means the+		     epsilon closure have a loop, then tie it to the+		     destination of the root_node.  */+		  ret = re_node_set_insert (dfa->edests + clone_node,+					    org_dest);+		  if (BE (ret < 0, 0))+		    return REG_ESPACE;+		  break;+		}+	      constraint |= dfa->nodes[org_node].opr.ctx_type;+	    }+	  clone_dest = duplicate_node (dfa, org_dest, constraint);+	  if (BE (clone_dest == -1, 0))+	    return REG_ESPACE;+	  ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);+	  if (BE (ret < 0, 0))+	    return REG_ESPACE;+	}+      else /* dfa->edests[org_node].nelem == 2 */+	{+	  /* In case of the node can epsilon-transit, and it has two+	     destinations. In the bin_tree_t and DFA, that's '|' and '*'.   */+	  org_dest = dfa->edests[org_node].elems[0];+	  re_node_set_empty (dfa->edests + clone_node);+	  /* Search for a duplicated node which satisfies the constraint.  */+	  clone_dest = search_duplicated_node (dfa, org_dest, constraint);+	  if (clone_dest == -1)+	    {+	      /* There are no such a duplicated node, create a new one.  */+	      reg_errcode_t err;+	      clone_dest = duplicate_node (dfa, org_dest, constraint);+	      if (BE (clone_dest == -1, 0))+		return REG_ESPACE;+	      ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);+	      if (BE (ret < 0, 0))+		return REG_ESPACE;+	      err = duplicate_node_closure (dfa, org_dest, clone_dest,+					    root_node, constraint);+	      if (BE (err != REG_NOERROR, 0))+		return err;+	    }+	  else+	    {+	      /* There are a duplicated node which satisfy the constraint,+		 use it to avoid infinite loop.  */+	      ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);+	      if (BE (ret < 0, 0))+		return REG_ESPACE;+	    }++	  org_dest = dfa->edests[org_node].elems[1];+	  clone_dest = duplicate_node (dfa, org_dest, constraint);+	  if (BE (clone_dest == -1, 0))+	    return REG_ESPACE;+	  ret = re_node_set_insert (dfa->edests + clone_node, clone_dest);+	  if (BE (ret < 0, 0))+	    return REG_ESPACE;+	}+      org_node = org_dest;+      clone_node = clone_dest;+    }+  return REG_NOERROR;+}++/* Search for a node which is duplicated from the node ORG_NODE, and+   satisfies the constraint CONSTRAINT.  */++static int+search_duplicated_node (const re_dfa_t *dfa, int org_node,+			unsigned int constraint)+{+  int idx;+  for (idx = dfa->nodes_len - 1; dfa->nodes[idx].duplicated && idx > 0; --idx)+    {+      if (org_node == dfa->org_indices[idx]+	  && constraint == dfa->nodes[idx].constraint)+	return idx; /* Found.  */+    }+  return -1; /* Not found.  */+}++/* Duplicate the node whose index is ORG_IDX and set the constraint CONSTRAINT.+   Return the index of the new node, or -1 if insufficient storage is+   available.  */++static int+duplicate_node (re_dfa_t *dfa, int org_idx, unsigned int constraint)+{+  int dup_idx = re_dfa_add_node (dfa, dfa->nodes[org_idx]);+  if (BE (dup_idx != -1, 1))+    {+      dfa->nodes[dup_idx].constraint = constraint;+      if (dfa->nodes[org_idx].type == ANCHOR)+	dfa->nodes[dup_idx].constraint |= dfa->nodes[org_idx].opr.ctx_type;+      dfa->nodes[dup_idx].duplicated = 1;++      /* Store the index of the original node.  */+      dfa->org_indices[dup_idx] = org_idx;+    }+  return dup_idx;+}++static reg_errcode_t+calc_inveclosure (re_dfa_t *dfa)+{+  int src, idx, ret;+  for (idx = 0; idx < dfa->nodes_len; ++idx)+    re_node_set_init_empty (dfa->inveclosures + idx);++  for (src = 0; src < dfa->nodes_len; ++src)+    {+      int *elems = dfa->eclosures[src].elems;+      for (idx = 0; idx < dfa->eclosures[src].nelem; ++idx)+	{+	  ret = re_node_set_insert_last (dfa->inveclosures + elems[idx], src);+	  if (BE (ret == -1, 0))+	    return REG_ESPACE;+	}+    }++  return REG_NOERROR;+}++/* Calculate "eclosure" for all the node in DFA.  */++static reg_errcode_t+calc_eclosure (re_dfa_t *dfa)+{+  int node_idx, incomplete;+#ifdef DEBUG+  assert (dfa->nodes_len > 0);+#endif+  incomplete = 0;+  /* For each nodes, calculate epsilon closure.  */+  for (node_idx = 0; ; ++node_idx)+    {+      reg_errcode_t err;+      re_node_set eclosure_elem;+      if (node_idx == dfa->nodes_len)+	{+	  if (!incomplete)+	    break;+	  incomplete = 0;+	  node_idx = 0;+	}++#ifdef DEBUG+      assert (dfa->eclosures[node_idx].nelem != -1);+#endif++      /* If we have already calculated, skip it.  */+      if (dfa->eclosures[node_idx].nelem != 0)+	continue;+      /* Calculate epsilon closure of `node_idx'.  */+      err = calc_eclosure_iter (&eclosure_elem, dfa, node_idx, 1);+      if (BE (err != REG_NOERROR, 0))+	return err;++      if (dfa->eclosures[node_idx].nelem == 0)+	{+	  incomplete = 1;+	  re_node_set_free (&eclosure_elem);+	}+    }+  return REG_NOERROR;+}++/* Calculate epsilon closure of NODE.  */++static reg_errcode_t+calc_eclosure_iter (re_node_set *new_set, re_dfa_t *dfa, int node, int root)+{+  reg_errcode_t err;+  unsigned int constraint;+  int i, incomplete;+  re_node_set eclosure;+  incomplete = 0;+  err = re_node_set_alloc (&eclosure, dfa->edests[node].nelem + 1);+  if (BE (err != REG_NOERROR, 0))+    return err;++  /* This indicates that we are calculating this node now.+     We reference this value to avoid infinite loop.  */+  dfa->eclosures[node].nelem = -1;++  constraint = ((dfa->nodes[node].type == ANCHOR)+		? dfa->nodes[node].opr.ctx_type : 0);+  /* If the current node has constraints, duplicate all nodes.+     Since they must inherit the constraints.  */+  if (constraint+      && dfa->edests[node].nelem+      && !dfa->nodes[dfa->edests[node].elems[0]].duplicated)+    {+      err = duplicate_node_closure (dfa, node, node, node, constraint);+      if (BE (err != REG_NOERROR, 0))+	return err;+    }++  /* Expand each epsilon destination nodes.  */+  if (IS_EPSILON_NODE(dfa->nodes[node].type))+    for (i = 0; i < dfa->edests[node].nelem; ++i)+      {+	re_node_set eclosure_elem;+	int edest = dfa->edests[node].elems[i];+	/* If calculating the epsilon closure of `edest' is in progress,+	   return intermediate result.  */+	if (dfa->eclosures[edest].nelem == -1)+	  {+	    incomplete = 1;+	    continue;+	  }+	/* If we haven't calculated the epsilon closure of `edest' yet,+	   calculate now. Otherwise use calculated epsilon closure.  */+	if (dfa->eclosures[edest].nelem == 0)+	  {+	    err = calc_eclosure_iter (&eclosure_elem, dfa, edest, 0);+	    if (BE (err != REG_NOERROR, 0))+	      return err;+	  }+	else+	  eclosure_elem = dfa->eclosures[edest];+	/* Merge the epsilon closure of `edest'.  */+	re_node_set_merge (&eclosure, &eclosure_elem);+	/* If the epsilon closure of `edest' is incomplete,+	   the epsilon closure of this node is also incomplete.  */+	if (dfa->eclosures[edest].nelem == 0)+	  {+	    incomplete = 1;+	    re_node_set_free (&eclosure_elem);+	  }+      }++  /* Epsilon closures include itself.  */+  re_node_set_insert (&eclosure, node);+  if (incomplete && !root)+    dfa->eclosures[node].nelem = 0;+  else+    dfa->eclosures[node] = eclosure;+  *new_set = eclosure;+  return REG_NOERROR;+}++/* Functions for token which are used in the parser.  */++/* Fetch a token from INPUT.+   We must not use this function inside bracket expressions.  */++static void+internal_function+fetch_token (re_token_t *result, re_string_t *input, reg_syntax_t syntax)+{+  re_string_skip_bytes (input, peek_token (result, input, syntax));+}++/* Peek a token from INPUT, and return the length of the token.+   We must not use this function inside bracket expressions.  */++static int+internal_function+peek_token (re_token_t *token, re_string_t *input, reg_syntax_t syntax)+{+  unsigned char c;++  if (re_string_eoi (input))+    {+      token->type = END_OF_RE;+      return 0;+    }++  c = re_string_peek_byte (input, 0);+  token->opr.c = c;++  token->word_char = 0;+#ifdef RE_ENABLE_I18N+  token->mb_partial = 0;+  if (input->mb_cur_max > 1 &&+      !re_string_first_byte (input, re_string_cur_idx (input)))+    {+      token->type = CHARACTER;+      token->mb_partial = 1;+      return 1;+    }+#endif+  if (c == '\\')+    {+      unsigned char c2;+      if (re_string_cur_idx (input) + 1 >= re_string_length (input))+	{+	  token->type = BACK_SLASH;+	  return 1;+	}++      c2 = re_string_peek_byte_case (input, 1);+      token->opr.c = c2;+      token->type = CHARACTER;+#ifdef RE_ENABLE_I18N+      if (input->mb_cur_max > 1)+	{+	  wint_t wc = re_string_wchar_at (input,+					  re_string_cur_idx (input) + 1);+	  token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;+	}+      else+#endif+	token->word_char = IS_WORD_CHAR (c2) != 0;++      switch (c2)+	{+	case '|':+	  if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_NO_BK_VBAR))+	    token->type = OP_ALT;+	  break;+	case '1': case '2': case '3': case '4': case '5':+	case '6': case '7': case '8': case '9':+	  if (!(syntax & RE_NO_BK_REFS))+	    {+	      token->type = OP_BACK_REF;+	      token->opr.idx = c2 - '1';+	    }+	  break;+	case '<':+	  if (!(syntax & RE_NO_GNU_OPS))+	    {+	      token->type = ANCHOR;+	      token->opr.ctx_type = WORD_FIRST;+	    }+	  break;+	case '>':+	  if (!(syntax & RE_NO_GNU_OPS))+	    {+	      token->type = ANCHOR;+	      token->opr.ctx_type = WORD_LAST;+	    }+	  break;+	case 'b':+	  if (!(syntax & RE_NO_GNU_OPS))+	    {+	      token->type = ANCHOR;+	      token->opr.ctx_type = WORD_DELIM;+	    }+	  break;+	case 'B':+	  if (!(syntax & RE_NO_GNU_OPS))+	    {+	      token->type = ANCHOR;+	      token->opr.ctx_type = NOT_WORD_DELIM;+	    }+	  break;+	case 'w':+	  if (!(syntax & RE_NO_GNU_OPS))+	    token->type = OP_WORD;+	  break;+	case 'W':+	  if (!(syntax & RE_NO_GNU_OPS))+	    token->type = OP_NOTWORD;+	  break;+	case 's':+	  if (!(syntax & RE_NO_GNU_OPS))+	    token->type = OP_SPACE;+	  break;+	case 'S':+	  if (!(syntax & RE_NO_GNU_OPS))+	    token->type = OP_NOTSPACE;+	  break;+	case '`':+	  if (!(syntax & RE_NO_GNU_OPS))+	    {+	      token->type = ANCHOR;+	      token->opr.ctx_type = BUF_FIRST;+	    }+	  break;+	case '\'':+	  if (!(syntax & RE_NO_GNU_OPS))+	    {+	      token->type = ANCHOR;+	      token->opr.ctx_type = BUF_LAST;+	    }+	  break;+	case '(':+	  if (!(syntax & RE_NO_BK_PARENS))+	    token->type = OP_OPEN_SUBEXP;+	  break;+	case ')':+	  if (!(syntax & RE_NO_BK_PARENS))+	    token->type = OP_CLOSE_SUBEXP;+	  break;+	case '+':+	  if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))+	    token->type = OP_DUP_PLUS;+	  break;+	case '?':+	  if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_BK_PLUS_QM))+	    token->type = OP_DUP_QUESTION;+	  break;+	case '{':+	  if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))+	    token->type = OP_OPEN_DUP_NUM;+	  break;+	case '}':+	  if ((syntax & RE_INTERVALS) && (!(syntax & RE_NO_BK_BRACES)))+	    token->type = OP_CLOSE_DUP_NUM;+	  break;+	default:+	  break;+	}+      return 2;+    }++  token->type = CHARACTER;+#ifdef RE_ENABLE_I18N+  if (input->mb_cur_max > 1)+    {+      wint_t wc = re_string_wchar_at (input, re_string_cur_idx (input));+      token->word_char = IS_WIDE_WORD_CHAR (wc) != 0;+    }+  else+#endif+    token->word_char = IS_WORD_CHAR (token->opr.c);++  switch (c)+    {+    case '\n':+      if (syntax & RE_NEWLINE_ALT)+	token->type = OP_ALT;+      break;+    case '|':+      if (!(syntax & RE_LIMITED_OPS) && (syntax & RE_NO_BK_VBAR))+	token->type = OP_ALT;+      break;+    case '*':+      token->type = OP_DUP_ASTERISK;+      break;+    case '+':+      if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))+	token->type = OP_DUP_PLUS;+      break;+    case '?':+      if (!(syntax & RE_LIMITED_OPS) && !(syntax & RE_BK_PLUS_QM))+	token->type = OP_DUP_QUESTION;+      break;+    case '{':+      if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))+	token->type = OP_OPEN_DUP_NUM;+      break;+    case '}':+      if ((syntax & RE_INTERVALS) && (syntax & RE_NO_BK_BRACES))+	token->type = OP_CLOSE_DUP_NUM;+      break;+    case '(':+      if (syntax & RE_NO_BK_PARENS)+	token->type = OP_OPEN_SUBEXP;+      break;+    case ')':+      if (syntax & RE_NO_BK_PARENS)+	token->type = OP_CLOSE_SUBEXP;+      break;+    case '[':+      token->type = OP_OPEN_BRACKET;+      break;+    case '.':+      token->type = OP_PERIOD;+      break;+    case '^':+      if (!(syntax & (RE_CONTEXT_INDEP_ANCHORS | RE_CARET_ANCHORS_HERE)) &&+	  re_string_cur_idx (input) != 0)+	{+	  char prev = re_string_peek_byte (input, -1);+	  if (!(syntax & RE_NEWLINE_ALT) || prev != '\n')+	    break;+	}+      token->type = ANCHOR;+      token->opr.ctx_type = LINE_FIRST;+      break;+    case '$':+      if (!(syntax & RE_CONTEXT_INDEP_ANCHORS) &&+	  re_string_cur_idx (input) + 1 != re_string_length (input))+	{+	  re_token_t next;+	  re_string_skip_bytes (input, 1);+	  peek_token (&next, input, syntax);+	  re_string_skip_bytes (input, -1);+	  if (next.type != OP_ALT && next.type != OP_CLOSE_SUBEXP)+	    break;+	}+      token->type = ANCHOR;+      token->opr.ctx_type = LINE_LAST;+      break;+    default:+      break;+    }+  return 1;+}++/* Peek a token from INPUT, and return the length of the token.+   We must not use this function out of bracket expressions.  */++static int+internal_function+peek_token_bracket (re_token_t *token, re_string_t *input, reg_syntax_t syntax)+{+  unsigned char c;+  if (re_string_eoi (input))+    {+      token->type = END_OF_RE;+      return 0;+    }+  c = re_string_peek_byte (input, 0);+  token->opr.c = c;++#ifdef RE_ENABLE_I18N+  if (input->mb_cur_max > 1 &&+      !re_string_first_byte (input, re_string_cur_idx (input)))+    {+      token->type = CHARACTER;+      return 1;+    }+#endif /* RE_ENABLE_I18N */++  if (c == '\\' && (syntax & RE_BACKSLASH_ESCAPE_IN_LISTS)+      && re_string_cur_idx (input) + 1 < re_string_length (input))+    {+      /* In this case, '\' escape a character.  */+      unsigned char c2;+      re_string_skip_bytes (input, 1);+      c2 = re_string_peek_byte (input, 0);+      token->opr.c = c2;+      token->type = CHARACTER;+      return 1;+    }+  if (c == '[') /* '[' is a special char in a bracket exps.  */+    {+      unsigned char c2;+      int token_len;+      if (re_string_cur_idx (input) + 1 < re_string_length (input))+	c2 = re_string_peek_byte (input, 1);+      else+	c2 = 0;+      token->opr.c = c2;+      token_len = 2;+      switch (c2)+	{+	case '.':+	  token->type = OP_OPEN_COLL_ELEM;+	  break;+	case '=':+	  token->type = OP_OPEN_EQUIV_CLASS;+	  break;+	case ':':+	  if (syntax & RE_CHAR_CLASSES)+	    {+	      token->type = OP_OPEN_CHAR_CLASS;+	      break;+	    }+	  /* else fall through.  */+	default:+	  token->type = CHARACTER;+	  token->opr.c = c;+	  token_len = 1;+	  break;+	}+      return token_len;+    }+  switch (c)+    {+    case '-':+      token->type = OP_CHARSET_RANGE;+      break;+    case ']':+      token->type = OP_CLOSE_BRACKET;+      break;+    case '^':+      token->type = OP_NON_MATCH_LIST;+      break;+    default:+      token->type = CHARACTER;+    }+  return 1;+}++/* Functions for parser.  */++/* Entry point of the parser.+   Parse the regular expression REGEXP and return the structure tree.+   If an error is occured, ERR is set by error code, and return NULL.+   This function build the following tree, from regular expression <reg_exp>:+	   CAT+	   / \+	  /   \+   <reg_exp>  EOR++   CAT means concatenation.+   EOR means end of regular expression.  */++static bin_tree_t *+parse (re_string_t *regexp, regex_t *preg, reg_syntax_t syntax,+       reg_errcode_t *err)+{+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;+  bin_tree_t *tree, *eor, *root;+  re_token_t current_token;+  dfa->syntax = syntax;+  fetch_token (&current_token, regexp, syntax | RE_CARET_ANCHORS_HERE);+  tree = parse_reg_exp (regexp, preg, &current_token, syntax, 0, err);+  if (BE (*err != REG_NOERROR && tree == NULL, 0))+    return NULL;+  eor = create_tree (dfa, NULL, NULL, END_OF_RE);+  if (tree != NULL)+    root = create_tree (dfa, tree, eor, CONCAT);+  else+    root = eor;+  if (BE (eor == NULL || root == NULL, 0))+    {+      *err = REG_ESPACE;+      return NULL;+    }+  return root;+}++/* This function build the following tree, from regular expression+   <branch1>|<branch2>:+	   ALT+	   / \+	  /   \+   <branch1> <branch2>++   ALT means alternative, which represents the operator `|'.  */++static bin_tree_t *+parse_reg_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,+	       reg_syntax_t syntax, int nest, reg_errcode_t *err)+{+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;+  bin_tree_t *tree, *branch = NULL;+  tree = parse_branch (regexp, preg, token, syntax, nest, err);+  if (BE (*err != REG_NOERROR && tree == NULL, 0))+    return NULL;++  while (token->type == OP_ALT)+    {+      fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE);+      if (token->type != OP_ALT && token->type != END_OF_RE+	  && (nest == 0 || token->type != OP_CLOSE_SUBEXP))+	{+	  branch = parse_branch (regexp, preg, token, syntax, nest, err);+	  if (BE (*err != REG_NOERROR && branch == NULL, 0))+	    return NULL;+	}+      else+	branch = NULL;+      tree = create_tree (dfa, tree, branch, OP_ALT);+      if (BE (tree == NULL, 0))+	{+	  *err = REG_ESPACE;+	  return NULL;+	}+    }+  return tree;+}++/* This function build the following tree, from regular expression+   <exp1><exp2>:+	CAT+	/ \+       /   \+   <exp1> <exp2>++   CAT means concatenation.  */++static bin_tree_t *+parse_branch (re_string_t *regexp, regex_t *preg, re_token_t *token,+	      reg_syntax_t syntax, int nest, reg_errcode_t *err)+{+  bin_tree_t *tree, *exp;+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;+  tree = parse_expression (regexp, preg, token, syntax, nest, err);+  if (BE (*err != REG_NOERROR && tree == NULL, 0))+    return NULL;++  while (token->type != OP_ALT && token->type != END_OF_RE+	 && (nest == 0 || token->type != OP_CLOSE_SUBEXP))+    {+      exp = parse_expression (regexp, preg, token, syntax, nest, err);+      if (BE (*err != REG_NOERROR && exp == NULL, 0))+	{+	  return NULL;+	}+      if (tree != NULL && exp != NULL)+	{+	  tree = create_tree (dfa, tree, exp, CONCAT);+	  if (tree == NULL)+	    {+	      *err = REG_ESPACE;+	      return NULL;+	    }+	}+      else if (tree == NULL)+	tree = exp;+      /* Otherwise exp == NULL, we don't need to create new tree.  */+    }+  return tree;+}++/* This function build the following tree, from regular expression a*:+	 *+	 |+	 a+*/++static bin_tree_t *+parse_expression (re_string_t *regexp, regex_t *preg, re_token_t *token,+		  reg_syntax_t syntax, int nest, reg_errcode_t *err)+{+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;+  bin_tree_t *tree;+  switch (token->type)+    {+    case CHARACTER:+      tree = create_token_tree (dfa, NULL, NULL, token);+      if (BE (tree == NULL, 0))+	{+	  *err = REG_ESPACE;+	  return NULL;+	}+#ifdef RE_ENABLE_I18N+      if (dfa->mb_cur_max > 1)+	{+	  while (!re_string_eoi (regexp)+		 && !re_string_first_byte (regexp, re_string_cur_idx (regexp)))+	    {+	      bin_tree_t *mbc_remain;+	      fetch_token (token, regexp, syntax);+	      mbc_remain = create_token_tree (dfa, NULL, NULL, token);+	      tree = create_tree (dfa, tree, mbc_remain, CONCAT);+	      if (BE (mbc_remain == NULL || tree == NULL, 0))+		{+		  *err = REG_ESPACE;+		  return NULL;+		}+	    }+	}+#endif+      break;+    case OP_OPEN_SUBEXP:+      tree = parse_sub_exp (regexp, preg, token, syntax, nest + 1, err);+      if (BE (*err != REG_NOERROR && tree == NULL, 0))+	return NULL;+      break;+    case OP_OPEN_BRACKET:+      tree = parse_bracket_exp (regexp, dfa, token, syntax, err);+      if (BE (*err != REG_NOERROR && tree == NULL, 0))+	return NULL;+      break;+    case OP_BACK_REF:+      if (!BE (dfa->completed_bkref_map & (1 << token->opr.idx), 1))+	{+	  *err = REG_ESUBREG;+	  return NULL;+	}+      dfa->used_bkref_map |= 1 << token->opr.idx;+      tree = create_token_tree (dfa, NULL, NULL, token);+      if (BE (tree == NULL, 0))+	{+	  *err = REG_ESPACE;+	  return NULL;+	}+      ++dfa->nbackref;+      dfa->has_mb_node = 1;+      break;+    case OP_OPEN_DUP_NUM:+      if (syntax & RE_CONTEXT_INVALID_DUP)+	{+	  *err = REG_BADRPT;+	  return NULL;+	}+      /* FALLTHROUGH */+    case OP_DUP_ASTERISK:+    case OP_DUP_PLUS:+    case OP_DUP_QUESTION:+      if (syntax & RE_CONTEXT_INVALID_OPS)+	{+	  *err = REG_BADRPT;+	  return NULL;+	}+      else if (syntax & RE_CONTEXT_INDEP_OPS)+	{+	  fetch_token (token, regexp, syntax);+	  return parse_expression (regexp, preg, token, syntax, nest, err);+	}+      /* else fall through  */+    case OP_CLOSE_SUBEXP:+      if ((token->type == OP_CLOSE_SUBEXP) &&+	  !(syntax & RE_UNMATCHED_RIGHT_PAREN_ORD))+	{+	  *err = REG_ERPAREN;+	  return NULL;+	}+      /* else fall through  */+    case OP_CLOSE_DUP_NUM:+      /* We treat it as a normal character.  */++      /* Then we can these characters as normal characters.  */+      token->type = CHARACTER;+      /* mb_partial and word_char bits should be initialized already+	 by peek_token.  */+      tree = create_token_tree (dfa, NULL, NULL, token);+      if (BE (tree == NULL, 0))+	{+	  *err = REG_ESPACE;+	  return NULL;+	}+      break;+    case ANCHOR:+      if ((token->opr.ctx_type+	   & (WORD_DELIM | NOT_WORD_DELIM | WORD_FIRST | WORD_LAST))+	  && dfa->word_ops_used == 0)+	init_word_char (dfa);+      if (token->opr.ctx_type == WORD_DELIM+          || token->opr.ctx_type == NOT_WORD_DELIM)+	{+	  bin_tree_t *tree_first, *tree_last;+	  if (token->opr.ctx_type == WORD_DELIM)+	    {+	      token->opr.ctx_type = WORD_FIRST;+	      tree_first = create_token_tree (dfa, NULL, NULL, token);+	      token->opr.ctx_type = WORD_LAST;+            }+          else+            {+	      token->opr.ctx_type = INSIDE_WORD;+	      tree_first = create_token_tree (dfa, NULL, NULL, token);+	      token->opr.ctx_type = INSIDE_NOTWORD;+            }+	  tree_last = create_token_tree (dfa, NULL, NULL, token);+	  tree = create_tree (dfa, tree_first, tree_last, OP_ALT);+	  if (BE (tree_first == NULL || tree_last == NULL || tree == NULL, 0))+	    {+	      *err = REG_ESPACE;+	      return NULL;+	    }+	}+      else+	{+	  tree = create_token_tree (dfa, NULL, NULL, token);+	  if (BE (tree == NULL, 0))+	    {+	      *err = REG_ESPACE;+	      return NULL;+	    }+	}+      /* We must return here, since ANCHORs can't be followed+	 by repetition operators.+	 eg. RE"^*" is invalid or "<ANCHOR(^)><CHAR(*)>",+	     it must not be "<ANCHOR(^)><REPEAT(*)>".  */+      fetch_token (token, regexp, syntax);+      return tree;+    case OP_PERIOD:+      tree = create_token_tree (dfa, NULL, NULL, token);+      if (BE (tree == NULL, 0))+	{+	  *err = REG_ESPACE;+	  return NULL;+	}+      if (dfa->mb_cur_max > 1)+	dfa->has_mb_node = 1;+      break;+    case OP_WORD:+    case OP_NOTWORD:+      tree = build_charclass_op (dfa, regexp->trans,+				 (const unsigned char *) "alnum",+				 (const unsigned char *) "_",+				 token->type == OP_NOTWORD, err);+      if (BE (*err != REG_NOERROR && tree == NULL, 0))+	return NULL;+      break;+    case OP_SPACE:+    case OP_NOTSPACE:+      tree = build_charclass_op (dfa, regexp->trans,+				 (const unsigned char *) "space",+				 (const unsigned char *) "",+				 token->type == OP_NOTSPACE, err);+      if (BE (*err != REG_NOERROR && tree == NULL, 0))+	return NULL;+      break;+    case OP_ALT:+    case END_OF_RE:+      return NULL;+    case BACK_SLASH:+      *err = REG_EESCAPE;+      return NULL;+    default:+      /* Must not happen?  */+#ifdef DEBUG+      assert (0);+#endif+      return NULL;+    }+  fetch_token (token, regexp, syntax);++  while (token->type == OP_DUP_ASTERISK || token->type == OP_DUP_PLUS+	 || token->type == OP_DUP_QUESTION || token->type == OP_OPEN_DUP_NUM)+    {+      tree = parse_dup_op (tree, regexp, dfa, token, syntax, err);+      if (BE (*err != REG_NOERROR && tree == NULL, 0))+	return NULL;+      /* In BRE consecutive duplications are not allowed.  */+      if ((syntax & RE_CONTEXT_INVALID_DUP)+	  && (token->type == OP_DUP_ASTERISK+	      || token->type == OP_OPEN_DUP_NUM))+	{+	  *err = REG_BADRPT;+	  return NULL;+	}+    }++  return tree;+}++/* This function build the following tree, from regular expression+   (<reg_exp>):+	 SUBEXP+	    |+	<reg_exp>+*/++static bin_tree_t *+parse_sub_exp (re_string_t *regexp, regex_t *preg, re_token_t *token,+	       reg_syntax_t syntax, int nest, reg_errcode_t *err)+{+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;+  bin_tree_t *tree;+  size_t cur_nsub;+  cur_nsub = preg->re_nsub++;++  fetch_token (token, regexp, syntax | RE_CARET_ANCHORS_HERE);++  /* The subexpression may be a null string.  */+  if (token->type == OP_CLOSE_SUBEXP)+    tree = NULL;+  else+    {+      tree = parse_reg_exp (regexp, preg, token, syntax, nest, err);+      if (BE (*err == REG_NOERROR && token->type != OP_CLOSE_SUBEXP, 0))+        *err = REG_EPAREN;+      if (BE (*err != REG_NOERROR, 0))+	return NULL;+    }++  if (cur_nsub <= '9' - '1')+    dfa->completed_bkref_map |= 1 << cur_nsub;++  tree = create_tree (dfa, tree, NULL, SUBEXP);+  if (BE (tree == NULL, 0))+    {+      *err = REG_ESPACE;+      return NULL;+    }+  tree->token.opr.idx = cur_nsub;+  return tree;+}++/* This function parse repetition operators like "*", "+", "{1,3}" etc.  */++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)+{+  bin_tree_t *tree = NULL, *old_tree = NULL;+  int i, start, end, start_idx = re_string_cur_idx (regexp);+  re_token_t start_token = *token;++  if (token->type == OP_OPEN_DUP_NUM)+    {+      end = 0;+      start = fetch_number (regexp, token, syntax);+      if (start == -1)+	{+	  if (token->type == CHARACTER && token->opr.c == ',')+	    start = 0; /* We treat "{,m}" as "{0,m}".  */+	  else+	    {+	      *err = REG_BADBR; /* <re>{} is invalid.  */+	      return NULL;+	    }+	}+      if (BE (start != -2, 1))+	{+	  /* We treat "{n}" as "{n,n}".  */+	  end = ((token->type == OP_CLOSE_DUP_NUM) ? start+		 : ((token->type == CHARACTER && token->opr.c == ',')+		    ? fetch_number (regexp, token, syntax) : -2));+	}+      if (BE (start == -2 || end == -2, 0))+	{+	  /* Invalid sequence.  */+	  if (BE (!(syntax & RE_INVALID_INTERVAL_ORD), 0))+	    {+	      if (token->type == END_OF_RE)+		*err = REG_EBRACE;+	      else+		*err = REG_BADBR;++	      return NULL;+	    }++	  /* If the syntax bit is set, rollback.  */+	  re_string_set_index (regexp, start_idx);+	  *token = start_token;+	  token->type = CHARACTER;+	  /* mb_partial and word_char bits should be already initialized by+	     peek_token.  */+	  return elem;+	}++      if (BE (end != -1 && start > end, 0))+	{+	  /* First number greater than second.  */+	  *err = REG_BADBR;+	  return NULL;+	}+    }+  else+    {+      start = (token->type == OP_DUP_PLUS) ? 1 : 0;+      end = (token->type == OP_DUP_QUESTION) ? 1 : -1;+    }++  fetch_token (token, regexp, syntax);++  if (BE (elem == NULL, 0))+    return NULL;+  if (BE (start == 0 && end == 0, 0))+    {+      postorder (elem, free_tree, NULL);+      return NULL;+    }++  /* Extract "<re>{n,m}" to "<re><re>...<re><re>{0,<m-n>}".  */+  if (BE (start > 0, 0))+    {+      tree = elem;+      for (i = 2; i <= start; ++i)+	{+	  elem = duplicate_tree (elem, dfa);+	  tree = create_tree (dfa, tree, elem, CONCAT);+	  if (BE (elem == NULL || tree == NULL, 0))+	    goto parse_dup_op_espace;+	}++      if (start == end)+	return tree;++      /* Duplicate ELEM before it is marked optional.  */+      elem = duplicate_tree (elem, dfa);+      old_tree = tree;+    }+  else+    old_tree = NULL;++  if (elem->token.type == SUBEXP)+    postorder (elem, mark_opt_subexp, (void *) (intptr_t) elem->token.opr.idx);++  tree = create_tree (dfa, elem, NULL, (end == -1 ? OP_DUP_ASTERISK : OP_ALT));+  if (BE (tree == NULL, 0))+    goto parse_dup_op_espace;++  /* This loop is actually executed only when end != -1,+     to rewrite <re>{0,n} as (<re>(<re>...<re>?)?)?...  We have+     already created the start+1-th copy.  */+  for (i = start + 2; i <= end; ++i)+    {+      elem = duplicate_tree (elem, dfa);+      tree = create_tree (dfa, tree, elem, CONCAT);+      if (BE (elem == NULL || tree == NULL, 0))+        goto parse_dup_op_espace;++      tree = create_tree (dfa, tree, NULL, OP_ALT);+      if (BE (tree == NULL, 0))+        goto parse_dup_op_espace;+    }++  if (old_tree)+    tree = create_tree (dfa, old_tree, tree, CONCAT);++  return tree;++ parse_dup_op_espace:+  *err = REG_ESPACE;+  return NULL;+}++/* Size of the names for collating symbol/equivalence_class/character_class.+   I'm not sure, but maybe enough.  */+#define BRACKET_NAME_BUF_SIZE 32++#ifndef _LIBC+  /* Local function for parse_bracket_exp only used in case of NOT _LIBC.+     Build the range expression which starts from START_ELEM, and ends+     at END_ELEM.  The result are written to MBCSET and SBCSET.+     RANGE_ALLOC is the allocated size of mbcset->range_starts, and+     mbcset->range_ends, is a pointer argument sinse we may+     update it.  */++static reg_errcode_t+internal_function+# ifdef RE_ENABLE_I18N+build_range_exp (bitset_t sbcset, re_charset_t *mbcset, int *range_alloc,+		 bracket_elem_t *start_elem, bracket_elem_t *end_elem)+# else /* not RE_ENABLE_I18N */+build_range_exp (bitset_t sbcset, bracket_elem_t *start_elem,+		 bracket_elem_t *end_elem)+# endif /* not RE_ENABLE_I18N */+{+  unsigned int start_ch, end_ch;+  /* Equivalence Classes and Character Classes can't be a range start/end.  */+  if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS+	  || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS,+	  0))+    return REG_ERANGE;++  /* We can handle no multi character collating elements without libc+     support.  */+  if (BE ((start_elem->type == COLL_SYM+	   && strlen ((char *) start_elem->opr.name) > 1)+	  || (end_elem->type == COLL_SYM+	      && strlen ((char *) end_elem->opr.name) > 1), 0))+    return REG_ECOLLATE;++# ifdef RE_ENABLE_I18N+  {+    wchar_t wc;+    wint_t start_wc;+    wint_t end_wc;+    wchar_t cmp_buf[6] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'};++    start_ch = ((start_elem->type == SB_CHAR) ? start_elem->opr.ch+		: ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]+		   : 0));+    end_ch = ((end_elem->type == SB_CHAR) ? end_elem->opr.ch+	      : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]+		 : 0));+    start_wc = ((start_elem->type == SB_CHAR || start_elem->type == COLL_SYM)+		? __btowc (start_ch) : start_elem->opr.wch);+    end_wc = ((end_elem->type == SB_CHAR || end_elem->type == COLL_SYM)+	      ? __btowc (end_ch) : end_elem->opr.wch);+    if (start_wc == WEOF || end_wc == WEOF)+      return REG_ECOLLATE;+    cmp_buf[0] = start_wc;+    cmp_buf[4] = end_wc;+    if (wcscoll (cmp_buf, cmp_buf + 4) > 0)+      return REG_ERANGE;++    /* Got valid collation sequence values, add them as a new entry.+       However, for !_LIBC we have no collation elements: if the+       character set is single byte, the single byte character set+       that we build below suffices.  parse_bracket_exp passes+       no MBCSET if dfa->mb_cur_max == 1.  */+    if (mbcset)+      {+        /* Check the space of the arrays.  */+        if (BE (*range_alloc == mbcset->nranges, 0))+          {+	    /* There is not enough space, need realloc.  */+	    wchar_t *new_array_start, *new_array_end;+	    int new_nranges;++	    /* +1 in case of mbcset->nranges is 0.  */+	    new_nranges = 2 * mbcset->nranges + 1;+	    /* Use realloc since mbcset->range_starts and mbcset->range_ends+	       are NULL if *range_alloc == 0.  */+	    new_array_start = re_realloc (mbcset->range_starts, wchar_t,+				          new_nranges);+	    new_array_end = re_realloc (mbcset->range_ends, wchar_t,+				        new_nranges);++	    if (BE (new_array_start == NULL || new_array_end == NULL, 0))+	      return REG_ESPACE;++	    mbcset->range_starts = new_array_start;+	    mbcset->range_ends = new_array_end;+	    *range_alloc = new_nranges;+          }++        mbcset->range_starts[mbcset->nranges] = start_wc;+        mbcset->range_ends[mbcset->nranges++] = end_wc;+      }++    /* Build the table for single byte characters.  */+    for (wc = 0; wc < SBC_MAX; ++wc)+      {+	cmp_buf[2] = wc;+	if (wcscoll (cmp_buf, cmp_buf + 2) <= 0+	    && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0)+	  bitset_set (sbcset, wc);+      }+  }+# else /* not RE_ENABLE_I18N */+  {+    unsigned int ch;+    start_ch = ((start_elem->type == SB_CHAR ) ? start_elem->opr.ch+		: ((start_elem->type == COLL_SYM) ? start_elem->opr.name[0]+		   : 0));+    end_ch = ((end_elem->type == SB_CHAR ) ? end_elem->opr.ch+	      : ((end_elem->type == COLL_SYM) ? end_elem->opr.name[0]+		 : 0));+    if (start_ch > end_ch)+      return REG_ERANGE;+    /* Build the table for single byte characters.  */+    for (ch = 0; ch < SBC_MAX; ++ch)+      if (start_ch <= ch  && ch <= end_ch)+	bitset_set (sbcset, ch);+  }+# endif /* not RE_ENABLE_I18N */+  return REG_NOERROR;+}+#endif /* not _LIBC */++#ifndef _LIBC+/* Helper function for parse_bracket_exp only used in case of NOT _LIBC..+   Build the collating element which is represented by NAME.+   The result are written to MBCSET and SBCSET.+   COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a+   pointer argument since we may update it.  */++static reg_errcode_t+internal_function+# ifdef RE_ENABLE_I18N+build_collating_symbol (bitset_t sbcset, re_charset_t *mbcset,+			int *coll_sym_alloc, const unsigned char *name)+# else /* not RE_ENABLE_I18N */+build_collating_symbol (bitset_t sbcset, const unsigned char *name)+# endif /* not RE_ENABLE_I18N */+{+  size_t name_len = strlen ((const char *) name);+  if (BE (name_len != 1, 0))+    return REG_ECOLLATE;+  else+    {+      bitset_set (sbcset, name[0]);+      return REG_NOERROR;+    }+}+#endif /* not _LIBC */++/* This function parse bracket expression like "[abc]", "[a-c]",+   "[[.a-a.]]" etc.  */++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)+{+#ifdef _LIBC+  const unsigned char *collseqmb;+  const char *collseqwc;+  uint32_t nrules;+  int32_t table_size;+  const int32_t *symb_table;+  const unsigned char *extra;++  /* Local function for parse_bracket_exp used in _LIBC environement.+     Seek the collating symbol entry correspondings to NAME.+     Return the index of the symbol in the SYMB_TABLE.  */++  auto inline int32_t+  __attribute ((always_inline))+  seek_collating_symbol_entry (name, name_len)+	 const unsigned char *name;+	 size_t name_len;+    {+      int32_t hash = elem_hash ((const char *) name, name_len);+      int32_t elem = hash % table_size;+      if (symb_table[2 * elem] != 0)+	{+	  int32_t second = hash % (table_size - 2) + 1;++	  do+	    {+	      /* First compare the hashing value.  */+	      if (symb_table[2 * elem] == hash+		  /* Compare the length of the name.  */+		  && name_len == extra[symb_table[2 * elem + 1]]+		  /* Compare the name.  */+		  && memcmp (name, &extra[symb_table[2 * elem + 1] + 1],+			     name_len) == 0)+		{+		  /* Yep, this is the entry.  */+		  break;+		}++	      /* Next entry.  */+	      elem += second;+	    }+	  while (symb_table[2 * elem] != 0);+	}+      return elem;+    }++  /* Local function for parse_bracket_exp used in _LIBC environment.+     Look up the collation sequence value of BR_ELEM.+     Return the value if succeeded, UINT_MAX otherwise.  */++  auto inline unsigned int+  __attribute ((always_inline))+  lookup_collation_sequence_value (br_elem)+	 bracket_elem_t *br_elem;+    {+      if (br_elem->type == SB_CHAR)+	{+	  /*+	  if (MB_CUR_MAX == 1)+	  */+	  if (nrules == 0)+	    return collseqmb[br_elem->opr.ch];+	  else+	    {+	      wint_t wc = __btowc (br_elem->opr.ch);+	      return __collseq_table_lookup (collseqwc, wc);+	    }+	}+      else if (br_elem->type == MB_CHAR)+	{+	  if (nrules != 0)+	    return __collseq_table_lookup (collseqwc, br_elem->opr.wch);+	}+      else if (br_elem->type == COLL_SYM)+	{+	  size_t sym_name_len = strlen ((char *) br_elem->opr.name);+	  if (nrules != 0)+	    {+	      int32_t elem, idx;+	      elem = seek_collating_symbol_entry (br_elem->opr.name,+						  sym_name_len);+	      if (symb_table[2 * elem] != 0)+		{+		  /* We found the entry.  */+		  idx = symb_table[2 * elem + 1];+		  /* Skip the name of collating element name.  */+		  idx += 1 + extra[idx];+		  /* Skip the byte sequence of the collating element.  */+		  idx += 1 + extra[idx];+		  /* Adjust for the alignment.  */+		  idx = (idx + 3) & ~3;+		  /* Skip the multibyte collation sequence value.  */+		  idx += sizeof (unsigned int);+		  /* Skip the wide char sequence of the collating element.  */+		  idx += sizeof (unsigned int) *+		    (1 + *(unsigned int *) (extra + idx));+		  /* Return the collation sequence value.  */+		  return *(unsigned int *) (extra + idx);+		}+	      else if (symb_table[2 * elem] == 0 && sym_name_len == 1)+		{+		  /* No valid character.  Match it as a single byte+		     character.  */+		  return collseqmb[br_elem->opr.name[0]];+		}+	    }+	  else if (sym_name_len == 1)+	    return collseqmb[br_elem->opr.name[0]];+	}+      return UINT_MAX;+    }++  /* Local function for parse_bracket_exp used in _LIBC environement.+     Build the range expression which starts from START_ELEM, and ends+     at END_ELEM.  The result are written to MBCSET and SBCSET.+     RANGE_ALLOC is the allocated size of mbcset->range_starts, and+     mbcset->range_ends, is a pointer argument sinse we may+     update it.  */++  auto inline reg_errcode_t+  __attribute ((always_inline))+  build_range_exp (sbcset, mbcset, range_alloc, start_elem, end_elem)+	 re_charset_t *mbcset;+	 int *range_alloc;+	 bitset_t sbcset;+	 bracket_elem_t *start_elem, *end_elem;+    {+      unsigned int ch;+      uint32_t start_collseq;+      uint32_t end_collseq;++      /* Equivalence Classes and Character Classes can't be a range+	 start/end.  */+      if (BE (start_elem->type == EQUIV_CLASS || start_elem->type == CHAR_CLASS+	      || end_elem->type == EQUIV_CLASS || end_elem->type == CHAR_CLASS,+	      0))+	return REG_ERANGE;++      start_collseq = lookup_collation_sequence_value (start_elem);+      end_collseq = lookup_collation_sequence_value (end_elem);+      /* Check start/end collation sequence values.  */+      if (BE (start_collseq == UINT_MAX || end_collseq == UINT_MAX, 0))+	return REG_ECOLLATE;+      if (BE ((syntax & RE_NO_EMPTY_RANGES) && start_collseq > end_collseq, 0))+	return REG_ERANGE;++      /* Got valid collation sequence values, add them as a new entry.+	 However, if we have no collation elements, and the character set+	 is single byte, the single byte character set that we+	 build below suffices. */+      if (nrules > 0 || dfa->mb_cur_max > 1)+	{+          /* Check the space of the arrays.  */+          if (BE (*range_alloc == mbcset->nranges, 0))+	    {+	      /* There is not enough space, need realloc.  */+	      uint32_t *new_array_start;+	      uint32_t *new_array_end;+	      int new_nranges;++	      /* +1 in case of mbcset->nranges is 0.  */+	      new_nranges = 2 * mbcset->nranges + 1;+	      new_array_start = re_realloc (mbcset->range_starts, uint32_t,+					    new_nranges);+	      new_array_end = re_realloc (mbcset->range_ends, uint32_t,+				          new_nranges);++	      if (BE (new_array_start == NULL || new_array_end == NULL, 0))+	        return REG_ESPACE;++	      mbcset->range_starts = new_array_start;+	      mbcset->range_ends = new_array_end;+	      *range_alloc = new_nranges;+	    }++          mbcset->range_starts[mbcset->nranges] = start_collseq;+          mbcset->range_ends[mbcset->nranges++] = end_collseq;+	}++      /* Build the table for single byte characters.  */+      for (ch = 0; ch < SBC_MAX; ch++)+	{+	  uint32_t ch_collseq;+	  /*+	  if (MB_CUR_MAX == 1)+	  */+	  if (nrules == 0)+	    ch_collseq = collseqmb[ch];+	  else+	    ch_collseq = __collseq_table_lookup (collseqwc, __btowc (ch));+	  if (start_collseq <= ch_collseq && ch_collseq <= end_collseq)+	    bitset_set (sbcset, ch);+	}+      return REG_NOERROR;+    }++  /* Local function for parse_bracket_exp used in _LIBC environement.+     Build the collating element which is represented by NAME.+     The result are written to MBCSET and SBCSET.+     COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a+     pointer argument sinse we may update it.  */++  auto inline reg_errcode_t+  __attribute ((always_inline))+  build_collating_symbol (sbcset, mbcset, coll_sym_alloc, name)+	 re_charset_t *mbcset;+	 int *coll_sym_alloc;+	 bitset_t sbcset;+	 const unsigned char *name;+    {+      int32_t elem, idx;+      size_t name_len = strlen ((const char *) name);+      if (nrules != 0)+	{+	  elem = seek_collating_symbol_entry (name, name_len);+	  if (symb_table[2 * elem] != 0)+	    {+	      /* We found the entry.  */+	      idx = symb_table[2 * elem + 1];+	      /* Skip the name of collating element name.  */+	      idx += 1 + extra[idx];+	    }+	  else if (symb_table[2 * elem] == 0 && name_len == 1)+	    {+	      /* No valid character, treat it as a normal+		 character.  */+	      bitset_set (sbcset, name[0]);+	      return REG_NOERROR;+	    }+	  else+	    return REG_ECOLLATE;++	  /* Got valid collation sequence, add it as a new entry.  */+	  /* Check the space of the arrays.  */+	  if (BE (*coll_sym_alloc == mbcset->ncoll_syms, 0))+	    {+	      /* Not enough, realloc it.  */+	      /* +1 in case of mbcset->ncoll_syms is 0.  */+	      int new_coll_sym_alloc = 2 * mbcset->ncoll_syms + 1;+	      /* Use realloc since mbcset->coll_syms is NULL+		 if *alloc == 0.  */+	      int32_t *new_coll_syms = re_realloc (mbcset->coll_syms, int32_t,+						   new_coll_sym_alloc);+	      if (BE (new_coll_syms == NULL, 0))+		return REG_ESPACE;+	      mbcset->coll_syms = new_coll_syms;+	      *coll_sym_alloc = new_coll_sym_alloc;+	    }+	  mbcset->coll_syms[mbcset->ncoll_syms++] = idx;+	  return REG_NOERROR;+	}+      else+	{+	  if (BE (name_len != 1, 0))+	    return REG_ECOLLATE;+	  else+	    {+	      bitset_set (sbcset, name[0]);+	      return REG_NOERROR;+	    }+	}+    }+#endif++  re_token_t br_token;+  re_bitset_ptr_t sbcset;+#ifdef RE_ENABLE_I18N+  re_charset_t *mbcset;+  int coll_sym_alloc = 0, range_alloc = 0, mbchar_alloc = 0;+  int equiv_class_alloc = 0, char_class_alloc = 0;+#endif /* not RE_ENABLE_I18N */+  int non_match = 0;+  bin_tree_t *work_tree;+  int token_len;+  int first_round = 1;+#ifdef _LIBC+  collseqmb = (const unsigned char *)+    _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);+  nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);+  if (nrules)+    {+      /*+      if (MB_CUR_MAX > 1)+      */+      collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);+      table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB);+      symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE,+						  _NL_COLLATE_SYMB_TABLEMB);+      extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,+						   _NL_COLLATE_SYMB_EXTRAMB);+    }+#endif+  sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);+#ifdef RE_ENABLE_I18N+  mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);+#endif /* RE_ENABLE_I18N */+#ifdef RE_ENABLE_I18N+  if (BE (sbcset == NULL || mbcset == NULL, 0))+#else+  if (BE (sbcset == NULL, 0))+#endif /* RE_ENABLE_I18N */+    {+      *err = REG_ESPACE;+      return NULL;+    }++  token_len = peek_token_bracket (token, regexp, syntax);+  if (BE (token->type == END_OF_RE, 0))+    {+      *err = REG_BADPAT;+      goto parse_bracket_exp_free_return;+    }+  if (token->type == OP_NON_MATCH_LIST)+    {+#ifdef RE_ENABLE_I18N+      mbcset->non_match = 1;+#endif /* not RE_ENABLE_I18N */+      non_match = 1;+      if (syntax & RE_HAT_LISTS_NOT_NEWLINE)+	bitset_set (sbcset, '\n');+      re_string_skip_bytes (regexp, token_len); /* Skip a token.  */+      token_len = peek_token_bracket (token, regexp, syntax);+      if (BE (token->type == END_OF_RE, 0))+	{+	  *err = REG_BADPAT;+	  goto parse_bracket_exp_free_return;+	}+    }++  /* We treat the first ']' as a normal character.  */+  if (token->type == OP_CLOSE_BRACKET)+    token->type = CHARACTER;++  while (1)+    {+      bracket_elem_t start_elem, end_elem;+      unsigned char start_name_buf[BRACKET_NAME_BUF_SIZE];+      unsigned char end_name_buf[BRACKET_NAME_BUF_SIZE];+      reg_errcode_t ret;+      int token_len2 = 0, is_range_exp = 0;+      re_token_t token2;++      start_elem.opr.name = start_name_buf;+      ret = parse_bracket_element (&start_elem, regexp, token, token_len, dfa,+				   syntax, first_round);+      if (BE (ret != REG_NOERROR, 0))+	{+	  *err = ret;+	  goto parse_bracket_exp_free_return;+	}+      first_round = 0;++      /* Get information about the next token.  We need it in any case.  */+      token_len = peek_token_bracket (token, regexp, syntax);++      /* Do not check for ranges if we know they are not allowed.  */+      if (start_elem.type != CHAR_CLASS && start_elem.type != EQUIV_CLASS)+	{+	  if (BE (token->type == END_OF_RE, 0))+	    {+	      *err = REG_EBRACK;+	      goto parse_bracket_exp_free_return;+	    }+	  if (token->type == OP_CHARSET_RANGE)+	    {+	      re_string_skip_bytes (regexp, token_len); /* Skip '-'.  */+	      token_len2 = peek_token_bracket (&token2, regexp, syntax);+	      if (BE (token2.type == END_OF_RE, 0))+		{+		  *err = REG_EBRACK;+		  goto parse_bracket_exp_free_return;+		}+	      if (token2.type == OP_CLOSE_BRACKET)+		{+		  /* We treat the last '-' as a normal character.  */+		  re_string_skip_bytes (regexp, -token_len);+		  token->type = CHARACTER;+		}+	      else+		is_range_exp = 1;+	    }+	}++      if (is_range_exp == 1)+	{+	  end_elem.opr.name = end_name_buf;+	  ret = parse_bracket_element (&end_elem, regexp, &token2, token_len2,+				       dfa, syntax, 1);+	  if (BE (ret != REG_NOERROR, 0))+	    {+	      *err = ret;+	      goto parse_bracket_exp_free_return;+	    }++	  token_len = peek_token_bracket (token, regexp, syntax);++#ifdef _LIBC+	  *err = build_range_exp (sbcset, mbcset, &range_alloc,+				  &start_elem, &end_elem);+#else+# ifdef RE_ENABLE_I18N+	  *err = build_range_exp (sbcset,+				  dfa->mb_cur_max > 1 ? mbcset : NULL,+				  &range_alloc, &start_elem, &end_elem);+# else+	  *err = build_range_exp (sbcset, &start_elem, &end_elem);+# endif+#endif /* RE_ENABLE_I18N */+	  if (BE (*err != REG_NOERROR, 0))+	    goto parse_bracket_exp_free_return;+	}+      else+	{+	  switch (start_elem.type)+	    {+	    case SB_CHAR:+	      bitset_set (sbcset, start_elem.opr.ch);+	      break;+#ifdef RE_ENABLE_I18N+	    case MB_CHAR:+	      /* Check whether the array has enough space.  */+	      if (BE (mbchar_alloc == mbcset->nmbchars, 0))+		{+		  wchar_t *new_mbchars;+		  /* Not enough, realloc it.  */+		  /* +1 in case of mbcset->nmbchars is 0.  */+		  mbchar_alloc = 2 * mbcset->nmbchars + 1;+		  /* Use realloc since array is NULL if *alloc == 0.  */+		  new_mbchars = re_realloc (mbcset->mbchars, wchar_t,+					    mbchar_alloc);+		  if (BE (new_mbchars == NULL, 0))+		    goto parse_bracket_exp_espace;+		  mbcset->mbchars = new_mbchars;+		}+	      mbcset->mbchars[mbcset->nmbchars++] = start_elem.opr.wch;+	      break;+#endif /* RE_ENABLE_I18N */+	    case EQUIV_CLASS:+	      *err = build_equiv_class (sbcset,+#ifdef RE_ENABLE_I18N+					mbcset, &equiv_class_alloc,+#endif /* RE_ENABLE_I18N */+					start_elem.opr.name);+	      if (BE (*err != REG_NOERROR, 0))+		goto parse_bracket_exp_free_return;+	      break;+	    case COLL_SYM:+	      *err = build_collating_symbol (sbcset,+#ifdef RE_ENABLE_I18N+					     mbcset, &coll_sym_alloc,+#endif /* RE_ENABLE_I18N */+					     start_elem.opr.name);+	      if (BE (*err != REG_NOERROR, 0))+		goto parse_bracket_exp_free_return;+	      break;+	    case CHAR_CLASS:+	      *err = build_charclass (regexp->trans, sbcset,+#ifdef RE_ENABLE_I18N+				      mbcset, &char_class_alloc,+#endif /* RE_ENABLE_I18N */+				      start_elem.opr.name, syntax);+	      if (BE (*err != REG_NOERROR, 0))+	       goto parse_bracket_exp_free_return;+	      break;+	    default:+	      assert (0);+	      break;+	    }+	}+      if (BE (token->type == END_OF_RE, 0))+	{+	  *err = REG_EBRACK;+	  goto parse_bracket_exp_free_return;+	}+      if (token->type == OP_CLOSE_BRACKET)+	break;+    }++  re_string_skip_bytes (regexp, token_len); /* Skip a token.  */++  /* If it is non-matching list.  */+  if (non_match)+    bitset_not (sbcset);++#ifdef RE_ENABLE_I18N+  /* Ensure only single byte characters are set.  */+  if (dfa->mb_cur_max > 1)+    bitset_mask (sbcset, dfa->sb_char);++  if (mbcset->nmbchars || mbcset->ncoll_syms || mbcset->nequiv_classes+      || mbcset->nranges || (dfa->mb_cur_max > 1 && (mbcset->nchar_classes+						     || mbcset->non_match)))+    {+      bin_tree_t *mbc_tree;+      int sbc_idx;+      /* Build a tree for complex bracket.  */+      dfa->has_mb_node = 1;+      br_token.type = COMPLEX_BRACKET;+      br_token.opr.mbcset = mbcset;+      mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);+      if (BE (mbc_tree == NULL, 0))+	goto parse_bracket_exp_espace;+      for (sbc_idx = 0; sbc_idx < BITSET_WORDS; ++sbc_idx)+	if (sbcset[sbc_idx])+	  break;+      /* If there are no bits set in sbcset, there is no point+	 of having both SIMPLE_BRACKET and COMPLEX_BRACKET.  */+      if (sbc_idx < BITSET_WORDS)+	{+          /* Build a tree for simple bracket.  */+          br_token.type = SIMPLE_BRACKET;+          br_token.opr.sbcset = sbcset;+          work_tree = create_token_tree (dfa, NULL, NULL, &br_token);+          if (BE (work_tree == NULL, 0))+            goto parse_bracket_exp_espace;++          /* Then join them by ALT node.  */+          work_tree = create_tree (dfa, work_tree, mbc_tree, OP_ALT);+          if (BE (work_tree == NULL, 0))+            goto parse_bracket_exp_espace;+	}+      else+	{+	  re_free (sbcset);+	  work_tree = mbc_tree;+	}+    }+  else+#endif /* not RE_ENABLE_I18N */+    {+#ifdef RE_ENABLE_I18N+      free_charset (mbcset);+#endif+      /* Build a tree for simple bracket.  */+      br_token.type = SIMPLE_BRACKET;+      br_token.opr.sbcset = sbcset;+      work_tree = create_token_tree (dfa, NULL, NULL, &br_token);+      if (BE (work_tree == NULL, 0))+        goto parse_bracket_exp_espace;+    }+  return work_tree;++ parse_bracket_exp_espace:+  *err = REG_ESPACE;+ parse_bracket_exp_free_return:+  re_free (sbcset);+#ifdef RE_ENABLE_I18N+  free_charset (mbcset);+#endif /* RE_ENABLE_I18N */+  return NULL;+}++/* Parse an element in the bracket expression.  */++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, int accept_hyphen)+{+#ifdef RE_ENABLE_I18N+  int cur_char_size;+  cur_char_size = re_string_char_size_at (regexp, re_string_cur_idx (regexp));+  if (cur_char_size > 1)+    {+      elem->type = MB_CHAR;+      elem->opr.wch = re_string_wchar_at (regexp, re_string_cur_idx (regexp));+      re_string_skip_bytes (regexp, cur_char_size);+      return REG_NOERROR;+    }+#endif /* RE_ENABLE_I18N */+  re_string_skip_bytes (regexp, token_len); /* Skip a token.  */+  if (token->type == OP_OPEN_COLL_ELEM || token->type == OP_OPEN_CHAR_CLASS+      || token->type == OP_OPEN_EQUIV_CLASS)+    return parse_bracket_symbol (elem, regexp, token);+  if (BE (token->type == OP_CHARSET_RANGE, 0) && !accept_hyphen)+    {+      /* A '-' must only appear as anything but a range indicator before+	 the closing bracket.  Everything else is an error.  */+      re_token_t token2;+      (void) peek_token_bracket (&token2, regexp, syntax);+      if (token2.type != OP_CLOSE_BRACKET)+	/* The actual error value is not standardized since this whole+	   case is undefined.  But ERANGE makes good sense.  */+	return REG_ERANGE;+    }+  elem->type = SB_CHAR;+  elem->opr.ch = token->opr.c;+  return REG_NOERROR;+}++/* Parse a bracket symbol in the bracket expression.  Bracket symbols are+   such as [:<character_class>:], [.<collating_element>.], and+   [=<equivalent_class>=].  */++static reg_errcode_t+parse_bracket_symbol (bracket_elem_t *elem, re_string_t *regexp,+		      re_token_t *token)+{+  unsigned char ch, delim = token->opr.c;+  int i = 0;+  if (re_string_eoi(regexp))+    return REG_EBRACK;+  for (;; ++i)+    {+      if (i >= BRACKET_NAME_BUF_SIZE)+	return REG_EBRACK;+      if (token->type == OP_OPEN_CHAR_CLASS)+	ch = re_string_fetch_byte_case (regexp);+      else+	ch = re_string_fetch_byte (regexp);+      if (re_string_eoi(regexp))+	return REG_EBRACK;+      if (ch == delim && re_string_peek_byte (regexp, 0) == ']')+	break;+      elem->opr.name[i] = ch;+    }+  re_string_skip_bytes (regexp, 1);+  elem->opr.name[i] = '\0';+  switch (token->type)+    {+    case OP_OPEN_COLL_ELEM:+      elem->type = COLL_SYM;+      break;+    case OP_OPEN_EQUIV_CLASS:+      elem->type = EQUIV_CLASS;+      break;+    case OP_OPEN_CHAR_CLASS:+      elem->type = CHAR_CLASS;+      break;+    default:+      break;+    }+  return REG_NOERROR;+}++  /* Helper function for parse_bracket_exp.+     Build the equivalence class which is represented by NAME.+     The result are written to MBCSET and SBCSET.+     EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes,+     is a pointer argument sinse we may update it.  */++static reg_errcode_t+#ifdef RE_ENABLE_I18N+build_equiv_class (bitset_t sbcset, re_charset_t *mbcset,+		   int *equiv_class_alloc, const unsigned char *name)+#else /* not RE_ENABLE_I18N */+build_equiv_class (bitset_t sbcset, const unsigned char *name)+#endif /* not RE_ENABLE_I18N */+{+#ifdef _LIBC+  uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);+  if (nrules != 0)+    {+      const int32_t *table, *indirect;+      const unsigned char *weights, *extra, *cp;+      unsigned char char_buf[2];+      int32_t idx1, idx2;+      unsigned int ch;+      size_t len;+      /* This #include defines a local function!  */+# include <locale/weight.h>+      /* Calculate the index for equivalence class.  */+      cp = name;+      table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);+      weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE,+					       _NL_COLLATE_WEIGHTMB);+      extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE,+						   _NL_COLLATE_EXTRAMB);+      indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,+						_NL_COLLATE_INDIRECTMB);+      idx1 = findidx (&cp);+      if (BE (idx1 == 0 || cp < name + strlen ((const char *) name), 0))+	/* This isn't a valid character.  */+	return REG_ECOLLATE;++      /* Build single byte matcing table for this equivalence class.  */+      char_buf[1] = (unsigned char) '\0';+      len = weights[idx1 & 0xffffff];+      for (ch = 0; ch < SBC_MAX; ++ch)+	{+	  char_buf[0] = ch;+	  cp = char_buf;+	  idx2 = findidx (&cp);+/*+	  idx2 = table[ch];+*/+	  if (idx2 == 0)+	    /* This isn't a valid character.  */+	    continue;+	  /* Compare only if the length matches and the collation rule+	     index is the same.  */+	  if (len == weights[idx2 & 0xffffff] && (idx1 >> 24) == (idx2 >> 24))+	    {+	      int cnt = 0;++	      while (cnt <= len &&+		     weights[(idx1 & 0xffffff) + 1 + cnt]+		     == weights[(idx2 & 0xffffff) + 1 + cnt])+		++cnt;++	      if (cnt > len)+		bitset_set (sbcset, ch);+	    }+	}+      /* Check whether the array has enough space.  */+      if (BE (*equiv_class_alloc == mbcset->nequiv_classes, 0))+	{+	  /* Not enough, realloc it.  */+	  /* +1 in case of mbcset->nequiv_classes is 0.  */+	  int new_equiv_class_alloc = 2 * mbcset->nequiv_classes + 1;+	  /* Use realloc since the array is NULL if *alloc == 0.  */+	  int32_t *new_equiv_classes = re_realloc (mbcset->equiv_classes,+						   int32_t,+						   new_equiv_class_alloc);+	  if (BE (new_equiv_classes == NULL, 0))+	    return REG_ESPACE;+	  mbcset->equiv_classes = new_equiv_classes;+	  *equiv_class_alloc = new_equiv_class_alloc;+	}+      mbcset->equiv_classes[mbcset->nequiv_classes++] = idx1;+    }+  else+#endif /* _LIBC */+    {+      if (BE (strlen ((const char *) name) != 1, 0))+	return REG_ECOLLATE;+      bitset_set (sbcset, *name);+    }+  return REG_NOERROR;+}++  /* Helper function for parse_bracket_exp.+     Build the character class which is represented by NAME.+     The result are written to MBCSET and SBCSET.+     CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes,+     is a pointer argument sinse we may update it.  */++static reg_errcode_t+#ifdef RE_ENABLE_I18N+build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,+		 re_charset_t *mbcset, int *char_class_alloc,+		 const unsigned char *class_name, reg_syntax_t syntax)+#else /* not RE_ENABLE_I18N */+build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,+		 const unsigned char *class_name, reg_syntax_t syntax)+#endif /* not RE_ENABLE_I18N */+{+  int i;+  const char *name = (const char *) class_name;++  /* In case of REG_ICASE "upper" and "lower" match the both of+     upper and lower cases.  */+  if ((syntax & RE_ICASE)+      && (strcmp (name, "upper") == 0 || strcmp (name, "lower") == 0))+    name = "alpha";++#ifdef RE_ENABLE_I18N+  /* Check the space of the arrays.  */+  if (BE (*char_class_alloc == mbcset->nchar_classes, 0))+    {+      /* Not enough, realloc it.  */+      /* +1 in case of mbcset->nchar_classes is 0.  */+      int new_char_class_alloc = 2 * mbcset->nchar_classes + 1;+      /* Use realloc since array is NULL if *alloc == 0.  */+      wctype_t *new_char_classes = re_realloc (mbcset->char_classes, wctype_t,+					       new_char_class_alloc);+      if (BE (new_char_classes == NULL, 0))+	return REG_ESPACE;+      mbcset->char_classes = new_char_classes;+      *char_class_alloc = new_char_class_alloc;+    }+  mbcset->char_classes[mbcset->nchar_classes++] = __wctype (name);+#endif /* RE_ENABLE_I18N */++#define BUILD_CHARCLASS_LOOP(ctype_func)	\+  do {						\+    if (BE (trans != NULL, 0))			\+      {						\+	for (i = 0; i < SBC_MAX; ++i)		\+  	  if (ctype_func (i))			\+	    bitset_set (sbcset, trans[i]);	\+      }						\+    else					\+      {						\+	for (i = 0; i < SBC_MAX; ++i)		\+  	  if (ctype_func (i))			\+	    bitset_set (sbcset, i);		\+      }						\+  } while (0)++  if (strcmp (name, "alnum") == 0)+    BUILD_CHARCLASS_LOOP (isalnum);+  else if (strcmp (name, "cntrl") == 0)+    BUILD_CHARCLASS_LOOP (iscntrl);+  else if (strcmp (name, "lower") == 0)+    BUILD_CHARCLASS_LOOP (islower);+  else if (strcmp (name, "space") == 0)+    BUILD_CHARCLASS_LOOP (isspace);+  else if (strcmp (name, "alpha") == 0)+    BUILD_CHARCLASS_LOOP (isalpha);+  else if (strcmp (name, "digit") == 0)+    BUILD_CHARCLASS_LOOP (isdigit);+  else if (strcmp (name, "print") == 0)+    BUILD_CHARCLASS_LOOP (isprint);+  else if (strcmp (name, "upper") == 0)+    BUILD_CHARCLASS_LOOP (isupper);+  else if (strcmp (name, "blank") == 0)+    BUILD_CHARCLASS_LOOP (isblank);+  else if (strcmp (name, "graph") == 0)+    BUILD_CHARCLASS_LOOP (isgraph);+  else if (strcmp (name, "punct") == 0)+    BUILD_CHARCLASS_LOOP (ispunct);+  else if (strcmp (name, "xdigit") == 0)+    BUILD_CHARCLASS_LOOP (isxdigit);+  else+    return REG_ECTYPE;++  return REG_NOERROR;+}++static bin_tree_t *+build_charclass_op (re_dfa_t *dfa, RE_TRANSLATE_TYPE trans,+		    const unsigned char *class_name,+		    const unsigned char *extra, int non_match,+		    reg_errcode_t *err)+{+  re_bitset_ptr_t sbcset;+#ifdef RE_ENABLE_I18N+  re_charset_t *mbcset;+  int alloc = 0;+#endif /* not RE_ENABLE_I18N */+  reg_errcode_t ret;+  re_token_t br_token;+  bin_tree_t *tree;++  sbcset = (re_bitset_ptr_t) calloc (sizeof (bitset_t), 1);+#ifdef RE_ENABLE_I18N+  mbcset = (re_charset_t *) calloc (sizeof (re_charset_t), 1);+#endif /* RE_ENABLE_I18N */++#ifdef RE_ENABLE_I18N+  if (BE (sbcset == NULL || mbcset == NULL, 0))+#else /* not RE_ENABLE_I18N */+  if (BE (sbcset == NULL, 0))+#endif /* not RE_ENABLE_I18N */+    {+      *err = REG_ESPACE;+      return NULL;+    }++  if (non_match)+    {+#ifdef RE_ENABLE_I18N+      mbcset->non_match = 1;+#endif /* not RE_ENABLE_I18N */+    }++  /* We don't care the syntax in this case.  */+  ret = build_charclass (trans, sbcset,+#ifdef RE_ENABLE_I18N+			 mbcset, &alloc,+#endif /* RE_ENABLE_I18N */+			 class_name, 0);++  if (BE (ret != REG_NOERROR, 0))+    {+      re_free (sbcset);+#ifdef RE_ENABLE_I18N+      free_charset (mbcset);+#endif /* RE_ENABLE_I18N */+      *err = ret;+      return NULL;+    }+  /* \w match '_' also.  */+  for (; *extra; extra++)+    bitset_set (sbcset, *extra);++  /* If it is non-matching list.  */+  if (non_match)+    bitset_not (sbcset);++#ifdef RE_ENABLE_I18N+  /* Ensure only single byte characters are set.  */+  if (dfa->mb_cur_max > 1)+    bitset_mask (sbcset, dfa->sb_char);+#endif++  /* Build a tree for simple bracket.  */+  br_token.type = SIMPLE_BRACKET;+  br_token.opr.sbcset = sbcset;+  tree = create_token_tree (dfa, NULL, NULL, &br_token);+  if (BE (tree == NULL, 0))+    goto build_word_op_espace;++#ifdef RE_ENABLE_I18N+  if (dfa->mb_cur_max > 1)+    {+      bin_tree_t *mbc_tree;+      /* Build a tree for complex bracket.  */+      br_token.type = COMPLEX_BRACKET;+      br_token.opr.mbcset = mbcset;+      dfa->has_mb_node = 1;+      mbc_tree = create_token_tree (dfa, NULL, NULL, &br_token);+      if (BE (mbc_tree == NULL, 0))+	goto build_word_op_espace;+      /* Then join them by ALT node.  */+      tree = create_tree (dfa, tree, mbc_tree, OP_ALT);+      if (BE (mbc_tree != NULL, 1))+	return tree;+    }+  else+    {+      free_charset (mbcset);+      return tree;+    }+#else /* not RE_ENABLE_I18N */+  return tree;+#endif /* not RE_ENABLE_I18N */++ build_word_op_espace:+  re_free (sbcset);+#ifdef RE_ENABLE_I18N+  free_charset (mbcset);+#endif /* RE_ENABLE_I18N */+  *err = REG_ESPACE;+  return NULL;+}++/* This is intended for the expressions like "a{1,3}".+   Fetch a number from `input', and return the number.+   Return -1, if the number field is empty like "{,1}".+   Return -2, If an error is occured.  */++static int+fetch_number (re_string_t *input, re_token_t *token, reg_syntax_t syntax)+{+  int num = -1;+  unsigned char c;+  while (1)+    {+      fetch_token (token, input, syntax);+      c = token->opr.c;+      if (BE (token->type == END_OF_RE, 0))+	return -2;+      if (token->type == OP_CLOSE_DUP_NUM || c == ',')+	break;+      num = ((token->type != CHARACTER || c < '0' || '9' < c || num == -2)+	     ? -2 : ((num == -1) ? c - '0' : num * 10 + c - '0'));+      num = (num > RE_DUP_MAX) ? -2 : num;+    }+  return num;+}++#ifdef RE_ENABLE_I18N+static void+free_charset (re_charset_t *cset)+{+  re_free (cset->mbchars);+# ifdef _LIBC+  re_free (cset->coll_syms);+  re_free (cset->equiv_classes);+  re_free (cset->range_starts);+  re_free (cset->range_ends);+# endif+  re_free (cset->char_classes);+  re_free (cset);+}+#endif /* RE_ENABLE_I18N */++/* Functions for binary tree operation.  */++/* Create a tree node.  */++static bin_tree_t *+create_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,+	     re_token_type_t type)+{+  re_token_t t;+  t.type = type;+  return create_token_tree (dfa, left, right, &t);+}++static bin_tree_t *+create_token_tree (re_dfa_t *dfa, bin_tree_t *left, bin_tree_t *right,+		   const re_token_t *token)+{+  bin_tree_t *tree;+  if (BE (dfa->str_tree_storage_idx == BIN_TREE_STORAGE_SIZE, 0))+    {+      bin_tree_storage_t *storage = re_malloc (bin_tree_storage_t, 1);++      if (storage == NULL)+	return NULL;+      storage->next = dfa->str_tree_storage;+      dfa->str_tree_storage = storage;+      dfa->str_tree_storage_idx = 0;+    }+  tree = &dfa->str_tree_storage->data[dfa->str_tree_storage_idx++];++  tree->parent = NULL;+  tree->left = left;+  tree->right = right;+  tree->token = *token;+  tree->token.duplicated = 0;+  tree->token.opt_subexp = 0;+  tree->first = NULL;+  tree->next = NULL;+  tree->node_idx = -1;++  if (left != NULL)+    left->parent = tree;+  if (right != NULL)+    right->parent = tree;+  return tree;+}++/* Mark the tree SRC as an optional subexpression.+   To be called from preorder or postorder.  */++static reg_errcode_t+mark_opt_subexp (void *extra, bin_tree_t *node)+{+  int idx = (int) (intptr_t) extra;+  if (node->token.type == SUBEXP && node->token.opr.idx == idx)+    node->token.opt_subexp = 1;++  return REG_NOERROR;+}++/* Free the allocated memory inside NODE. */++static void+free_token (re_token_t *node)+{+#ifdef RE_ENABLE_I18N+  if (node->type == COMPLEX_BRACKET && node->duplicated == 0)+    free_charset (node->opr.mbcset);+  else+#endif /* RE_ENABLE_I18N */+    if (node->type == SIMPLE_BRACKET && node->duplicated == 0)+      re_free (node->opr.sbcset);+}++/* Worker function for tree walking.  Free the allocated memory inside NODE+   and its children. */++static reg_errcode_t+free_tree (void *extra, bin_tree_t *node)+{+  free_token (&node->token);+  return REG_NOERROR;+}+++/* Duplicate the node SRC, and return new node.  This is a preorder+   visit similar to the one implemented by the generic visitor, but+   we need more infrastructure to maintain two parallel trees --- so,+   it's easier to duplicate.  */++static bin_tree_t *+duplicate_tree (const bin_tree_t *root, re_dfa_t *dfa)+{+  const bin_tree_t *node;+  bin_tree_t *dup_root;+  bin_tree_t **p_new = &dup_root, *dup_node = root->parent;++  for (node = root; ; )+    {+      /* Create a new tree and link it back to the current parent.  */+      *p_new = create_token_tree (dfa, NULL, NULL, &node->token);+      if (*p_new == NULL)+	return NULL;+      (*p_new)->parent = dup_node;+      (*p_new)->token.duplicated = 1;+      dup_node = *p_new;++      /* Go to the left node, or up and to the right.  */+      if (node->left)+	{+	  node = node->left;+	  p_new = &dup_node->left;+	}+      else+	{+	  const bin_tree_t *prev = NULL;+	  while (node->right == prev || node->right == NULL)+	    {+	      prev = node;+	      node = node->parent;+	      dup_node = dup_node->parent;+	      if (!node)+	        return dup_root;+	    }+	  node = node->right;+	  p_new = &dup_node->right;+	}+    }+}
+ cbits/regex.c view
@@ -0,0 +1,74 @@+/* Extended regular expression matching and search library.+   Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc.+   This file is part of the GNU C Library.+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.++   The GNU C Library is free software; you can redistribute it and/or+   modify it under the terms of the GNU Lesser General Public+   License as published by the Free Software Foundation; either+   version 2.1 of the License, or (at your option) any later version.++   The GNU C Library is distributed in the hope that it will be useful,+   but WITHOUT ANY WARRANTY; without even the implied warranty of+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU+   Lesser General Public License for more details.++   You should have received a copy of the GNU Lesser General Public+   License along with the GNU C Library; if not, write to the Free+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA+   02111-1307 USA.  */++#ifdef HAVE_CONFIG_H+#include "config.h"+#endif++/* Make sure noone compiles this code with a C++ compiler.  */+#ifdef __cplusplus+# error "This is C code, use a C compiler"+#endif++#ifdef _LIBC+/* We have to keep the namespace clean.  */+# define regfree(preg) __regfree (preg)+# define regexec(pr, st, nm, pm, ef) __regexec (pr, st, nm, pm, ef)+# define regcomp(preg, pattern, cflags) __regcomp (preg, pattern, cflags)+# define regerror(errcode, preg, errbuf, errbuf_size) \+	__regerror(errcode, preg, errbuf, errbuf_size)+# define re_set_registers(bu, re, nu, st, en) \+	__re_set_registers (bu, re, nu, st, en)+# define re_match_2(bufp, string1, size1, string2, size2, pos, regs, stop) \+	__re_match_2 (bufp, string1, size1, string2, size2, pos, regs, stop)+# define re_match(bufp, string, size, pos, regs) \+	__re_match (bufp, string, size, pos, regs)+# define re_search(bufp, string, size, startpos, range, regs) \+	__re_search (bufp, string, size, startpos, range, regs)+# define re_compile_pattern(pattern, length, bufp) \+	__re_compile_pattern (pattern, length, bufp)+# define re_set_syntax(syntax) __re_set_syntax (syntax)+# define re_search_2(bufp, st1, s1, st2, s2, startpos, range, regs, stop) \+	__re_search_2 (bufp, st1, s1, st2, s2, startpos, range, regs, stop)+# define re_compile_fastmap(bufp) __re_compile_fastmap (bufp)++# include "../locale/localeinfo.h"+#endif++/* On some systems, limits.h sets RE_DUP_MAX to a lower value than+   GNU regex allows.  Include it before <regex.h>, which correctly+   #undefs RE_DUP_MAX and sets it to the right value.  */+#include <limits.h>++#include "regex.h"+#include "regex_internal.h"++#include "regex_internal.c"+#include "regcomp.c"+#include "regexec.c"++/* Binary backward compatibility.  */+#if _LIBC+# include <shlib-compat.h>+# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)+link_warning (re_max_failures, "the 're_max_failures' variable is obsolete and will go away.")+int re_max_failures = 2000;+# endif+#endif
+ cbits/regex.h view
@@ -0,0 +1,558 @@+/* Definitions for data structures and routines for the regular+   expression library.+   Copyright (C) 1985,1989-93,1995-98,2000,2001,2002,2003,2005,2006+   Free Software Foundation, Inc.+   This file is part of the GNU C Library.++   The GNU C Library is free software; you can redistribute it and/or+   modify it under the terms of the GNU Lesser General Public+   License as published by the Free Software Foundation; either+   version 2.1 of the License, or (at your option) any later version.++   The GNU C Library is distributed in the hope that it will be useful,+   but WITHOUT ANY WARRANTY; without even the implied warranty of+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU+   Lesser General Public License for more details.++   You should have received a copy of the GNU Lesser General Public+   License along with the GNU C Library; if not, write to the Free+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA+   02111-1307 USA.  */++#ifndef _REGEX_H+#define _REGEX_H 1++#include <sys/types.h>++#define REGEX_DLL_IMPEXP extern++/* Allow the use in C++ code.  */+#ifdef __cplusplus+extern "C" {+#endif++/* The following two types have to be signed and unsigned integer type+   wide enough to hold a value of a pointer.  For most ANSI compilers+   ptrdiff_t and size_t should be likely OK.  Still size of these two+   types is 2 for Microsoft C.  Ugh... */+typedef long int s_reg_t;+typedef unsigned long int active_reg_t;++/* The following bits are used to determine the regexp syntax we+   recognize.  The set/not-set meanings are chosen so that Emacs syntax+   remains the value 0.  The bits are given in alphabetical order, and+   the definitions shifted by one from the previous bit; thus, when we+   add or remove a bit, only one other definition need change.  */+typedef unsigned long int reg_syntax_t;++/* If this bit is not set, then \ inside a bracket expression is literal.+   If set, then such a \ quotes the following character.  */+#define RE_BACKSLASH_ESCAPE_IN_LISTS ((unsigned long int) 1)++/* If this bit is not set, then + and ? are operators, and \+ and \? are+     literals.+   If set, then \+ and \? are operators and + and ? are literals.  */+#define RE_BK_PLUS_QM (RE_BACKSLASH_ESCAPE_IN_LISTS << 1)++/* If this bit is set, then character classes are supported.  They are:+     [:alpha:], [:upper:], [:lower:],  [:digit:], [:alnum:], [:xdigit:],+     [:space:], [:print:], [:punct:], [:graph:], and [:cntrl:].+   If not set, then character classes are not supported.  */+#define RE_CHAR_CLASSES (RE_BK_PLUS_QM << 1)++/* If this bit is set, then ^ and $ are always anchors (outside bracket+     expressions, of course).+   If this bit is not set, then it depends:+        ^  is an anchor if it is at the beginning of a regular+           expression or after an open-group or an alternation operator;+        $  is an anchor if it is at the end of a regular expression, or+           before a close-group or an alternation operator.++   This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because+   POSIX draft 11.2 says that * etc. in leading positions is undefined.+   We already implemented a previous draft which made those constructs+   invalid, though, so we haven't changed the code back.  */+#define RE_CONTEXT_INDEP_ANCHORS (RE_CHAR_CLASSES << 1)++/* If this bit is set, then special characters are always special+     regardless of where they are in the pattern.+   If this bit is not set, then special characters are special only in+     some contexts; otherwise they are ordinary.  Specifically,+     * + ? and intervals are only special when not after the beginning,+     open-group, or alternation operator.  */+#define RE_CONTEXT_INDEP_OPS (RE_CONTEXT_INDEP_ANCHORS << 1)++/* If this bit is set, then *, +, ?, and { cannot be first in an re or+     immediately after an alternation or begin-group operator.  */+#define RE_CONTEXT_INVALID_OPS (RE_CONTEXT_INDEP_OPS << 1)++/* If this bit is set, then . matches newline.+   If not set, then it doesn't.  */+#define RE_DOT_NEWLINE (RE_CONTEXT_INVALID_OPS << 1)++/* If this bit is set, then . doesn't match NUL.+   If not set, then it does.  */+#define RE_DOT_NOT_NULL (RE_DOT_NEWLINE << 1)++/* If this bit is set, nonmatching lists [^...] do not match newline.+   If not set, they do.  */+#define RE_HAT_LISTS_NOT_NEWLINE (RE_DOT_NOT_NULL << 1)++/* If this bit is set, either \{...\} or {...} defines an+     interval, depending on RE_NO_BK_BRACES.+   If not set, \{, \}, {, and } are literals.  */+#define RE_INTERVALS (RE_HAT_LISTS_NOT_NEWLINE << 1)++/* If this bit is set, +, ? and | aren't recognized as operators.+   If not set, they are.  */+#define RE_LIMITED_OPS (RE_INTERVALS << 1)++/* If this bit is set, newline is an alternation operator.+   If not set, newline is literal.  */+#define RE_NEWLINE_ALT (RE_LIMITED_OPS << 1)++/* If this bit is set, then `{...}' defines an interval, and \{ and \}+     are literals.+  If not set, then `\{...\}' defines an interval.  */+#define RE_NO_BK_BRACES (RE_NEWLINE_ALT << 1)++/* If this bit is set, (...) defines a group, and \( and \) are literals.+   If not set, \(...\) defines a group, and ( and ) are literals.  */+#define RE_NO_BK_PARENS (RE_NO_BK_BRACES << 1)++/* If this bit is set, then \<digit> matches <digit>.+   If not set, then \<digit> is a back-reference.  */+#define RE_NO_BK_REFS (RE_NO_BK_PARENS << 1)++/* If this bit is set, then | is an alternation operator, and \| is literal.+   If not set, then \| is an alternation operator, and | is literal.  */+#define RE_NO_BK_VBAR (RE_NO_BK_REFS << 1)++/* If this bit is set, then an ending range point collating higher+     than the starting range point, as in [z-a], is invalid.+   If not set, then when ending range point collates higher than the+     starting range point, the range is ignored.  */+#define RE_NO_EMPTY_RANGES (RE_NO_BK_VBAR << 1)++/* If this bit is set, then an unmatched ) is ordinary.+   If not set, then an unmatched ) is invalid.  */+#define RE_UNMATCHED_RIGHT_PAREN_ORD (RE_NO_EMPTY_RANGES << 1)++/* If this bit is set, succeed as soon as we match the whole pattern,+   without further backtracking.  */+#define RE_NO_POSIX_BACKTRACKING (RE_UNMATCHED_RIGHT_PAREN_ORD << 1)++/* If this bit is set, do not process the GNU regex operators.+   If not set, then the GNU regex operators are recognized. */+#define RE_NO_GNU_OPS (RE_NO_POSIX_BACKTRACKING << 1)++/* If this bit is set, turn on internal regex debugging.+   If not set, and debugging was on, turn it off.+   This only works if regex.c is compiled -DDEBUG.+   We define this bit always, so that all that's needed to turn on+   debugging is to recompile regex.c; the calling code can always have+   this bit set, and it won't affect anything in the normal case. */+#define RE_DEBUG (RE_NO_GNU_OPS << 1)++/* If this bit is set, a syntactically invalid interval is treated as+   a string of ordinary characters.  For example, the ERE 'a{1' is+   treated as 'a\{1'.  */+#define RE_INVALID_INTERVAL_ORD (RE_DEBUG << 1)++/* If this bit is set, then ignore case when matching.+   If not set, then case is significant.  */+#define RE_ICASE (RE_INVALID_INTERVAL_ORD << 1)++/* This bit is used internally like RE_CONTEXT_INDEP_ANCHORS but only+   for ^, because it is difficult to scan the regex backwards to find+   whether ^ should be special.  */+#define RE_CARET_ANCHORS_HERE (RE_ICASE << 1)++/* If this bit is set, then \{ cannot be first in an bre or+   immediately after an alternation or begin-group operator.  */+#define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1)++/* If this bit is set, then no_sub will be set to 1 during+   re_compile_pattern.  */+#define RE_NO_SUB (RE_CONTEXT_INVALID_DUP << 1)++/* This global variable defines the particular regexp syntax to use (for+   some interfaces).  When a regexp is compiled, the syntax used is+   stored in the pattern buffer, so changing this does not affect+   already-compiled regexps.  */+REGEX_DLL_IMPEXP reg_syntax_t re_syntax_options;++/* Define combinations of the above bits for the standard possibilities.+   (The [[[ comments delimit what gets put into the Texinfo file, so+   don't delete them!)  */+/* [[[begin syntaxes]]] */+#define RE_SYNTAX_EMACS 0++#define RE_SYNTAX_AWK							\+  (RE_BACKSLASH_ESCAPE_IN_LISTS   | RE_DOT_NOT_NULL			\+   | RE_NO_BK_PARENS              | RE_NO_BK_REFS			\+   | RE_NO_BK_VBAR                | RE_NO_EMPTY_RANGES			\+   | RE_DOT_NEWLINE		  | RE_CONTEXT_INDEP_ANCHORS		\+   | RE_UNMATCHED_RIGHT_PAREN_ORD | RE_NO_GNU_OPS)++#define RE_SYNTAX_GNU_AWK						\+  ((RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS | RE_DEBUG)	\+   & ~(RE_DOT_NOT_NULL | RE_INTERVALS | RE_CONTEXT_INDEP_OPS		\+       | RE_CONTEXT_INVALID_OPS ))++#define RE_SYNTAX_POSIX_AWK						\+  (RE_SYNTAX_POSIX_EXTENDED | RE_BACKSLASH_ESCAPE_IN_LISTS		\+   | RE_INTERVALS	    | RE_NO_GNU_OPS)++#define RE_SYNTAX_GREP							\+  (RE_BK_PLUS_QM              | RE_CHAR_CLASSES				\+   | RE_HAT_LISTS_NOT_NEWLINE | RE_INTERVALS				\+   | RE_NEWLINE_ALT)++#define RE_SYNTAX_EGREP							\+  (RE_CHAR_CLASSES        | RE_CONTEXT_INDEP_ANCHORS			\+   | RE_CONTEXT_INDEP_OPS | RE_HAT_LISTS_NOT_NEWLINE			\+   | RE_NEWLINE_ALT       | RE_NO_BK_PARENS				\+   | RE_NO_BK_VBAR)++#define RE_SYNTAX_POSIX_EGREP						\+  (RE_SYNTAX_EGREP | RE_INTERVALS | RE_NO_BK_BRACES			\+   | RE_INVALID_INTERVAL_ORD)++/* P1003.2/D11.2, section 4.20.7.1, lines 5078ff.  */+#define RE_SYNTAX_ED RE_SYNTAX_POSIX_BASIC++#define RE_SYNTAX_SED RE_SYNTAX_POSIX_BASIC++/* Syntax bits common to both basic and extended POSIX regex syntax.  */+#define _RE_SYNTAX_POSIX_COMMON						\+  (RE_CHAR_CLASSES | RE_DOT_NEWLINE      | RE_DOT_NOT_NULL		\+   | RE_INTERVALS  | RE_NO_EMPTY_RANGES)++#define RE_SYNTAX_POSIX_BASIC						\+  (_RE_SYNTAX_POSIX_COMMON | RE_BK_PLUS_QM | RE_CONTEXT_INVALID_DUP)++/* Differs from ..._POSIX_BASIC only in that RE_BK_PLUS_QM becomes+   RE_LIMITED_OPS, i.e., \? \+ \| are not recognized.  Actually, this+   isn't minimal, since other operators, such as \`, aren't disabled.  */+#define RE_SYNTAX_POSIX_MINIMAL_BASIC					\+  (_RE_SYNTAX_POSIX_COMMON | RE_LIMITED_OPS)++#define RE_SYNTAX_POSIX_EXTENDED					\+  (_RE_SYNTAX_POSIX_COMMON  | RE_CONTEXT_INDEP_ANCHORS			\+   | RE_CONTEXT_INDEP_OPS   | RE_NO_BK_BRACES				\+   | RE_NO_BK_PARENS        | RE_NO_BK_VBAR				\+   | RE_CONTEXT_INVALID_OPS | RE_UNMATCHED_RIGHT_PAREN_ORD)++/* Differs from ..._POSIX_EXTENDED in that RE_CONTEXT_INDEP_OPS is+   removed and RE_NO_BK_REFS is added.  */+#define RE_SYNTAX_POSIX_MINIMAL_EXTENDED				\+  (_RE_SYNTAX_POSIX_COMMON  | RE_CONTEXT_INDEP_ANCHORS			\+   | RE_CONTEXT_INVALID_OPS | RE_NO_BK_BRACES				\+   | RE_NO_BK_PARENS        | RE_NO_BK_REFS				\+   | RE_NO_BK_VBAR	    | RE_UNMATCHED_RIGHT_PAREN_ORD)+/* [[[end syntaxes]]] */++/* Maximum number of duplicates an interval can allow.  Some systems+   (erroneously) define this in other header files, but we want our+   value, so remove any previous define.  */+#ifdef RE_DUP_MAX+# undef RE_DUP_MAX+#endif+/* If sizeof(int) == 2, then ((1 << 15) - 1) overflows.  */+#define RE_DUP_MAX (0x7fff)+++/* POSIX `cflags' bits (i.e., information for `regcomp').  */++/* If this bit is set, then use extended regular expression syntax.+   If not set, then use basic regular expression syntax.  */+#define REG_EXTENDED 1++/* If this bit is set, then ignore case when matching.+   If not set, then case is significant.  */+#define REG_ICASE (REG_EXTENDED << 1)++/* If this bit is set, then anchors do not match at newline+     characters in the string.+   If not set, then anchors do match at newlines.  */+#define REG_NEWLINE (REG_ICASE << 1)++/* If this bit is set, then report only success or fail in regexec.+   If not set, then returns differ between not matching and errors.  */+#define REG_NOSUB (REG_NEWLINE << 1)+++/* POSIX `eflags' bits (i.e., information for regexec).  */++/* If this bit is set, then the beginning-of-line operator doesn't match+     the beginning of the string (presumably because it's not the+     beginning of a line).+   If not set, then the beginning-of-line operator does match the+     beginning of the string.  */+#define REG_NOTBOL 1++/* Like REG_NOTBOL, except for the end-of-line.  */+#define REG_NOTEOL (1 << 1)++/* Use PMATCH[0] to delimit the start and end of the search in the+   buffer.  */+#define REG_STARTEND (1 << 2)+++/* If any error codes are removed, changed, or added, update the+   `re_error_msg' table in regex.c.  */+typedef enum+{+#ifdef _XOPEN_SOURCE+  REG_ENOSYS = -1,	/* This will never happen for this implementation.  */+#endif++  REG_NOERROR = 0,	/* Success.  */+  REG_NOMATCH,		/* Didn't find a match (for regexec).  */++  /* POSIX regcomp return error codes.  (In the order listed in the+     standard.)  */+  REG_BADPAT,		/* Invalid pattern.  */+  REG_ECOLLATE,		/* Inalid collating element.  */+  REG_ECTYPE,		/* Invalid character class name.  */+  REG_EESCAPE,		/* Trailing backslash.  */+  REG_ESUBREG,		/* Invalid back reference.  */+  REG_EBRACK,		/* Unmatched left bracket.  */+  REG_EPAREN,		/* Parenthesis imbalance.  */+  REG_EBRACE,		/* Unmatched \{.  */+  REG_BADBR,		/* Invalid contents of \{\}.  */+  REG_ERANGE,		/* Invalid range end.  */+  REG_ESPACE,		/* Ran out of memory.  */+  REG_BADRPT,		/* No preceding re for repetition op.  */++  /* Error codes we've added.  */+  REG_EEND,		/* Premature end.  */+  REG_ESIZE,		/* Compiled pattern bigger than 2^16 bytes.  */+  REG_ERPAREN		/* Unmatched ) or \); not returned from regcomp.  */+} reg_errcode_t;++/* This data structure represents a compiled pattern.  Before calling+   the pattern compiler, the fields `buffer', `allocated', `fastmap',+   `translate', and `no_sub' can be set.  After the pattern has been+   compiled, the `re_nsub' field is available.  All other fields are+   private to the regex routines.  */++#ifndef RE_TRANSLATE_TYPE+# define RE_TRANSLATE_TYPE unsigned char *+#endif++struct re_pattern_buffer+{+  /* Space that holds the compiled pattern.  It is declared as+     `unsigned char *' because its elements are sometimes used as+     array indexes.  */+  unsigned char *buffer;++  /* Number of bytes to which `buffer' points.  */+  unsigned long int allocated;++  /* Number of bytes actually used in `buffer'.  */+  unsigned long int used;++  /* Syntax setting with which the pattern was compiled.  */+  reg_syntax_t syntax;++  /* Pointer to a fastmap, if any, otherwise zero.  re_search uses the+     fastmap, if there is one, to skip over impossible starting points+     for matches.  */+  char *fastmap;++  /* Either a translate table to apply to all characters before+     comparing them, or zero for no translation.  The translation is+     applied to a pattern when it is compiled and to a string when it+     is matched.  */+  RE_TRANSLATE_TYPE translate;++  /* Number of subexpressions found by the compiler.  */+  size_t re_nsub;++  /* Zero if this pattern cannot match the empty string, one else.+     Well, in truth it's used only in `re_search_2', to see whether or+     not we should use the fastmap, so we don't set this absolutely+     perfectly; see `re_compile_fastmap' (the `duplicate' case).  */+  unsigned can_be_null : 1;++  /* If REGS_UNALLOCATED, allocate space in the `regs' structure+     for `max (RE_NREGS, re_nsub + 1)' groups.+     If REGS_REALLOCATE, reallocate space if necessary.+     If REGS_FIXED, use what's there.  */+#define REGS_UNALLOCATED 0+#define REGS_REALLOCATE 1+#define REGS_FIXED 2+  unsigned regs_allocated : 2;++  /* Set to zero when `regex_compile' compiles a pattern; set to one+     by `re_compile_fastmap' if it updates the fastmap.  */+  unsigned fastmap_accurate : 1;++  /* If set, `re_match_2' does not return information about+     subexpressions.  */+  unsigned no_sub : 1;++  /* If set, a beginning-of-line anchor doesn't match at the beginning+     of the string.  */+  unsigned not_bol : 1;++  /* Similarly for an end-of-line anchor.  */+  unsigned not_eol : 1;++  /* If true, an anchor at a newline matches.  */+  unsigned newline_anchor : 1;+};++typedef struct re_pattern_buffer regex_t;++/* Type for byte offsets within the string.  POSIX mandates this.  */+typedef int regoff_t;+++/* This is the structure we store register match data in.  See+   regex.texinfo for a full description of what registers match.  */+struct re_registers+{+  unsigned num_regs;+  regoff_t *start;+  regoff_t *end;+};+++/* If `regs_allocated' is REGS_UNALLOCATED in the pattern buffer,+   `re_match_2' returns information about at least this many registers+   the first time a `regs' structure is passed.  */+#ifndef RE_NREGS+# define RE_NREGS 30+#endif+++/* POSIX specification for registers.  Aside from the different names than+   `re_registers', POSIX uses an array of structures, instead of a+   structure of arrays.  */+typedef struct+{+  regoff_t rm_so;  /* Byte offset from string's start to substring's start.  */+  regoff_t rm_eo;  /* Byte offset from string's start to substring's end.  */+} regmatch_t;++/* Declarations for routines.  */++/* Sets the current default syntax to SYNTAX, and return the old syntax.+   You can also simply assign to the `re_syntax_options' variable.  */+REGEX_DLL_IMPEXP reg_syntax_t re_set_syntax (reg_syntax_t __syntax);++/* Compile the regular expression PATTERN, with length LENGTH+   and syntax given by the global `re_syntax_options', into the buffer+   BUFFER.  Return NULL if successful, and an error string if not.  */+REGEX_DLL_IMPEXP const char *re_compile_pattern (const char *__pattern, size_t __length,+				       struct re_pattern_buffer *__buffer);+++/* Compile a fastmap for the compiled pattern in BUFFER; used to+   accelerate searches.  Return 0 if successful and -2 if was an+   internal error.  */+REGEX_DLL_IMPEXP int re_compile_fastmap (struct re_pattern_buffer *__buffer);+++/* Search in the string STRING (with length LENGTH) for the pattern+   compiled into BUFFER.  Start searching at position START, for RANGE+   characters.  Return the starting position of the match, -1 for no+   match, or -2 for an internal error.  Also return register+   information in REGS (if REGS and BUFFER->no_sub are nonzero).  */+REGEX_DLL_IMPEXP int re_search (struct re_pattern_buffer *__buffer, const char *__string,+		      int __length, int __start, int __range,+		      struct re_registers *__regs);+++/* Like `re_search', but search in the concatenation of STRING1 and+   STRING2.  Also, stop searching at index START + STOP.  */+REGEX_DLL_IMPEXP int re_search_2 (struct re_pattern_buffer *__buffer,+			const char *__string1, int __length1,+			const char *__string2, int __length2, int __start,+			int __range, struct re_registers *__regs, int __stop);+++/* Like `re_search', but return how many characters in STRING the regexp+   in BUFFER matched, starting at position START.  */+REGEX_DLL_IMPEXP int re_match (struct re_pattern_buffer *__buffer, const char *__string,+		     int __length, int __start, struct re_registers *__regs);+++/* Relates to `re_match' as `re_search_2' relates to `re_search'.  */+REGEX_DLL_IMPEXP int re_match_2 (struct re_pattern_buffer *__buffer,+		       const char *__string1, int __length1,+		       const char *__string2, int __length2, int __start,+		       struct re_registers *__regs, int __stop);+++/* Set REGS to hold NUM_REGS registers, storing them in STARTS and+   ENDS.  Subsequent matches using BUFFER and REGS will use this memory+   for recording register information.  STARTS and ENDS must be+   allocated with malloc, and must each be at least `NUM_REGS * sizeof+   (regoff_t)' bytes long.++   If NUM_REGS == 0, then subsequent matches should allocate their own+   register data.++   Unless this function is called, the first search or match using+   PATTERN_BUFFER will allocate its own register data, without+   freeing the old data.  */+REGEX_DLL_IMPEXP void re_set_registers (struct re_pattern_buffer *__buffer,+			      struct re_registers *__regs,+			      unsigned int __num_regs,+			      regoff_t *__starts, regoff_t *__ends);++#if defined _REGEX_RE_COMP || defined _LIBC+# ifndef _CRAY+/* 4.2 bsd compatibility.  */+REGEX_DLL_IMPEXP char *re_comp (const char *);+REGEX_DLL_IMPEXP int re_exec (const char *);+# endif+#endif++/* GCC 2.95 and later have "__restrict"; C99 compilers have+   "restrict", and "configure" may have defined "restrict".  */+#ifndef __restrict+# if ! (2 < __GNUC__ || (2 == __GNUC__ && 95 <= __GNUC_MINOR__))+#  if defined restrict || 199901L <= __STDC_VERSION__+#   define __restrict restrict+#  else+#   define __restrict+#  endif+# endif+#endif+/* gcc 3.1 and up support the [restrict] syntax.  */+#ifndef __restrict_arr+# if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) \+     && !defined __GNUG__+#  define __restrict_arr __restrict+# else+#  define __restrict_arr+# endif+#endif++/* POSIX compatibility.  */+REGEX_DLL_IMPEXP int regcomp (regex_t *__restrict __preg,+		    const char *__restrict __pattern,+		    int __cflags);++REGEX_DLL_IMPEXP int regexec (const regex_t *__restrict __preg,+		    const char *__restrict __string, size_t __nmatch,+		    regmatch_t __pmatch[__restrict_arr],+		    int __eflags);++REGEX_DLL_IMPEXP size_t regerror (int __errcode, const regex_t *__restrict __preg,+			char *__restrict __errbuf, size_t __errbuf_size);++REGEX_DLL_IMPEXP void regfree (regex_t *__preg);+++#ifdef __cplusplus+}+#endif	/* C++ */++#endif /* regex.h */
+ cbits/regex_internal.c view
@@ -0,0 +1,1717 @@+/* Extended regular expression matching and search library.+   Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.+   This file is part of the GNU C Library.+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.++   The GNU C Library is free software; you can redistribute it and/or+   modify it under the terms of the GNU Lesser General Public+   License as published by the Free Software Foundation; either+   version 2.1 of the License, or (at your option) any later version.++   The GNU C Library is distributed in the hope that it will be useful,+   but WITHOUT ANY WARRANTY; without even the implied warranty of+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU+   Lesser General Public License for more details.++   You should have received a copy of the GNU Lesser General Public+   License along with the GNU C Library; if not, write to the Free+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA+   02111-1307 USA.  */++static void re_string_construct_common (const char *str, int len,+					re_string_t *pstr,+					RE_TRANSLATE_TYPE trans, int icase,+					const re_dfa_t *dfa) internal_function;+static re_dfastate_t *create_ci_newstate (const re_dfa_t *dfa,+					  const re_node_set *nodes,+					  unsigned int hash) internal_function;+static re_dfastate_t *create_cd_newstate (const re_dfa_t *dfa,+					  const re_node_set *nodes,+					  unsigned int context,+					  unsigned int hash) internal_function;++/* Functions for string operation.  */++/* This function allocate the buffers.  It is necessary to call+   re_string_reconstruct before using the object.  */++static reg_errcode_t+internal_function+re_string_allocate (re_string_t *pstr, const char *str, int len, int init_len,+		    RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa)+{+  reg_errcode_t ret;+  int init_buf_len;++  /* Ensure at least one character fits into the buffers.  */+  if (init_len < dfa->mb_cur_max)+    init_len = dfa->mb_cur_max;+  init_buf_len = (len + 1 < init_len) ? len + 1: init_len;+  re_string_construct_common (str, len, pstr, trans, icase, dfa);++  ret = re_string_realloc_buffers (pstr, init_buf_len);+  if (BE (ret != REG_NOERROR, 0))+    return ret;++  pstr->word_char = dfa->word_char;+  pstr->word_ops_used = dfa->word_ops_used;+  pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;+  pstr->valid_len = (pstr->mbs_allocated || dfa->mb_cur_max > 1) ? 0 : len;+  pstr->valid_raw_len = pstr->valid_len;+  return REG_NOERROR;+}++/* This function allocate the buffers, and initialize them.  */++static reg_errcode_t+internal_function+re_string_construct (re_string_t *pstr, const char *str, int len,+		     RE_TRANSLATE_TYPE trans, int icase, const re_dfa_t *dfa)+{+  reg_errcode_t ret;+  memset (pstr, '\0', sizeof (re_string_t));+  re_string_construct_common (str, len, pstr, trans, icase, dfa);++  if (len > 0)+    {+      ret = re_string_realloc_buffers (pstr, len + 1);+      if (BE (ret != REG_NOERROR, 0))+	return ret;+    }+  pstr->mbs = pstr->mbs_allocated ? pstr->mbs : (unsigned char *) str;++  if (icase)+    {+#ifdef RE_ENABLE_I18N+      if (dfa->mb_cur_max > 1)+	{+	  while (1)+	    {+	      ret = build_wcs_upper_buffer (pstr);+	      if (BE (ret != REG_NOERROR, 0))+		return ret;+	      if (pstr->valid_raw_len >= len)+		break;+	      if (pstr->bufs_len > pstr->valid_len + dfa->mb_cur_max)+		break;+	      ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);+	      if (BE (ret != REG_NOERROR, 0))+		return ret;+	    }+	}+      else+#endif /* RE_ENABLE_I18N  */+	build_upper_buffer (pstr);+    }+  else+    {+#ifdef RE_ENABLE_I18N+      if (dfa->mb_cur_max > 1)+	build_wcs_buffer (pstr);+      else+#endif /* RE_ENABLE_I18N  */+	{+	  if (trans != NULL)+	    re_string_translate_buffer (pstr);+	  else+	    {+	      pstr->valid_len = pstr->bufs_len;+	      pstr->valid_raw_len = pstr->bufs_len;+	    }+	}+    }++  return REG_NOERROR;+}++/* Helper functions for re_string_allocate, and re_string_construct.  */++static reg_errcode_t+internal_function+re_string_realloc_buffers (re_string_t *pstr, int new_buf_len)+{+#ifdef RE_ENABLE_I18N+  if (pstr->mb_cur_max > 1)+    {+      wint_t *new_wcs = re_realloc (pstr->wcs, wint_t, new_buf_len);+      if (BE (new_wcs == NULL, 0))+	return REG_ESPACE;+      pstr->wcs = new_wcs;+      if (pstr->offsets != NULL)+	{+	  int *new_offsets = re_realloc (pstr->offsets, int, new_buf_len);+	  if (BE (new_offsets == NULL, 0))+	    return REG_ESPACE;+	  pstr->offsets = new_offsets;+	}+    }+#endif /* RE_ENABLE_I18N  */+  if (pstr->mbs_allocated)+    {+      unsigned char *new_mbs = re_realloc (pstr->mbs, unsigned char,+					   new_buf_len);+      if (BE (new_mbs == NULL, 0))+	return REG_ESPACE;+      pstr->mbs = new_mbs;+    }+  pstr->bufs_len = new_buf_len;+  return REG_NOERROR;+}+++static void+internal_function+re_string_construct_common (const char *str, int len, re_string_t *pstr,+			    RE_TRANSLATE_TYPE trans, int icase,+			    const re_dfa_t *dfa)+{+  pstr->raw_mbs = (const unsigned char *) str;+  pstr->len = len;+  pstr->raw_len = len;+  pstr->trans = trans;+  pstr->icase = icase ? 1 : 0;+  pstr->mbs_allocated = (trans != NULL || icase);+  pstr->mb_cur_max = dfa->mb_cur_max;+  pstr->is_utf8 = dfa->is_utf8;+  pstr->map_notascii = dfa->map_notascii;+  pstr->stop = pstr->len;+  pstr->raw_stop = pstr->stop;+}++#ifdef RE_ENABLE_I18N++/* Build wide character buffer PSTR->WCS.+   If the byte sequence of the string are:+     <mb1>(0), <mb1>(1), <mb2>(0), <mb2>(1), <sb3>+   Then wide character buffer will be:+     <wc1>   , WEOF    , <wc2>   , WEOF    , <wc3>+   We use WEOF for padding, they indicate that the position isn't+   a first byte of a multibyte character.++   Note that this function assumes PSTR->VALID_LEN elements are already+   built and starts from PSTR->VALID_LEN.  */++static void+internal_function+build_wcs_buffer (re_string_t *pstr)+{+#ifdef _LIBC+  unsigned char buf[MB_LEN_MAX];+  assert (MB_LEN_MAX >= pstr->mb_cur_max);+#else+  unsigned char buf[64];+#endif+  mbstate_t prev_st;+  int byte_idx, end_idx, remain_len;+  size_t mbclen;++  /* Build the buffers from pstr->valid_len to either pstr->len or+     pstr->bufs_len.  */+  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;+  for (byte_idx = pstr->valid_len; byte_idx < end_idx;)+    {+      wchar_t wc;+      const char *p;++      remain_len = end_idx - byte_idx;+      prev_st = pstr->cur_state;+      /* Apply the translation if we need.  */+      if (BE (pstr->trans != NULL, 0))+	{+	  int i, ch;++	  for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)+	    {+	      ch = pstr->raw_mbs [pstr->raw_mbs_idx + byte_idx + i];+	      buf[i] = pstr->mbs[byte_idx + i] = pstr->trans[ch];+	    }+	  p = (const char *) buf;+	}+      else+	p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx;+      mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state);+      if (BE (mbclen == (size_t) -2, 0))+	{+	  /* The buffer doesn't have enough space, finish to build.  */+	  pstr->cur_state = prev_st;+	  break;+	}+      else if (BE (mbclen == (size_t) -1 || mbclen == 0, 0))+	{+	  /* We treat these cases as a singlebyte character.  */+	  mbclen = 1;+	  wc = (wchar_t) pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];+	  if (BE (pstr->trans != NULL, 0))+	    wc = pstr->trans[wc];+	  pstr->cur_state = prev_st;+	}++      /* Write wide character and padding.  */+      pstr->wcs[byte_idx++] = wc;+      /* Write paddings.  */+      for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)+	pstr->wcs[byte_idx++] = WEOF;+    }+  pstr->valid_len = byte_idx;+  pstr->valid_raw_len = byte_idx;+}++/* Build wide character buffer PSTR->WCS like build_wcs_buffer,+   but for REG_ICASE.  */++static reg_errcode_t+internal_function+build_wcs_upper_buffer (re_string_t *pstr)+{+  mbstate_t prev_st;+  int src_idx, byte_idx, end_idx, remain_len;+  size_t mbclen;+#ifdef _LIBC+  char buf[MB_LEN_MAX];+  assert (MB_LEN_MAX >= pstr->mb_cur_max);+#else+  char buf[64];+#endif++  byte_idx = pstr->valid_len;+  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;++  /* The following optimization assumes that ASCII characters can be+     mapped to wide characters with a simple cast.  */+  if (! pstr->map_notascii && pstr->trans == NULL && !pstr->offsets_needed)+    {+      while (byte_idx < end_idx)+	{+	  wchar_t wc;++	  if (isascii (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx])+	      && mbsinit (&pstr->cur_state))+	    {+	      /* In case of a singlebyte character.  */+	      pstr->mbs[byte_idx]+		= toupper (pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx]);+	      /* The next step uses the assumption that wchar_t is encoded+		 ASCII-safe: all ASCII values can be converted like this.  */+	      pstr->wcs[byte_idx] = (wchar_t) pstr->mbs[byte_idx];+	      ++byte_idx;+	      continue;+	    }++	  remain_len = end_idx - byte_idx;+	  prev_st = pstr->cur_state;+	  mbclen = mbrtowc (&wc,+			    ((const char *) pstr->raw_mbs + pstr->raw_mbs_idx+			     + byte_idx), remain_len, &pstr->cur_state);+	  if (BE (mbclen + 2 > 2, 1))+	    {+	      wchar_t wcu = wc;+	      if (iswlower (wc))+		{+		  size_t mbcdlen;++		  wcu = towupper (wc);+		  mbcdlen = wcrtomb (buf, wcu, &prev_st);+		  if (BE (mbclen == mbcdlen, 1))+		    memcpy (pstr->mbs + byte_idx, buf, mbclen);+		  else+		    {+		      src_idx = byte_idx;+		      goto offsets_needed;+		    }+		}+	      else+		memcpy (pstr->mbs + byte_idx,+			pstr->raw_mbs + pstr->raw_mbs_idx + byte_idx, mbclen);+	      pstr->wcs[byte_idx++] = wcu;+	      /* Write paddings.  */+	      for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)+		pstr->wcs[byte_idx++] = WEOF;+	    }+	  else if (mbclen == (size_t) -1 || mbclen == 0)+	    {+	      /* It is an invalid character or '\0'.  Just use the byte.  */+	      int ch = pstr->raw_mbs[pstr->raw_mbs_idx + byte_idx];+	      pstr->mbs[byte_idx] = ch;+	      /* And also cast it to wide char.  */+	      pstr->wcs[byte_idx++] = (wchar_t) ch;+	      if (BE (mbclen == (size_t) -1, 0))+		pstr->cur_state = prev_st;+	    }+	  else+	    {+	      /* The buffer doesn't have enough space, finish to build.  */+	      pstr->cur_state = prev_st;+	      break;+	    }+	}+      pstr->valid_len = byte_idx;+      pstr->valid_raw_len = byte_idx;+      return REG_NOERROR;+    }+  else+    for (src_idx = pstr->valid_raw_len; byte_idx < end_idx;)+      {+	wchar_t wc;+	const char *p;+      offsets_needed:+	remain_len = end_idx - byte_idx;+	prev_st = pstr->cur_state;+	if (BE (pstr->trans != NULL, 0))+	  {+	    int i, ch;++	    for (i = 0; i < pstr->mb_cur_max && i < remain_len; ++i)+	      {+		ch = pstr->raw_mbs [pstr->raw_mbs_idx + src_idx + i];+		buf[i] = pstr->trans[ch];+	      }+	    p = (const char *) buf;+	  }+	else+	  p = (const char *) pstr->raw_mbs + pstr->raw_mbs_idx + src_idx;+	mbclen = mbrtowc (&wc, p, remain_len, &pstr->cur_state);+	if (BE (mbclen + 2 > 2, 1))+	  {+	    wchar_t wcu = wc;+	    if (iswlower (wc))+	      {+		size_t mbcdlen;++		wcu = towupper (wc);+		mbcdlen = wcrtomb ((char *) buf, wcu, &prev_st);+		if (BE (mbclen == mbcdlen, 1))+		  memcpy (pstr->mbs + byte_idx, buf, mbclen);+		else if (mbcdlen != (size_t) -1)+		  {+		    size_t i;++		    if (byte_idx + mbcdlen > pstr->bufs_len)+		      {+			pstr->cur_state = prev_st;+			break;+		      }++		    if (pstr->offsets == NULL)+		      {+			pstr->offsets = re_malloc (int, pstr->bufs_len);++			if (pstr->offsets == NULL)+			  return REG_ESPACE;+		      }+		    if (!pstr->offsets_needed)+		      {+			for (i = 0; i < (size_t) byte_idx; ++i)+			  pstr->offsets[i] = i;+			pstr->offsets_needed = 1;+		      }++		    memcpy (pstr->mbs + byte_idx, buf, mbcdlen);+		    pstr->wcs[byte_idx] = wcu;+		    pstr->offsets[byte_idx] = src_idx;+		    for (i = 1; i < mbcdlen; ++i)+		      {+			pstr->offsets[byte_idx + i]+			  = src_idx + (i < mbclen ? i : mbclen - 1);+			pstr->wcs[byte_idx + i] = WEOF;+		      }+		    pstr->len += mbcdlen - mbclen;+		    if (pstr->raw_stop > src_idx)+		      pstr->stop += mbcdlen - mbclen;+		    end_idx = (pstr->bufs_len > pstr->len)+			      ? pstr->len : pstr->bufs_len;+		    byte_idx += mbcdlen;+		    src_idx += mbclen;+		    continue;+		  }+                else+                  memcpy (pstr->mbs + byte_idx, p, mbclen);+	      }+	    else+	      memcpy (pstr->mbs + byte_idx, p, mbclen);++	    if (BE (pstr->offsets_needed != 0, 0))+	      {+		size_t i;+		for (i = 0; i < mbclen; ++i)+		  pstr->offsets[byte_idx + i] = src_idx + i;+	      }+	    src_idx += mbclen;++	    pstr->wcs[byte_idx++] = wcu;+	    /* Write paddings.  */+	    for (remain_len = byte_idx + mbclen - 1; byte_idx < remain_len ;)+	      pstr->wcs[byte_idx++] = WEOF;+	  }+	else if (mbclen == (size_t) -1 || mbclen == 0)+	  {+	    /* It is an invalid character or '\0'.  Just use the byte.  */+	    int ch = pstr->raw_mbs[pstr->raw_mbs_idx + src_idx];++	    if (BE (pstr->trans != NULL, 0))+	      ch = pstr->trans [ch];+	    pstr->mbs[byte_idx] = ch;++	    if (BE (pstr->offsets_needed != 0, 0))+	      pstr->offsets[byte_idx] = src_idx;+	    ++src_idx;++	    /* And also cast it to wide char.  */+	    pstr->wcs[byte_idx++] = (wchar_t) ch;+	    if (BE (mbclen == (size_t) -1, 0))+	      pstr->cur_state = prev_st;+	  }+	else+	  {+	    /* The buffer doesn't have enough space, finish to build.  */+	    pstr->cur_state = prev_st;+	    break;+	  }+      }+  pstr->valid_len = byte_idx;+  pstr->valid_raw_len = src_idx;+  return REG_NOERROR;+}++/* Skip characters until the index becomes greater than NEW_RAW_IDX.+   Return the index.  */++static int+internal_function+re_string_skip_chars (re_string_t *pstr, int new_raw_idx, wint_t *last_wc)+{+  mbstate_t prev_st;+  int rawbuf_idx;+  size_t mbclen;+  wchar_t wc = WEOF;++  /* Skip the characters which are not necessary to check.  */+  for (rawbuf_idx = pstr->raw_mbs_idx + pstr->valid_raw_len;+       rawbuf_idx < new_raw_idx;)+    {+      int remain_len;+      remain_len = pstr->len - rawbuf_idx;+      prev_st = pstr->cur_state;+      mbclen = mbrtowc (&wc, (const char *) pstr->raw_mbs + rawbuf_idx,+			remain_len, &pstr->cur_state);+      if (BE (mbclen == (size_t) -2 || mbclen == (size_t) -1 || mbclen == 0, 0))+	{+	  /* We treat these cases as a single byte character.  */+	  if (mbclen == 0 || remain_len == 0)+	    wc = L'\0';+	  else+	    wc = *(unsigned char *) (pstr->raw_mbs + rawbuf_idx);+	  mbclen = 1;+	  pstr->cur_state = prev_st;+	}+      /* Then proceed the next character.  */+      rawbuf_idx += mbclen;+    }+  *last_wc = (wint_t) wc;+  return rawbuf_idx;+}+#endif /* RE_ENABLE_I18N  */++/* Build the buffer PSTR->MBS, and apply the translation if we need.+   This function is used in case of REG_ICASE.  */++static void+internal_function+build_upper_buffer (re_string_t *pstr)+{+  int char_idx, end_idx;+  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;++  for (char_idx = pstr->valid_len; char_idx < end_idx; ++char_idx)+    {+      int ch = pstr->raw_mbs[pstr->raw_mbs_idx + char_idx];+      if (BE (pstr->trans != NULL, 0))+	ch = pstr->trans[ch];+      if (islower (ch))+	pstr->mbs[char_idx] = toupper (ch);+      else+	pstr->mbs[char_idx] = ch;+    }+  pstr->valid_len = char_idx;+  pstr->valid_raw_len = char_idx;+}++/* Apply TRANS to the buffer in PSTR.  */++static void+internal_function+re_string_translate_buffer (re_string_t *pstr)+{+  int buf_idx, end_idx;+  end_idx = (pstr->bufs_len > pstr->len) ? pstr->len : pstr->bufs_len;++  for (buf_idx = pstr->valid_len; buf_idx < end_idx; ++buf_idx)+    {+      int ch = pstr->raw_mbs[pstr->raw_mbs_idx + buf_idx];+      pstr->mbs[buf_idx] = pstr->trans[ch];+    }++  pstr->valid_len = buf_idx;+  pstr->valid_raw_len = buf_idx;+}++/* This function re-construct the buffers.+   Concretely, convert to wide character in case of pstr->mb_cur_max > 1,+   convert to upper case in case of REG_ICASE, apply translation.  */++static reg_errcode_t+internal_function+re_string_reconstruct (re_string_t *pstr, int idx, int eflags)+{+  int offset = idx - pstr->raw_mbs_idx;+  if (BE (offset < 0, 0))+    {+      /* Reset buffer.  */+#ifdef RE_ENABLE_I18N+      if (pstr->mb_cur_max > 1)+	memset (&pstr->cur_state, '\0', sizeof (mbstate_t));+#endif /* RE_ENABLE_I18N */+      pstr->len = pstr->raw_len;+      pstr->stop = pstr->raw_stop;+      pstr->valid_len = 0;+      pstr->raw_mbs_idx = 0;+      pstr->valid_raw_len = 0;+      pstr->offsets_needed = 0;+      pstr->tip_context = ((eflags & REG_NOTBOL) ? CONTEXT_BEGBUF+			   : CONTEXT_NEWLINE | CONTEXT_BEGBUF);+      if (!pstr->mbs_allocated)+	pstr->mbs = (unsigned char *) pstr->raw_mbs;+      offset = idx;+    }++  if (BE (offset != 0, 1))+    {+      /* Should the already checked characters be kept?  */+      if (BE (offset < pstr->valid_raw_len, 1))+	{+	  /* Yes, move them to the front of the buffer.  */+#ifdef RE_ENABLE_I18N+	  if (BE (pstr->offsets_needed, 0))+	    {+	      int low = 0, high = pstr->valid_len, mid;+	      do+		{+		  mid = (high + low) / 2;+		  if (pstr->offsets[mid] > offset)+		    high = mid;+		  else if (pstr->offsets[mid] < offset)+		    low = mid + 1;+		  else+		    break;+		}+	      while (low < high);+	      if (pstr->offsets[mid] < offset)+		++mid;+	      pstr->tip_context = re_string_context_at (pstr, mid - 1,+							eflags);+	      /* This can be quite complicated, so handle specially+		 only the common and easy case where the character with+		 different length representation of lower and upper+		 case is present at or after offset.  */+	      if (pstr->valid_len > offset+		  && mid == offset && pstr->offsets[mid] == offset)+		{+		  memmove (pstr->wcs, pstr->wcs + offset,+			   (pstr->valid_len - offset) * sizeof (wint_t));+		  memmove (pstr->mbs, pstr->mbs + offset, pstr->valid_len - offset);+		  pstr->valid_len -= offset;+		  pstr->valid_raw_len -= offset;+		  for (low = 0; low < pstr->valid_len; low++)+		    pstr->offsets[low] = pstr->offsets[low + offset] - offset;+		}+	      else+		{+		  /* Otherwise, just find out how long the partial multibyte+		     character at offset is and fill it with WEOF/255.  */+		  pstr->len = pstr->raw_len - idx + offset;+		  pstr->stop = pstr->raw_stop - idx + offset;+		  pstr->offsets_needed = 0;+		  while (mid > 0 && pstr->offsets[mid - 1] == offset)+		    --mid;+		  while (mid < pstr->valid_len)+		    if (pstr->wcs[mid] != WEOF)+		      break;+		    else+		      ++mid;+		  if (mid == pstr->valid_len)+		    pstr->valid_len = 0;+		  else+		    {+		      pstr->valid_len = pstr->offsets[mid] - offset;+		      if (pstr->valid_len)+			{+			  for (low = 0; low < pstr->valid_len; ++low)+			    pstr->wcs[low] = WEOF;+			  memset (pstr->mbs, 255, pstr->valid_len);+			}+		    }+		  pstr->valid_raw_len = pstr->valid_len;+		}+	    }+	  else+#endif+	    {+	      pstr->tip_context = re_string_context_at (pstr, offset - 1,+							eflags);+#ifdef RE_ENABLE_I18N+	      if (pstr->mb_cur_max > 1)+		memmove (pstr->wcs, pstr->wcs + offset,+			 (pstr->valid_len - offset) * sizeof (wint_t));+#endif /* RE_ENABLE_I18N */+	      if (BE (pstr->mbs_allocated, 0))+		memmove (pstr->mbs, pstr->mbs + offset,+			 pstr->valid_len - offset);+	      pstr->valid_len -= offset;+	      pstr->valid_raw_len -= offset;+#if DEBUG+	      assert (pstr->valid_len > 0);+#endif+	    }+	}+      else+	{+	  /* No, skip all characters until IDX.  */+	  int prev_valid_len = pstr->valid_len;++#ifdef RE_ENABLE_I18N+	  if (BE (pstr->offsets_needed, 0))+	    {+	      pstr->len = pstr->raw_len - idx + offset;+	      pstr->stop = pstr->raw_stop - idx + offset;+	      pstr->offsets_needed = 0;+	    }+#endif+	  pstr->valid_len = 0;+#ifdef RE_ENABLE_I18N+	  if (pstr->mb_cur_max > 1)+	    {+	      int wcs_idx;+	      wint_t wc = WEOF;++	      if (pstr->is_utf8)+		{+		  const unsigned char *raw, *p, *q, *end;++		  /* Special case UTF-8.  Multi-byte chars start with any+		     byte other than 0x80 - 0xbf.  */+		  raw = pstr->raw_mbs + pstr->raw_mbs_idx;+		  end = raw + (offset - pstr->mb_cur_max);+		  if (end < pstr->raw_mbs)+		    end = pstr->raw_mbs;+		  p = raw + offset - 1;+#ifdef _LIBC+		  /* We know the wchar_t encoding is UCS4, so for the simple+		     case, ASCII characters, skip the conversion step.  */+		  if (isascii (*p) && BE (pstr->trans == NULL, 1))+		    {+		      memset (&pstr->cur_state, '\0', sizeof (mbstate_t));+		      /* pstr->valid_len = 0; */+		      wc = (wchar_t) *p;+		    }+		  else+#endif+		    for (; p >= end; --p)+		      if ((*p & 0xc0) != 0x80)+			{+			  mbstate_t cur_state;+			  wchar_t wc2;+			  int mlen = raw + pstr->len - p;+			  unsigned char buf[6];+			  size_t mbclen;++			  q = p;+			  if (BE (pstr->trans != NULL, 0))+			    {+			      int i = mlen < 6 ? mlen : 6;+			      while (--i >= 0)+				buf[i] = pstr->trans[p[i]];+			      q = buf;+			    }+			  /* XXX Don't use mbrtowc, we know which conversion+			     to use (UTF-8 -> UCS4).  */+			  memset (&cur_state, 0, sizeof (cur_state));+			  mbclen = mbrtowc (&wc2, (const char *) p, mlen,+					    &cur_state);+			  if (raw + offset - p <= mbclen+			      && mbclen < (size_t) -2)+			    {+			      memset (&pstr->cur_state, '\0',+				      sizeof (mbstate_t));+			      pstr->valid_len = mbclen - (raw + offset - p);+			      wc = wc2;+			    }+			  break;+			}+		}++	      if (wc == WEOF)+		pstr->valid_len = re_string_skip_chars (pstr, idx, &wc) - idx;+	      if (wc == WEOF)+		pstr->tip_context+		  = re_string_context_at (pstr, prev_valid_len - 1, eflags);+	      else+		pstr->tip_context = ((BE (pstr->word_ops_used != 0, 0)+				      && IS_WIDE_WORD_CHAR (wc))+				     ? CONTEXT_WORD+				     : ((IS_WIDE_NEWLINE (wc)+					 && pstr->newline_anchor)+					? CONTEXT_NEWLINE : 0));+	      if (BE (pstr->valid_len, 0))+		{+		  for (wcs_idx = 0; wcs_idx < pstr->valid_len; ++wcs_idx)+		    pstr->wcs[wcs_idx] = WEOF;+		  if (pstr->mbs_allocated)+		    memset (pstr->mbs, 255, pstr->valid_len);+		}+	      pstr->valid_raw_len = pstr->valid_len;+	    }+	  else+#endif /* RE_ENABLE_I18N */+	    {+	      int c = pstr->raw_mbs[pstr->raw_mbs_idx + offset - 1];+	      pstr->valid_raw_len = 0;+	      if (pstr->trans)+		c = pstr->trans[c];+	      pstr->tip_context = (bitset_contain (pstr->word_char, c)+				   ? CONTEXT_WORD+				   : ((IS_NEWLINE (c) && pstr->newline_anchor)+				      ? CONTEXT_NEWLINE : 0));+	    }+	}+      if (!BE (pstr->mbs_allocated, 0))+	pstr->mbs += offset;+    }+  pstr->raw_mbs_idx = idx;+  pstr->len -= offset;+  pstr->stop -= offset;++  /* Then build the buffers.  */+#ifdef RE_ENABLE_I18N+  if (pstr->mb_cur_max > 1)+    {+      if (pstr->icase)+	{+	  reg_errcode_t ret = build_wcs_upper_buffer (pstr);+	  if (BE (ret != REG_NOERROR, 0))+	    return ret;+	}+      else+	build_wcs_buffer (pstr);+    }+  else+#endif /* RE_ENABLE_I18N */+    if (BE (pstr->mbs_allocated, 0))+      {+	if (pstr->icase)+	  build_upper_buffer (pstr);+	else if (pstr->trans != NULL)+	  re_string_translate_buffer (pstr);+      }+    else+      pstr->valid_len = pstr->len;++  pstr->cur_idx = 0;+  return REG_NOERROR;+}++static unsigned char+internal_function __attribute ((pure))+re_string_peek_byte_case (const re_string_t *pstr, int idx)+{+  int ch, off;++  /* Handle the common (easiest) cases first.  */+  if (BE (!pstr->mbs_allocated, 1))+    return re_string_peek_byte (pstr, idx);++#ifdef RE_ENABLE_I18N+  if (pstr->mb_cur_max > 1+      && ! re_string_is_single_byte_char (pstr, pstr->cur_idx + idx))+    return re_string_peek_byte (pstr, idx);+#endif++  off = pstr->cur_idx + idx;+#ifdef RE_ENABLE_I18N+  if (pstr->offsets_needed)+    off = pstr->offsets[off];+#endif++  ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];++#ifdef RE_ENABLE_I18N+  /* Ensure that e.g. for tr_TR.UTF-8 BACKSLASH DOTLESS SMALL LETTER I+     this function returns CAPITAL LETTER I instead of first byte of+     DOTLESS SMALL LETTER I.  The latter would confuse the parser,+     since peek_byte_case doesn't advance cur_idx in any way.  */+  if (pstr->offsets_needed && !isascii (ch))+    return re_string_peek_byte (pstr, idx);+#endif++  return ch;+}++static unsigned char+internal_function __attribute ((pure))+re_string_fetch_byte_case (re_string_t *pstr)+{+  if (BE (!pstr->mbs_allocated, 1))+    return re_string_fetch_byte (pstr);++#ifdef RE_ENABLE_I18N+  if (pstr->offsets_needed)+    {+      int off, ch;++      /* For tr_TR.UTF-8 [[:islower:]] there is+	 [[: CAPITAL LETTER I WITH DOT lower:]] in mbs.  Skip+	 in that case the whole multi-byte character and return+	 the original letter.  On the other side, with+	 [[: DOTLESS SMALL LETTER I return [[:I, as doing+	 anything else would complicate things too much.  */++      if (!re_string_first_byte (pstr, pstr->cur_idx))+	return re_string_fetch_byte (pstr);++      off = pstr->offsets[pstr->cur_idx];+      ch = pstr->raw_mbs[pstr->raw_mbs_idx + off];++      if (! isascii (ch))+	return re_string_fetch_byte (pstr);++      re_string_skip_bytes (pstr,+			    re_string_char_size_at (pstr, pstr->cur_idx));+      return ch;+    }+#endif++  return pstr->raw_mbs[pstr->raw_mbs_idx + pstr->cur_idx++];+}++static void+internal_function+re_string_destruct (re_string_t *pstr)+{+#ifdef RE_ENABLE_I18N+  re_free (pstr->wcs);+  re_free (pstr->offsets);+#endif /* RE_ENABLE_I18N  */+  if (pstr->mbs_allocated)+    re_free (pstr->mbs);+}++/* Return the context at IDX in INPUT.  */++static unsigned int+internal_function+re_string_context_at (const re_string_t *input, int idx, int eflags)+{+  int c;+  if (BE (idx < 0, 0))+    /* In this case, we use the value stored in input->tip_context,+       since we can't know the character in input->mbs[-1] here.  */+    return input->tip_context;+  if (BE (idx == input->len, 0))+    return ((eflags & REG_NOTEOL) ? CONTEXT_ENDBUF+	    : CONTEXT_NEWLINE | CONTEXT_ENDBUF);+#ifdef RE_ENABLE_I18N+  if (input->mb_cur_max > 1)+    {+      wint_t wc;+      int wc_idx = idx;+      while(input->wcs[wc_idx] == WEOF)+	{+#ifdef DEBUG+	  /* It must not happen.  */+	  assert (wc_idx >= 0);+#endif+	  --wc_idx;+	  if (wc_idx < 0)+	    return input->tip_context;+	}+      wc = input->wcs[wc_idx];+      if (BE (input->word_ops_used != 0, 0) && IS_WIDE_WORD_CHAR (wc))+	return CONTEXT_WORD;+      return (IS_WIDE_NEWLINE (wc) && input->newline_anchor+	      ? CONTEXT_NEWLINE : 0);+    }+  else+#endif+    {+      c = re_string_byte_at (input, idx);+      if (bitset_contain (input->word_char, c))+	return CONTEXT_WORD;+      return IS_NEWLINE (c) && input->newline_anchor ? CONTEXT_NEWLINE : 0;+    }+}++/* Functions for set operation.  */++static reg_errcode_t+internal_function+re_node_set_alloc (re_node_set *set, int size)+{+  set->alloc = size;+  set->nelem = 0;+  set->elems = re_malloc (int, size);+  if (BE (set->elems == NULL, 0))+    return REG_ESPACE;+  return REG_NOERROR;+}++static reg_errcode_t+internal_function+re_node_set_init_1 (re_node_set *set, int elem)+{+  set->alloc = 1;+  set->nelem = 1;+  set->elems = re_malloc (int, 1);+  if (BE (set->elems == NULL, 0))+    {+      set->alloc = set->nelem = 0;+      return REG_ESPACE;+    }+  set->elems[0] = elem;+  return REG_NOERROR;+}++static reg_errcode_t+internal_function+re_node_set_init_2 (re_node_set *set, int elem1, int elem2)+{+  set->alloc = 2;+  set->elems = re_malloc (int, 2);+  if (BE (set->elems == NULL, 0))+    return REG_ESPACE;+  if (elem1 == elem2)+    {+      set->nelem = 1;+      set->elems[0] = elem1;+    }+  else+    {+      set->nelem = 2;+      if (elem1 < elem2)+	{+	  set->elems[0] = elem1;+	  set->elems[1] = elem2;+	}+      else+	{+	  set->elems[0] = elem2;+	  set->elems[1] = elem1;+	}+    }+  return REG_NOERROR;+}++static reg_errcode_t+internal_function+re_node_set_init_copy (re_node_set *dest, const re_node_set *src)+{+  dest->nelem = src->nelem;+  if (src->nelem > 0)+    {+      dest->alloc = dest->nelem;+      dest->elems = re_malloc (int, dest->alloc);+      if (BE (dest->elems == NULL, 0))+	{+	  dest->alloc = dest->nelem = 0;+	  return REG_ESPACE;+	}+      memcpy (dest->elems, src->elems, src->nelem * sizeof (int));+    }+  else+    re_node_set_init_empty (dest);+  return REG_NOERROR;+}++/* Calculate the intersection of the sets SRC1 and SRC2. And merge it to+   DEST. Return value indicate the error code or REG_NOERROR if succeeded.+   Note: We assume dest->elems is NULL, when dest->alloc is 0.  */++static reg_errcode_t+internal_function+re_node_set_add_intersect (re_node_set *dest, const re_node_set *src1,+			   const re_node_set *src2)+{+  int i1, i2, is, id, delta, sbase;+  if (src1->nelem == 0 || src2->nelem == 0)+    return REG_NOERROR;++  /* We need dest->nelem + 2 * elems_in_intersection; this is a+     conservative estimate.  */+  if (src1->nelem + src2->nelem + dest->nelem > dest->alloc)+    {+      int new_alloc = src1->nelem + src2->nelem + dest->alloc;+      int *new_elems = re_realloc (dest->elems, int, new_alloc);+      if (BE (new_elems == NULL, 0))+        return REG_ESPACE;+      dest->elems = new_elems;+      dest->alloc = new_alloc;+    }++  /* Find the items in the intersection of SRC1 and SRC2, and copy+     into the top of DEST those that are not already in DEST itself.  */+  sbase = dest->nelem + src1->nelem + src2->nelem;+  i1 = src1->nelem - 1;+  i2 = src2->nelem - 1;+  id = dest->nelem - 1;+  for (;;)+    {+      if (src1->elems[i1] == src2->elems[i2])+	{+	  /* Try to find the item in DEST.  Maybe we could binary search?  */+	  while (id >= 0 && dest->elems[id] > src1->elems[i1])+	    --id;++          if (id < 0 || dest->elems[id] != src1->elems[i1])+            dest->elems[--sbase] = src1->elems[i1];++	  if (--i1 < 0 || --i2 < 0)+	    break;+	}++      /* Lower the highest of the two items.  */+      else if (src1->elems[i1] < src2->elems[i2])+	{+	  if (--i2 < 0)+	    break;+	}+      else+	{+	  if (--i1 < 0)+	    break;+	}+    }++  id = dest->nelem - 1;+  is = dest->nelem + src1->nelem + src2->nelem - 1;+  delta = is - sbase + 1;++  /* Now copy.  When DELTA becomes zero, the remaining+     DEST elements are already in place; this is more or+     less the same loop that is in re_node_set_merge.  */+  dest->nelem += delta;+  if (delta > 0 && id >= 0)+    for (;;)+      {+        if (dest->elems[is] > dest->elems[id])+          {+            /* Copy from the top.  */+            dest->elems[id + delta--] = dest->elems[is--];+            if (delta == 0)+              break;+          }+        else+          {+            /* Slide from the bottom.  */+            dest->elems[id + delta] = dest->elems[id];+            if (--id < 0)+              break;+          }+      }++  /* Copy remaining SRC elements.  */+  memcpy (dest->elems, dest->elems + sbase, delta * sizeof (int));++  return REG_NOERROR;+}++/* Calculate the union set of the sets SRC1 and SRC2. And store it to+   DEST. Return value indicate the error code or REG_NOERROR if succeeded.  */++static reg_errcode_t+internal_function+re_node_set_init_union (re_node_set *dest, const re_node_set *src1,+			const re_node_set *src2)+{+  int i1, i2, id;+  if (src1 != NULL && src1->nelem > 0 && src2 != NULL && src2->nelem > 0)+    {+      dest->alloc = src1->nelem + src2->nelem;+      dest->elems = re_malloc (int, dest->alloc);+      if (BE (dest->elems == NULL, 0))+	return REG_ESPACE;+    }+  else+    {+      if (src1 != NULL && src1->nelem > 0)+	return re_node_set_init_copy (dest, src1);+      else if (src2 != NULL && src2->nelem > 0)+	return re_node_set_init_copy (dest, src2);+      else+	re_node_set_init_empty (dest);+      return REG_NOERROR;+    }+  for (i1 = i2 = id = 0 ; i1 < src1->nelem && i2 < src2->nelem ;)+    {+      if (src1->elems[i1] > src2->elems[i2])+	{+	  dest->elems[id++] = src2->elems[i2++];+	  continue;+	}+      if (src1->elems[i1] == src2->elems[i2])+	++i2;+      dest->elems[id++] = src1->elems[i1++];+    }+  if (i1 < src1->nelem)+    {+      memcpy (dest->elems + id, src1->elems + i1,+	     (src1->nelem - i1) * sizeof (int));+      id += src1->nelem - i1;+    }+  else if (i2 < src2->nelem)+    {+      memcpy (dest->elems + id, src2->elems + i2,+	     (src2->nelem - i2) * sizeof (int));+      id += src2->nelem - i2;+    }+  dest->nelem = id;+  return REG_NOERROR;+}++/* Calculate the union set of the sets DEST and SRC. And store it to+   DEST. Return value indicate the error code or REG_NOERROR if succeeded.  */++static reg_errcode_t+internal_function+re_node_set_merge (re_node_set *dest, const re_node_set *src)+{+  int is, id, sbase, delta;+  if (src == NULL || src->nelem == 0)+    return REG_NOERROR;+  if (dest->alloc < 2 * src->nelem + dest->nelem)+    {+      int new_alloc = 2 * (src->nelem + dest->alloc);+      int *new_buffer = re_realloc (dest->elems, int, new_alloc);+      if (BE (new_buffer == NULL, 0))+	return REG_ESPACE;+      dest->elems = new_buffer;+      dest->alloc = new_alloc;+    }++  if (BE (dest->nelem == 0, 0))+    {+      dest->nelem = src->nelem;+      memcpy (dest->elems, src->elems, src->nelem * sizeof (int));+      return REG_NOERROR;+    }++  /* Copy into the top of DEST the items of SRC that are not+     found in DEST.  Maybe we could binary search in DEST?  */+  for (sbase = dest->nelem + 2 * src->nelem,+       is = src->nelem - 1, id = dest->nelem - 1; is >= 0 && id >= 0; )+    {+      if (dest->elems[id] == src->elems[is])+        is--, id--;+      else if (dest->elems[id] < src->elems[is])+        dest->elems[--sbase] = src->elems[is--];+      else /* if (dest->elems[id] > src->elems[is]) */+        --id;+    }++  if (is >= 0)+    {+      /* If DEST is exhausted, the remaining items of SRC must be unique.  */+      sbase -= is + 1;+      memcpy (dest->elems + sbase, src->elems, (is + 1) * sizeof (int));+    }++  id = dest->nelem - 1;+  is = dest->nelem + 2 * src->nelem - 1;+  delta = is - sbase + 1;+  if (delta == 0)+    return REG_NOERROR;++  /* Now copy.  When DELTA becomes zero, the remaining+     DEST elements are already in place.  */+  dest->nelem += delta;+  for (;;)+    {+      if (dest->elems[is] > dest->elems[id])+        {+	  /* Copy from the top.  */+          dest->elems[id + delta--] = dest->elems[is--];+	  if (delta == 0)+	    break;+	}+      else+        {+          /* Slide from the bottom.  */+          dest->elems[id + delta] = dest->elems[id];+	  if (--id < 0)+	    {+	      /* Copy remaining SRC elements.  */+	      memcpy (dest->elems, dest->elems + sbase,+	              delta * sizeof (int));+	      break;+	    }+	}+    }++  return REG_NOERROR;+}++/* Insert the new element ELEM to the re_node_set* SET.+   SET should not already have ELEM.+   return -1 if an error is occured, return 1 otherwise.  */++static int+internal_function+re_node_set_insert (re_node_set *set, int elem)+{+  int idx;+  /* In case the set is empty.  */+  if (set->alloc == 0)+    {+      if (BE (re_node_set_init_1 (set, elem) == REG_NOERROR, 1))+	return 1;+      else+	return -1;+    }++  if (BE (set->nelem, 0) == 0)+    {+      /* We already guaranteed above that set->alloc != 0.  */+      set->elems[0] = elem;+      ++set->nelem;+      return 1;+    }++  /* Realloc if we need.  */+  if (set->alloc == set->nelem)+    {+      int *new_elems;+      set->alloc = set->alloc * 2;+      new_elems = re_realloc (set->elems, int, set->alloc);+      if (BE (new_elems == NULL, 0))+	return -1;+      set->elems = new_elems;+    }++  /* Move the elements which follows the new element.  Test the+     first element separately to skip a check in the inner loop.  */+  if (elem < set->elems[0])+    {+      idx = 0;+      for (idx = set->nelem; idx > 0; idx--)+        set->elems[idx] = set->elems[idx - 1];+    }+  else+    {+      for (idx = set->nelem; set->elems[idx - 1] > elem; idx--)+        set->elems[idx] = set->elems[idx - 1];+    }++  /* Insert the new element.  */+  set->elems[idx] = elem;+  ++set->nelem;+  return 1;+}++/* Insert the new element ELEM to the re_node_set* SET.+   SET should not already have any element greater than or equal to ELEM.+   Return -1 if an error is occured, return 1 otherwise.  */++static int+internal_function+re_node_set_insert_last (re_node_set *set, int elem)+{+  /* Realloc if we need.  */+  if (set->alloc == set->nelem)+    {+      int *new_elems;+      set->alloc = (set->alloc + 1) * 2;+      new_elems = re_realloc (set->elems, int, set->alloc);+      if (BE (new_elems == NULL, 0))+	return -1;+      set->elems = new_elems;+    }++  /* Insert the new element.  */+  set->elems[set->nelem++] = elem;+  return 1;+}++/* Compare two node sets SET1 and SET2.+   return 1 if SET1 and SET2 are equivalent, return 0 otherwise.  */++static int+internal_function __attribute ((pure))+re_node_set_compare (const re_node_set *set1, const re_node_set *set2)+{+  int i;+  if (set1 == NULL || set2 == NULL || set1->nelem != set2->nelem)+    return 0;+  for (i = set1->nelem ; --i >= 0 ; )+    if (set1->elems[i] != set2->elems[i])+      return 0;+  return 1;+}++/* Return (idx + 1) if SET contains the element ELEM, return 0 otherwise.  */++static int+internal_function __attribute ((pure))+re_node_set_contains (const re_node_set *set, int elem)+{+  unsigned int idx, right, mid;+  if (set->nelem <= 0)+    return 0;++  /* Binary search the element.  */+  idx = 0;+  right = set->nelem - 1;+  while (idx < right)+    {+      mid = (idx + right) / 2;+      if (set->elems[mid] < elem)+	idx = mid + 1;+      else+	right = mid;+    }+  return set->elems[idx] == elem ? idx + 1 : 0;+}++static void+internal_function+re_node_set_remove_at (re_node_set *set, int idx)+{+  if (idx < 0 || idx >= set->nelem)+    return;+  --set->nelem;+  for (; idx < set->nelem; idx++)+    set->elems[idx] = set->elems[idx + 1];+}+++/* Add the token TOKEN to dfa->nodes, and return the index of the token.+   Or return -1, if an error will be occured.  */++static int+internal_function+re_dfa_add_node (re_dfa_t *dfa, re_token_t token)+{+  int type = token.type;+  if (BE (dfa->nodes_len >= dfa->nodes_alloc, 0))+    {+      size_t new_nodes_alloc = dfa->nodes_alloc * 2;+      int *new_nexts, *new_indices;+      re_node_set *new_edests, *new_eclosures;+      re_token_t *new_nodes;++      /* Avoid overflows.  */+      if (BE (new_nodes_alloc < dfa->nodes_alloc, 0))+	return -1;++      new_nodes = re_realloc (dfa->nodes, re_token_t, new_nodes_alloc);+      if (BE (new_nodes == NULL, 0))+	return -1;+      dfa->nodes = new_nodes;+      new_nexts = re_realloc (dfa->nexts, int, new_nodes_alloc);+      new_indices = re_realloc (dfa->org_indices, int, new_nodes_alloc);+      new_edests = re_realloc (dfa->edests, re_node_set, new_nodes_alloc);+      new_eclosures = re_realloc (dfa->eclosures, re_node_set, new_nodes_alloc);+      if (BE (new_nexts == NULL || new_indices == NULL+	      || new_edests == NULL || new_eclosures == NULL, 0))+	return -1;+      dfa->nexts = new_nexts;+      dfa->org_indices = new_indices;+      dfa->edests = new_edests;+      dfa->eclosures = new_eclosures;+      dfa->nodes_alloc = new_nodes_alloc;+    }+  dfa->nodes[dfa->nodes_len] = token;+  dfa->nodes[dfa->nodes_len].constraint = 0;+#ifdef RE_ENABLE_I18N+  dfa->nodes[dfa->nodes_len].accept_mb =+    (type == OP_PERIOD && dfa->mb_cur_max > 1) || type == COMPLEX_BRACKET;+#endif+  dfa->nexts[dfa->nodes_len] = -1;+  re_node_set_init_empty (dfa->edests + dfa->nodes_len);+  re_node_set_init_empty (dfa->eclosures + dfa->nodes_len);+  return dfa->nodes_len++;+}++static inline unsigned int+internal_function+calc_state_hash (const re_node_set *nodes, unsigned int context)+{+  unsigned int hash = nodes->nelem + context;+  int i;+  for (i = 0 ; i < nodes->nelem ; i++)+    hash += nodes->elems[i];+  return hash;+}++/* Search for the state whose node_set is equivalent to NODES.+   Return the pointer to the state, if we found it in the DFA.+   Otherwise create the new one and return it.  In case of an error+   return NULL and set the error code in ERR.+   Note: - We assume NULL as the invalid state, then it is possible that+	   return value is NULL and ERR is REG_NOERROR.+	 - We never return non-NULL value in case of any errors, it is for+	   optimization.  */++static re_dfastate_t *+internal_function+re_acquire_state (reg_errcode_t *err, const re_dfa_t *dfa,+		  const re_node_set *nodes)+{+  unsigned int hash;+  re_dfastate_t *new_state;+  struct re_state_table_entry *spot;+  int i;+  if (BE (nodes->nelem == 0, 0))+    {+      *err = REG_NOERROR;+      return NULL;+    }+  hash = calc_state_hash (nodes, 0);+  spot = dfa->state_table + (hash & dfa->state_hash_mask);++  for (i = 0 ; i < spot->num ; i++)+    {+      re_dfastate_t *state = spot->array[i];+      if (hash != state->hash)+	continue;+      if (re_node_set_compare (&state->nodes, nodes))+	return state;+    }++  /* There are no appropriate state in the dfa, create the new one.  */+  new_state = create_ci_newstate (dfa, nodes, hash);+  if (BE (new_state == NULL, 0))+    *err = REG_ESPACE;++  return new_state;+}++/* Search for the state whose node_set is equivalent to NODES and+   whose context is equivalent to CONTEXT.+   Return the pointer to the state, if we found it in the DFA.+   Otherwise create the new one and return it.  In case of an error+   return NULL and set the error code in ERR.+   Note: - We assume NULL as the invalid state, then it is possible that+	   return value is NULL and ERR is REG_NOERROR.+	 - We never return non-NULL value in case of any errors, it is for+	   optimization.  */++static re_dfastate_t *+internal_function+re_acquire_state_context (reg_errcode_t *err, const re_dfa_t *dfa,+			  const re_node_set *nodes, unsigned int context)+{+  unsigned int hash;+  re_dfastate_t *new_state;+  struct re_state_table_entry *spot;+  int i;+  if (nodes->nelem == 0)+    {+      *err = REG_NOERROR;+      return NULL;+    }+  hash = calc_state_hash (nodes, context);+  spot = dfa->state_table + (hash & dfa->state_hash_mask);++  for (i = 0 ; i < spot->num ; i++)+    {+      re_dfastate_t *state = spot->array[i];+      if (state->hash == hash+	  && state->context == context+	  && re_node_set_compare (state->entrance_nodes, nodes))+	return state;+    }+  /* There are no appropriate state in `dfa', create the new one.  */+  new_state = create_cd_newstate (dfa, nodes, context, hash);+  if (BE (new_state == NULL, 0))+    *err = REG_ESPACE;++  return new_state;+}++/* Finish initialization of the new state NEWSTATE, and using its hash value+   HASH put in the appropriate bucket of DFA's state table.  Return value+   indicates the error code if failed.  */++static reg_errcode_t+register_state (const re_dfa_t *dfa, re_dfastate_t *newstate,+		unsigned int hash)+{+  struct re_state_table_entry *spot;+  reg_errcode_t err;+  int i;++  newstate->hash = hash;+  err = re_node_set_alloc (&newstate->non_eps_nodes, newstate->nodes.nelem);+  if (BE (err != REG_NOERROR, 0))+    return REG_ESPACE;+  for (i = 0; i < newstate->nodes.nelem; i++)+    {+      int elem = newstate->nodes.elems[i];+      if (!IS_EPSILON_NODE (dfa->nodes[elem].type))+        re_node_set_insert_last (&newstate->non_eps_nodes, elem);+    }++  spot = dfa->state_table + (hash & dfa->state_hash_mask);+  if (BE (spot->alloc <= spot->num, 0))+    {+      int new_alloc = 2 * spot->num + 2;+      re_dfastate_t **new_array = re_realloc (spot->array, re_dfastate_t *,+					      new_alloc);+      if (BE (new_array == NULL, 0))+	return REG_ESPACE;+      spot->array = new_array;+      spot->alloc = new_alloc;+    }+  spot->array[spot->num++] = newstate;+  return REG_NOERROR;+}++static void+free_state (re_dfastate_t *state)+{+  re_node_set_free (&state->non_eps_nodes);+  re_node_set_free (&state->inveclosure);+  if (state->entrance_nodes != &state->nodes)+    {+      re_node_set_free (state->entrance_nodes);+      re_free (state->entrance_nodes);+    }+  re_node_set_free (&state->nodes);+  re_free (state->word_trtable);+  re_free (state->trtable);+  re_free (state);+}++/* Create the new state which is independ of contexts.+   Return the new state if succeeded, otherwise return NULL.  */++static re_dfastate_t *+internal_function+create_ci_newstate (const re_dfa_t *dfa, const re_node_set *nodes,+		    unsigned int hash)+{+  int i;+  reg_errcode_t err;+  re_dfastate_t *newstate;++  newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);+  if (BE (newstate == NULL, 0))+    return NULL;+  err = re_node_set_init_copy (&newstate->nodes, nodes);+  if (BE (err != REG_NOERROR, 0))+    {+      re_free (newstate);+      return NULL;+    }++  newstate->entrance_nodes = &newstate->nodes;+  for (i = 0 ; i < nodes->nelem ; i++)+    {+      re_token_t *node = dfa->nodes + nodes->elems[i];+      re_token_type_t type = node->type;+      if (type == CHARACTER && !node->constraint)+	continue;+#ifdef RE_ENABLE_I18N+      newstate->accept_mb |= node->accept_mb;+#endif /* RE_ENABLE_I18N */++      /* If the state has the halt node, the state is a halt state.  */+      if (type == END_OF_RE)+	newstate->halt = 1;+      else if (type == OP_BACK_REF)+	newstate->has_backref = 1;+      else if (type == ANCHOR || node->constraint)+	newstate->has_constraint = 1;+    }+  err = register_state (dfa, newstate, hash);+  if (BE (err != REG_NOERROR, 0))+    {+      free_state (newstate);+      newstate = NULL;+    }+  return newstate;+}++/* Create the new state which is depend on the context CONTEXT.+   Return the new state if succeeded, otherwise return NULL.  */++static re_dfastate_t *+internal_function+create_cd_newstate (const re_dfa_t *dfa, const re_node_set *nodes,+		    unsigned int context, unsigned int hash)+{+  int i, nctx_nodes = 0;+  reg_errcode_t err;+  re_dfastate_t *newstate;++  newstate = (re_dfastate_t *) calloc (sizeof (re_dfastate_t), 1);+  if (BE (newstate == NULL, 0))+    return NULL;+  err = re_node_set_init_copy (&newstate->nodes, nodes);+  if (BE (err != REG_NOERROR, 0))+    {+      re_free (newstate);+      return NULL;+    }++  newstate->context = context;+  newstate->entrance_nodes = &newstate->nodes;++  for (i = 0 ; i < nodes->nelem ; i++)+    {+      unsigned int constraint = 0;+      re_token_t *node = dfa->nodes + nodes->elems[i];+      re_token_type_t type = node->type;+      if (node->constraint)+	constraint = node->constraint;++      if (type == CHARACTER && !constraint)+	continue;+#ifdef RE_ENABLE_I18N+      newstate->accept_mb |= node->accept_mb;+#endif /* RE_ENABLE_I18N */++      /* If the state has the halt node, the state is a halt state.  */+      if (type == END_OF_RE)+	newstate->halt = 1;+      else if (type == OP_BACK_REF)+	newstate->has_backref = 1;+      else if (type == ANCHOR)+	constraint = node->opr.ctx_type;++      if (constraint)+	{+	  if (newstate->entrance_nodes == &newstate->nodes)+	    {+	      newstate->entrance_nodes = re_malloc (re_node_set, 1);+	      if (BE (newstate->entrance_nodes == NULL, 0))+		{+		  free_state (newstate);+		  return NULL;+		}+	      re_node_set_init_copy (newstate->entrance_nodes, nodes);+	      nctx_nodes = 0;+	      newstate->has_constraint = 1;+	    }++	  if (NOT_SATISFY_PREV_CONSTRAINT (constraint,context))+	    {+	      re_node_set_remove_at (&newstate->nodes, i - nctx_nodes);+	      ++nctx_nodes;+	    }+	}+    }+  err = register_state (dfa, newstate, hash);+  if (BE (err != REG_NOERROR, 0))+    {+      free_state (newstate);+      newstate = NULL;+    }+  return  newstate;+}
+ cbits/regex_internal.h view
@@ -0,0 +1,769 @@+/* Extended regular expression matching and search library.+   Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.+   This file is part of the GNU C Library.+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.++   The GNU C Library is free software; you can redistribute it and/or+   modify it under the terms of the GNU Lesser General Public+   License as published by the Free Software Foundation; either+   version 2.1 of the License, or (at your option) any later version.++   The GNU C Library is distributed in the hope that it will be useful,+   but WITHOUT ANY WARRANTY; without even the implied warranty of+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU+   Lesser General Public License for more details.++   You should have received a copy of the GNU Lesser General Public+   License along with the GNU C Library; if not, write to the Free+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA+   02111-1307 USA.  */++#ifndef _REGEX_INTERNAL_H+#define _REGEX_INTERNAL_H 1++#include <assert.h>+#include <ctype.h>+#include <stdio.h>+#include <stdlib.h>+#include <string.h>++#if defined HAVE_LANGINFO_H || defined HAVE_LANGINFO_CODESET || defined _LIBC+# include <langinfo.h>+#endif+#if defined HAVE_LOCALE_H || defined _LIBC+# include <locale.h>+#endif+#if defined HAVE_WCHAR_H || defined _LIBC+# include <wchar.h>+#endif /* HAVE_WCHAR_H || _LIBC */+#if defined HAVE_WCTYPE_H || defined _LIBC+# include <wctype.h>+#endif /* HAVE_WCTYPE_H || _LIBC */+#if defined HAVE_STDBOOL_H || defined _LIBC+# include <stdbool.h>+#endif /* HAVE_STDBOOL_H || _LIBC */+#if defined HAVE_STDINT_H || defined _LIBC+# include <stdint.h>+#endif /* HAVE_STDINT_H || _LIBC */+#if defined _LIBC+# include <bits/libc-lock.h>+#else+# define __libc_lock_define(CLASS,NAME)+# define __libc_lock_init(NAME) do { } while (0)+# define __libc_lock_lock(NAME) do { } while (0)+# define __libc_lock_unlock(NAME) do { } while (0)+#endif++/* In case that the system doesn't have isblank().  */+#if !defined _LIBC && !defined HAVE_ISBLANK && !defined isblank+# define isblank(ch) ((ch) == ' ' || (ch) == '\t')+#endif++#ifdef _LIBC+# ifndef _RE_DEFINE_LOCALE_FUNCTIONS+#  define _RE_DEFINE_LOCALE_FUNCTIONS 1+#   include <locale/localeinfo.h>+#   include <locale/elem-hash.h>+#   include <locale/coll-lookup.h>+# endif+#endif++/* This is for other GNU distributions with internationalized messages.  */+#if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC+# include <libintl.h>+# ifdef _LIBC+#  undef gettext+#  define gettext(msgid) \+  INTUSE(__dcgettext) (_libc_intl_domainname, msgid, LC_MESSAGES)+# endif+#else+# define gettext(msgid) (msgid)+#endif++#ifndef gettext_noop+/* This define is so xgettext can find the internationalizable+   strings.  */+# define gettext_noop(String) String+#endif++/* For loser systems without the definition.  */+#ifndef SIZE_MAX+# define SIZE_MAX ((size_t) -1)+#endif++#if (defined MB_CUR_MAX && HAVE_LOCALE_H && HAVE_WCTYPE_H && HAVE_WCHAR_H && HAVE_WCRTOMB && HAVE_MBRTOWC && HAVE_WCSCOLL) || _LIBC+# define RE_ENABLE_I18N+#endif++#if __GNUC__ >= 3+# define BE(expr, val) __builtin_expect (expr, val)+#else+# define BE(expr, val) (expr)+# define inline+#endif++/* Number of single byte character.  */+#define SBC_MAX 256++#define COLL_ELEM_LEN_MAX 8++/* The character which represents newline.  */+#define NEWLINE_CHAR '\n'+#define WIDE_NEWLINE_CHAR L'\n'++/* Rename to standard API for using out of glibc.  */+#ifndef _LIBC+# define __wctype wctype+# define __iswctype iswctype+# define __btowc btowc+# define __mempcpy mempcpy+# define __wcrtomb wcrtomb+# define __regfree regfree+# define attribute_hidden+#endif /* not _LIBC */++#ifdef __GNUC__+# define __attribute(arg) __attribute__ (arg)+#else+# define __attribute(arg)+#endif++extern const char __re_error_msgid[] attribute_hidden;+extern const size_t __re_error_msgid_idx[] attribute_hidden;++/* An integer used to represent a set of bits.  It must be unsigned,+   and must be at least as wide as unsigned int.  */+typedef unsigned long int bitset_word_t;+/* All bits set in a bitset_word_t.  */+#define BITSET_WORD_MAX ULONG_MAX+/* Number of bits in a bitset_word_t.  */+#define BITSET_WORD_BITS (sizeof (bitset_word_t) * CHAR_BIT)+/* Number of bitset_word_t in a bit_set.  */+#define BITSET_WORDS (SBC_MAX / BITSET_WORD_BITS)+typedef bitset_word_t bitset_t[BITSET_WORDS];+typedef bitset_word_t *re_bitset_ptr_t;+typedef const bitset_word_t *re_const_bitset_ptr_t;++#define bitset_set(set,i) \+  (set[i / BITSET_WORD_BITS] |= (bitset_word_t) 1 << i % BITSET_WORD_BITS)+#define bitset_clear(set,i) \+  (set[i / BITSET_WORD_BITS] &= ~((bitset_word_t) 1 << i % BITSET_WORD_BITS))+#define bitset_contain(set,i) \+  (set[i / BITSET_WORD_BITS] & ((bitset_word_t) 1 << i % BITSET_WORD_BITS))+#define bitset_empty(set) memset (set, '\0', sizeof (bitset_t))+#define bitset_set_all(set) memset (set, '\xff', sizeof (bitset_t))+#define bitset_copy(dest,src) memcpy (dest, src, sizeof (bitset_t))++#define PREV_WORD_CONSTRAINT 0x0001+#define PREV_NOTWORD_CONSTRAINT 0x0002+#define NEXT_WORD_CONSTRAINT 0x0004+#define NEXT_NOTWORD_CONSTRAINT 0x0008+#define PREV_NEWLINE_CONSTRAINT 0x0010+#define NEXT_NEWLINE_CONSTRAINT 0x0020+#define PREV_BEGBUF_CONSTRAINT 0x0040+#define NEXT_ENDBUF_CONSTRAINT 0x0080+#define WORD_DELIM_CONSTRAINT 0x0100+#define NOT_WORD_DELIM_CONSTRAINT 0x0200++typedef enum+{+  INSIDE_WORD = PREV_WORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,+  WORD_FIRST = PREV_NOTWORD_CONSTRAINT | NEXT_WORD_CONSTRAINT,+  WORD_LAST = PREV_WORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,+  INSIDE_NOTWORD = PREV_NOTWORD_CONSTRAINT | NEXT_NOTWORD_CONSTRAINT,+  LINE_FIRST = PREV_NEWLINE_CONSTRAINT,+  LINE_LAST = NEXT_NEWLINE_CONSTRAINT,+  BUF_FIRST = PREV_BEGBUF_CONSTRAINT,+  BUF_LAST = NEXT_ENDBUF_CONSTRAINT,+  WORD_DELIM = WORD_DELIM_CONSTRAINT,+  NOT_WORD_DELIM = NOT_WORD_DELIM_CONSTRAINT+} re_context_type;++typedef struct+{+  int alloc;+  int nelem;+  int *elems;+} re_node_set;++typedef enum+{+  NON_TYPE = 0,++  /* Node type, These are used by token, node, tree.  */+  CHARACTER = 1,+  END_OF_RE = 2,+  SIMPLE_BRACKET = 3,+  OP_BACK_REF = 4,+  OP_PERIOD = 5,+#ifdef RE_ENABLE_I18N+  COMPLEX_BRACKET = 6,+  OP_UTF8_PERIOD = 7,+#endif /* RE_ENABLE_I18N */++  /* We define EPSILON_BIT as a macro so that OP_OPEN_SUBEXP is used+     when the debugger shows values of this enum type.  */+#define EPSILON_BIT 8+  OP_OPEN_SUBEXP = EPSILON_BIT | 0,+  OP_CLOSE_SUBEXP = EPSILON_BIT | 1,+  OP_ALT = EPSILON_BIT | 2,+  OP_DUP_ASTERISK = EPSILON_BIT | 3,+  ANCHOR = EPSILON_BIT | 4,++  /* Tree type, these are used only by tree. */+  CONCAT = 16,+  SUBEXP = 17,++  /* Token type, these are used only by token.  */+  OP_DUP_PLUS = 18,+  OP_DUP_QUESTION,+  OP_OPEN_BRACKET,+  OP_CLOSE_BRACKET,+  OP_CHARSET_RANGE,+  OP_OPEN_DUP_NUM,+  OP_CLOSE_DUP_NUM,+  OP_NON_MATCH_LIST,+  OP_OPEN_COLL_ELEM,+  OP_CLOSE_COLL_ELEM,+  OP_OPEN_EQUIV_CLASS,+  OP_CLOSE_EQUIV_CLASS,+  OP_OPEN_CHAR_CLASS,+  OP_CLOSE_CHAR_CLASS,+  OP_WORD,+  OP_NOTWORD,+  OP_SPACE,+  OP_NOTSPACE,+  BACK_SLASH++} re_token_type_t;++#ifdef RE_ENABLE_I18N+typedef struct+{+  /* Multibyte characters.  */+  wchar_t *mbchars;++  /* Collating symbols.  */+# ifdef _LIBC+  int32_t *coll_syms;+# endif++  /* Equivalence classes. */+# ifdef _LIBC+  int32_t *equiv_classes;+# endif++  /* Range expressions. */+# ifdef _LIBC+  uint32_t *range_starts;+  uint32_t *range_ends;+# else /* not _LIBC */+  wchar_t *range_starts;+  wchar_t *range_ends;+# endif /* not _LIBC */++  /* Character classes. */+  wctype_t *char_classes;++  /* If this character set is the non-matching list.  */+  unsigned int non_match : 1;++  /* # of multibyte characters.  */+  int nmbchars;++  /* # of collating symbols.  */+  int ncoll_syms;++  /* # of equivalence classes. */+  int nequiv_classes;++  /* # of range expressions. */+  int nranges;++  /* # of character classes. */+  int nchar_classes;+} re_charset_t;+#endif /* RE_ENABLE_I18N */++typedef struct+{+  union+  {+    unsigned char c;		/* for CHARACTER */+    re_bitset_ptr_t sbcset;	/* for SIMPLE_BRACKET */+#ifdef RE_ENABLE_I18N+    re_charset_t *mbcset;	/* for COMPLEX_BRACKET */+#endif /* RE_ENABLE_I18N */+    int idx;			/* for BACK_REF */+    re_context_type ctx_type;	/* for ANCHOR */+  } opr;+#if __GNUC__ >= 2+  re_token_type_t type : 8;+#else+  re_token_type_t type;+#endif+  unsigned int constraint : 10;	/* context constraint */+  unsigned int duplicated : 1;+  unsigned int opt_subexp : 1;+#ifdef RE_ENABLE_I18N+  unsigned int accept_mb : 1;+  /* These 2 bits can be moved into the union if needed (e.g. if running out+     of bits; move opr.c to opr.c.c and move the flags to opr.c.flags).  */+  unsigned int mb_partial : 1;+#endif+  unsigned int word_char : 1;+} re_token_t;++#define IS_EPSILON_NODE(type) ((type) & EPSILON_BIT)++struct re_string_t+{+  /* Indicate the raw buffer which is the original string passed as an+     argument of regexec(), re_search(), etc..  */+  const unsigned char *raw_mbs;+  /* Store the multibyte string.  In case of "case insensitive mode" like+     REG_ICASE, upper cases of the string are stored, otherwise MBS points+     the same address that RAW_MBS points.  */+  unsigned char *mbs;+#ifdef RE_ENABLE_I18N+  /* Store the wide character string which is corresponding to MBS.  */+  wint_t *wcs;+  int *offsets;+  mbstate_t cur_state;+#endif+  /* Index in RAW_MBS.  Each character mbs[i] corresponds to+     raw_mbs[raw_mbs_idx + i].  */+  int raw_mbs_idx;+  /* The length of the valid characters in the buffers.  */+  int valid_len;+  /* The corresponding number of bytes in raw_mbs array.  */+  int valid_raw_len;+  /* The length of the buffers MBS and WCS.  */+  int bufs_len;+  /* The index in MBS, which is updated by re_string_fetch_byte.  */+  int cur_idx;+  /* length of RAW_MBS array.  */+  int raw_len;+  /* This is RAW_LEN - RAW_MBS_IDX + VALID_LEN - VALID_RAW_LEN.  */+  int len;+  /* End of the buffer may be shorter than its length in the cases such+     as re_match_2, re_search_2.  Then, we use STOP for end of the buffer+     instead of LEN.  */+  int raw_stop;+  /* This is RAW_STOP - RAW_MBS_IDX adjusted through OFFSETS.  */+  int stop;++  /* The context of mbs[0].  We store the context independently, since+     the context of mbs[0] may be different from raw_mbs[0], which is+     the beginning of the input string.  */+  unsigned int tip_context;+  /* The translation passed as a part of an argument of re_compile_pattern.  */+  RE_TRANSLATE_TYPE trans;+  /* Copy of re_dfa_t's word_char.  */+  re_const_bitset_ptr_t word_char;+  /* 1 if REG_ICASE.  */+  unsigned char icase;+  unsigned char is_utf8;+  unsigned char map_notascii;+  unsigned char mbs_allocated;+  unsigned char offsets_needed;+  unsigned char newline_anchor;+  unsigned char word_ops_used;+  int mb_cur_max;+};+typedef struct re_string_t re_string_t;+++struct re_dfa_t;+typedef struct re_dfa_t re_dfa_t;++#ifndef _LIBC+# ifdef __i386__+#  define internal_function   __attribute ((regparm (3), stdcall))+# else+#  define internal_function+# endif+#endif++#ifndef NOT_IN_libc+static reg_errcode_t re_string_realloc_buffers (re_string_t *pstr,+						int new_buf_len)+     internal_function;+# ifdef RE_ENABLE_I18N+static void build_wcs_buffer (re_string_t *pstr) internal_function;+static int build_wcs_upper_buffer (re_string_t *pstr) internal_function;+# endif /* RE_ENABLE_I18N */+static void build_upper_buffer (re_string_t *pstr) internal_function;+static void re_string_translate_buffer (re_string_t *pstr) internal_function;+static unsigned int re_string_context_at (const re_string_t *input, int idx,+					  int eflags)+     internal_function __attribute ((pure));+#endif+#define re_string_peek_byte(pstr, offset) \+  ((pstr)->mbs[(pstr)->cur_idx + offset])+#define re_string_fetch_byte(pstr) \+  ((pstr)->mbs[(pstr)->cur_idx++])+#define re_string_first_byte(pstr, idx) \+  ((idx) == (pstr)->valid_len || (pstr)->wcs[idx] != WEOF)+#define re_string_is_single_byte_char(pstr, idx) \+  ((pstr)->wcs[idx] != WEOF && ((pstr)->valid_len == (idx) + 1 \+				|| (pstr)->wcs[(idx) + 1] != WEOF))+#define re_string_eoi(pstr) ((pstr)->stop <= (pstr)->cur_idx)+#define re_string_cur_idx(pstr) ((pstr)->cur_idx)+#define re_string_get_buffer(pstr) ((pstr)->mbs)+#define re_string_length(pstr) ((pstr)->len)+#define re_string_byte_at(pstr,idx) ((pstr)->mbs[idx])+#define re_string_skip_bytes(pstr,idx) ((pstr)->cur_idx += (idx))+#define re_string_set_index(pstr,idx) ((pstr)->cur_idx = (idx))++#ifdef HAVE_ALLOCA_H+ #include <alloca.h>+#endif++#ifndef _LIBC+# if HAVE_ALLOCA+/* The OS usually guarantees only one guard page at the bottom of the stack,+   and a page size can be as small as 4096 bytes.  So we cannot safely+   allocate anything larger than 4096 bytes.  Also care for the possibility+   of a few compiler-allocated temporary stack slots.  */+#  define __libc_use_alloca(n) ((n) < 4032)+# else+/* alloca is implemented with malloc, so just use malloc.  */+#  define __libc_use_alloca(n) 0+# endif+#endif++#define re_malloc(t,n) ((t *) malloc ((n) * sizeof (t)))+#define re_realloc(p,t,n) ((t *) realloc (p, (n) * sizeof (t)))+#define re_free(p) free (p)++struct bin_tree_t+{+  struct bin_tree_t *parent;+  struct bin_tree_t *left;+  struct bin_tree_t *right;+  struct bin_tree_t *first;+  struct bin_tree_t *next;++  re_token_t token;++  /* `node_idx' is the index in dfa->nodes, if `type' == 0.+     Otherwise `type' indicate the type of this node.  */+  int node_idx;+};+typedef struct bin_tree_t bin_tree_t;++#define BIN_TREE_STORAGE_SIZE \+  ((1024 - sizeof (void *)) / sizeof (bin_tree_t))++struct bin_tree_storage_t+{+  struct bin_tree_storage_t *next;+  bin_tree_t data[BIN_TREE_STORAGE_SIZE];+};+typedef struct bin_tree_storage_t bin_tree_storage_t;++#define CONTEXT_WORD 1+#define CONTEXT_NEWLINE (CONTEXT_WORD << 1)+#define CONTEXT_BEGBUF (CONTEXT_NEWLINE << 1)+#define CONTEXT_ENDBUF (CONTEXT_BEGBUF << 1)++#define IS_WORD_CONTEXT(c) ((c) & CONTEXT_WORD)+#define IS_NEWLINE_CONTEXT(c) ((c) & CONTEXT_NEWLINE)+#define IS_BEGBUF_CONTEXT(c) ((c) & CONTEXT_BEGBUF)+#define IS_ENDBUF_CONTEXT(c) ((c) & CONTEXT_ENDBUF)+#define IS_ORDINARY_CONTEXT(c) ((c) == 0)++#define IS_WORD_CHAR(ch) (isalnum (ch) || (ch) == '_')+#define IS_NEWLINE(ch) ((ch) == NEWLINE_CHAR)+#define IS_WIDE_WORD_CHAR(ch) (iswalnum (ch) || (ch) == L'_')+#define IS_WIDE_NEWLINE(ch) ((ch) == WIDE_NEWLINE_CHAR)++#define NOT_SATISFY_PREV_CONSTRAINT(constraint,context) \+ ((((constraint) & PREV_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \+  || ((constraint & PREV_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \+  || ((constraint & PREV_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context))\+  || ((constraint & PREV_BEGBUF_CONSTRAINT) && !IS_BEGBUF_CONTEXT (context)))++#define NOT_SATISFY_NEXT_CONSTRAINT(constraint,context) \+ ((((constraint) & NEXT_WORD_CONSTRAINT) && !IS_WORD_CONTEXT (context)) \+  || (((constraint) & NEXT_NOTWORD_CONSTRAINT) && IS_WORD_CONTEXT (context)) \+  || (((constraint) & NEXT_NEWLINE_CONSTRAINT) && !IS_NEWLINE_CONTEXT (context)) \+  || (((constraint) & NEXT_ENDBUF_CONSTRAINT) && !IS_ENDBUF_CONTEXT (context)))++struct re_dfastate_t+{+  unsigned int hash;+  re_node_set nodes;+  re_node_set non_eps_nodes;+  re_node_set inveclosure;+  re_node_set *entrance_nodes;+  struct re_dfastate_t **trtable, **word_trtable;+  unsigned int context : 4;+  unsigned int halt : 1;+  /* If this state can accept `multi byte'.+     Note that we refer to multibyte characters, and multi character+     collating elements as `multi byte'.  */+  unsigned int accept_mb : 1;+  /* If this state has backreference node(s).  */+  unsigned int has_backref : 1;+  unsigned int has_constraint : 1;+};+typedef struct re_dfastate_t re_dfastate_t;++struct re_state_table_entry+{+  int num;+  int alloc;+  re_dfastate_t **array;+};++/* Array type used in re_sub_match_last_t and re_sub_match_top_t.  */++typedef struct+{+  int next_idx;+  int alloc;+  re_dfastate_t **array;+} state_array_t;++/* Store information about the node NODE whose type is OP_CLOSE_SUBEXP.  */++typedef struct+{+  int node;+  int str_idx; /* The position NODE match at.  */+  state_array_t path;+} re_sub_match_last_t;++/* Store information about the node NODE whose type is OP_OPEN_SUBEXP.+   And information about the node, whose type is OP_CLOSE_SUBEXP,+   corresponding to NODE is stored in LASTS.  */++typedef struct+{+  int str_idx;+  int node;+  state_array_t *path;+  int alasts; /* Allocation size of LASTS.  */+  int nlasts; /* The number of LASTS.  */+  re_sub_match_last_t **lasts;+} re_sub_match_top_t;++struct re_backref_cache_entry+{+  int node;+  int str_idx;+  int subexp_from;+  int subexp_to;+  char more;+  char unused;+  unsigned short int eps_reachable_subexps_map;+};++typedef struct+{+  /* The string object corresponding to the input string.  */+  re_string_t input;+#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)+  const re_dfa_t *const dfa;+#else+  const re_dfa_t *dfa;+#endif+  /* EFLAGS of the argument of regexec.  */+  int eflags;+  /* Where the matching ends.  */+  int match_last;+  int last_node;+  /* The state log used by the matcher.  */+  re_dfastate_t **state_log;+  int state_log_top;+  /* Back reference cache.  */+  int nbkref_ents;+  int abkref_ents;+  struct re_backref_cache_entry *bkref_ents;+  int max_mb_elem_len;+  int nsub_tops;+  int asub_tops;+  re_sub_match_top_t **sub_tops;+} re_match_context_t;++typedef struct+{+  re_dfastate_t **sifted_states;+  re_dfastate_t **limited_states;+  int last_node;+  int last_str_idx;+  re_node_set limits;+} re_sift_context_t;++struct re_fail_stack_ent_t+{+  int idx;+  int node;+  regmatch_t *regs;+  re_node_set eps_via_nodes;+};++struct re_fail_stack_t+{+  int num;+  int alloc;+  struct re_fail_stack_ent_t *stack;+};++struct re_dfa_t+{+  re_token_t *nodes;+  size_t nodes_alloc;+  size_t nodes_len;+  int *nexts;+  int *org_indices;+  re_node_set *edests;+  re_node_set *eclosures;+  re_node_set *inveclosures;+  struct re_state_table_entry *state_table;+  re_dfastate_t *init_state;+  re_dfastate_t *init_state_word;+  re_dfastate_t *init_state_nl;+  re_dfastate_t *init_state_begbuf;+  bin_tree_t *str_tree;+  bin_tree_storage_t *str_tree_storage;+  re_bitset_ptr_t sb_char;+  int str_tree_storage_idx;++  /* number of subexpressions `re_nsub' is in regex_t.  */+  unsigned int state_hash_mask;+  int init_node;+  int nbackref; /* The number of backreference in this dfa.  */++  /* Bitmap expressing which backreference is used.  */+  bitset_word_t used_bkref_map;+  bitset_word_t completed_bkref_map;++  unsigned int has_plural_match : 1;+  /* If this dfa has "multibyte node", which is a backreference or+     a node which can accept multibyte character or multi character+     collating element.  */+  unsigned int has_mb_node : 1;+  unsigned int is_utf8 : 1;+  unsigned int map_notascii : 1;+  unsigned int word_ops_used : 1;+  int mb_cur_max;+  bitset_t word_char;+  reg_syntax_t syntax;+  int *subexp_map;+#ifdef DEBUG+  char* re_str;+#endif+  __libc_lock_define (, lock)+};++#define re_node_set_init_empty(set) memset (set, '\0', sizeof (re_node_set))+#define re_node_set_remove(set,id) \+  (re_node_set_remove_at (set, re_node_set_contains (set, id) - 1))+#define re_node_set_empty(p) ((p)->nelem = 0)+#define re_node_set_free(set) re_free ((set)->elems)+++typedef enum+{+  SB_CHAR,+  MB_CHAR,+  EQUIV_CLASS,+  COLL_SYM,+  CHAR_CLASS+} bracket_elem_type;++typedef struct+{+  bracket_elem_type type;+  union+  {+    unsigned char ch;+    unsigned char *name;+    wchar_t wch;+  } opr;+} bracket_elem_t;+++/* Inline functions for bitset operation.  */+static inline void+bitset_not (bitset_t set)+{+  int bitset_i;+  for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)+    set[bitset_i] = ~set[bitset_i];+}++static inline void+bitset_merge (bitset_t dest, const bitset_t src)+{+  int bitset_i;+  for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)+    dest[bitset_i] |= src[bitset_i];+}++static inline void+bitset_mask (bitset_t dest, const bitset_t src)+{+  int bitset_i;+  for (bitset_i = 0; bitset_i < BITSET_WORDS; ++bitset_i)+    dest[bitset_i] &= src[bitset_i];+}++#ifdef RE_ENABLE_I18N+/* Inline functions for re_string.  */+static inline int+internal_function __attribute ((pure))+re_string_char_size_at (const re_string_t *pstr, int idx)+{+  int byte_idx;+  if (pstr->mb_cur_max == 1)+    return 1;+  for (byte_idx = 1; idx + byte_idx < pstr->valid_len; ++byte_idx)+    if (pstr->wcs[idx + byte_idx] != WEOF)+      break;+  return byte_idx;+}++static inline wint_t+internal_function __attribute ((pure))+re_string_wchar_at (const re_string_t *pstr, int idx)+{+  if (pstr->mb_cur_max == 1)+    return (wint_t) pstr->mbs[idx];+  return (wint_t) pstr->wcs[idx];+}++# ifndef NOT_IN_libc+static int+internal_function __attribute ((pure))+re_string_elem_size_at (const re_string_t *pstr, int idx)+{+#  ifdef _LIBC+  const unsigned char *p, *extra;+  const int32_t *table, *indirect;+  int32_t tmp;+#   include <locale/weight.h>+  uint_fast32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);++  if (nrules != 0)+    {+      table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);+      extra = (const unsigned char *)+	_NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);+      indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE,+						_NL_COLLATE_INDIRECTMB);+      p = pstr->mbs + idx;+      tmp = findidx (&p);+      return p - pstr->mbs - idx;+    }+  else+#  endif /* _LIBC */+    return 1;+}+# endif+#endif /* RE_ENABLE_I18N */++#endif /*  _REGEX_INTERNAL_H */
+ cbits/regexec.c view
@@ -0,0 +1,4333 @@+/* Extended regular expression matching and search library.+   Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.+   This file is part of the GNU C Library.+   Contributed by Isamu Hasegawa <isamu@yamato.ibm.com>.++   The GNU C Library is free software; you can redistribute it and/or+   modify it under the terms of the GNU Lesser General Public+   License as published by the Free Software Foundation; either+   version 2.1 of the License, or (at your option) any later version.++   The GNU C Library is distributed in the hope that it will be useful,+   but WITHOUT ANY WARRANTY; without even the implied warranty of+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU+   Lesser General Public License for more details.++   You should have received a copy of the GNU Lesser General Public+   License along with the GNU C Library; if not, write to the Free+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA+   02111-1307 USA.  */++static reg_errcode_t match_ctx_init (re_match_context_t *cache, int eflags,+				     int n) internal_function;+static void match_ctx_clean (re_match_context_t *mctx) internal_function;+static void match_ctx_free (re_match_context_t *cache) internal_function;+static reg_errcode_t match_ctx_add_entry (re_match_context_t *cache, int node,+					  int str_idx, int from, int to)+     internal_function;+static int search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx)+     internal_function;+static reg_errcode_t match_ctx_add_subtop (re_match_context_t *mctx, int node,+					   int str_idx) internal_function;+static re_sub_match_last_t * match_ctx_add_sublast (re_sub_match_top_t *subtop,+						   int node, int str_idx)+     internal_function;+static void sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts,+			   re_dfastate_t **limited_sts, int last_node,+			   int last_str_idx)+     internal_function;+static reg_errcode_t re_search_internal (const regex_t *preg,+					 const char *string, int length,+					 int start, int range, int stop,+					 size_t nmatch, regmatch_t pmatch[],+					 int eflags) internal_function;+static int re_search_2_stub (struct re_pattern_buffer *bufp,+			     const char *string1, int length1,+			     const char *string2, int length2,+			     int start, int range, struct re_registers *regs,+			     int stop, int ret_len) internal_function;+static int re_search_stub (struct re_pattern_buffer *bufp,+			   const char *string, int length, int start,+			   int range, int stop, struct re_registers *regs,+			   int ret_len) internal_function;+static unsigned re_copy_regs (struct re_registers *regs, regmatch_t *pmatch,+			      int nregs, int regs_allocated) internal_function;+static reg_errcode_t prune_impossible_nodes (re_match_context_t *mctx)+     internal_function;+static int check_matching (re_match_context_t *mctx, int fl_longest_match,+			   int *p_match_first) internal_function;+static int check_halt_state_context (const re_match_context_t *mctx,+				     const re_dfastate_t *state, int idx)+     internal_function;+static void update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,+			 regmatch_t *prev_idx_match, int cur_node,+			 int cur_idx, int nmatch) internal_function;+static reg_errcode_t push_fail_stack (struct re_fail_stack_t *fs,+				      int str_idx, int dest_node, int nregs,+				      regmatch_t *regs,+				      re_node_set *eps_via_nodes)+     internal_function;+static reg_errcode_t set_regs (const regex_t *preg,+			       const re_match_context_t *mctx,+			       size_t nmatch, regmatch_t *pmatch,+			       int fl_backtrack) internal_function;+static reg_errcode_t free_fail_stack_return (struct re_fail_stack_t *fs)+     internal_function;++#ifdef RE_ENABLE_I18N+static int sift_states_iter_mb (const re_match_context_t *mctx,+				re_sift_context_t *sctx,+				int node_idx, int str_idx, int max_str_idx)+     internal_function;+#endif /* RE_ENABLE_I18N */+static reg_errcode_t sift_states_backward (const re_match_context_t *mctx,+					   re_sift_context_t *sctx)+     internal_function;+static reg_errcode_t build_sifted_states (const re_match_context_t *mctx,+					  re_sift_context_t *sctx, int str_idx,+					  re_node_set *cur_dest)+     internal_function;+static reg_errcode_t update_cur_sifted_state (const re_match_context_t *mctx,+					      re_sift_context_t *sctx,+					      int str_idx,+					      re_node_set *dest_nodes)+     internal_function;+static reg_errcode_t add_epsilon_src_nodes (const re_dfa_t *dfa,+					    re_node_set *dest_nodes,+					    const re_node_set *candidates)+     internal_function;+static int check_dst_limits (const re_match_context_t *mctx,+			     re_node_set *limits,+			     int dst_node, int dst_idx, int src_node,+			     int src_idx) internal_function;+static int check_dst_limits_calc_pos_1 (const re_match_context_t *mctx,+					int boundaries, int subexp_idx,+					int from_node, int bkref_idx)+     internal_function;+static int check_dst_limits_calc_pos (const re_match_context_t *mctx,+				      int limit, int subexp_idx,+				      int node, int str_idx,+				      int bkref_idx) internal_function;+static reg_errcode_t check_subexp_limits (const re_dfa_t *dfa,+					  re_node_set *dest_nodes,+					  const re_node_set *candidates,+					  re_node_set *limits,+					  struct re_backref_cache_entry *bkref_ents,+					  int str_idx) internal_function;+static reg_errcode_t sift_states_bkref (const re_match_context_t *mctx,+					re_sift_context_t *sctx,+					int str_idx, const re_node_set *candidates)+     internal_function;+static reg_errcode_t merge_state_array (const re_dfa_t *dfa,+					re_dfastate_t **dst,+					re_dfastate_t **src, int num)+     internal_function;+static re_dfastate_t *find_recover_state (reg_errcode_t *err,+					 re_match_context_t *mctx) internal_function;+static re_dfastate_t *transit_state (reg_errcode_t *err,+				     re_match_context_t *mctx,+				     re_dfastate_t *state) internal_function;+static re_dfastate_t *merge_state_with_log (reg_errcode_t *err,+					    re_match_context_t *mctx,+					    re_dfastate_t *next_state)+     internal_function;+static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx,+						re_node_set *cur_nodes,+						int str_idx) internal_function;+#if 0+static re_dfastate_t *transit_state_sb (reg_errcode_t *err,+					re_match_context_t *mctx,+					re_dfastate_t *pstate)+     internal_function;+#endif+#ifdef RE_ENABLE_I18N+static reg_errcode_t transit_state_mb (re_match_context_t *mctx,+				       re_dfastate_t *pstate)+     internal_function;+#endif /* RE_ENABLE_I18N */+static reg_errcode_t transit_state_bkref (re_match_context_t *mctx,+					  const re_node_set *nodes)+     internal_function;+static reg_errcode_t get_subexp (re_match_context_t *mctx,+				 int bkref_node, int bkref_str_idx)+     internal_function;+static reg_errcode_t get_subexp_sub (re_match_context_t *mctx,+				     const re_sub_match_top_t *sub_top,+				     re_sub_match_last_t *sub_last,+				     int bkref_node, int bkref_str)+     internal_function;+static int find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,+			     int subexp_idx, int type) internal_function;+static reg_errcode_t check_arrival (re_match_context_t *mctx,+				    state_array_t *path, int top_node,+				    int top_str, int last_node, int last_str,+				    int type) internal_function;+static reg_errcode_t check_arrival_add_next_nodes (re_match_context_t *mctx,+						   int str_idx,+						   re_node_set *cur_nodes,+						   re_node_set *next_nodes)+     internal_function;+static reg_errcode_t check_arrival_expand_ecl (const re_dfa_t *dfa,+					       re_node_set *cur_nodes,+					       int ex_subexp, int type)+     internal_function;+static reg_errcode_t check_arrival_expand_ecl_sub (const re_dfa_t *dfa,+						   re_node_set *dst_nodes,+						   int target, int ex_subexp,+						   int type) internal_function;+static reg_errcode_t expand_bkref_cache (re_match_context_t *mctx,+					 re_node_set *cur_nodes, int cur_str,+					 int subexp_num, int type)+     internal_function;+static int build_trtable (const re_dfa_t *dfa,+			  re_dfastate_t *state) internal_function;+#ifdef RE_ENABLE_I18N+static int check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,+				    const re_string_t *input, int idx)+     internal_function;+# ifdef _LIBC+static unsigned int find_collation_sequence_value (const unsigned char *mbs,+						   size_t name_len)+     internal_function;+# endif /* _LIBC */+#endif /* RE_ENABLE_I18N */+static int group_nodes_into_DFAstates (const re_dfa_t *dfa,+				       const re_dfastate_t *state,+				       re_node_set *states_node,+				       bitset_t *states_ch) internal_function;+static int check_node_accept (const re_match_context_t *mctx,+			      const re_token_t *node, int idx)+     internal_function;+static reg_errcode_t extend_buffers (re_match_context_t *mctx)+     internal_function;++/* Entry point for POSIX code.  */++/* regexec searches for a given pattern, specified by PREG, in the+   string STRING.++   If NMATCH is zero or REG_NOSUB was set in the cflags argument to+   `regcomp', we ignore PMATCH.  Otherwise, we assume PMATCH has at+   least NMATCH elements, and we set them to the offsets of the+   corresponding matched substrings.++   EFLAGS specifies `execution flags' which affect matching: if+   REG_NOTBOL is set, then ^ does not match at the beginning of the+   string; if REG_NOTEOL is set, then $ does not match at the end.++   We return 0 if we find a match and REG_NOMATCH if not.  */++int+regexec (preg, string, nmatch, pmatch, eflags)+    const regex_t *__restrict preg;+    const char *__restrict string;+    size_t nmatch;+    regmatch_t pmatch[];+    int eflags;+{+  reg_errcode_t err;+  int start, length;+  re_dfa_t *dfa = (re_dfa_t *) preg->buffer;++  if (eflags & ~(REG_NOTBOL | REG_NOTEOL | REG_STARTEND))+    return REG_BADPAT;++  if (eflags & REG_STARTEND)+    {+      start = pmatch[0].rm_so;+      length = pmatch[0].rm_eo;+    }+  else+    {+      start = 0;+      length = strlen (string);+    }++  __libc_lock_lock (dfa->lock);+  if (preg->no_sub)+    err = re_search_internal (preg, string, length, start, length - start,+			      length, 0, NULL, eflags);+  else+    err = re_search_internal (preg, string, length, start, length - start,+			      length, nmatch, pmatch, eflags);+  __libc_lock_unlock (dfa->lock);+  return err != REG_NOERROR;+}++#ifdef _LIBC+# include <shlib-compat.h>+versioned_symbol (libc, __regexec, regexec, GLIBC_2_3_4);++# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)+__typeof__ (__regexec) __compat_regexec;++int+attribute_compat_text_section+__compat_regexec (const regex_t *__restrict preg,+		  const char *__restrict string, size_t nmatch,+		  regmatch_t pmatch[], int eflags)+{+  return regexec (preg, string, nmatch, pmatch,+		  eflags & (REG_NOTBOL | REG_NOTEOL));+}+compat_symbol (libc, __compat_regexec, regexec, GLIBC_2_0);+# endif+#endif++/* Entry points for GNU code.  */++/* re_match, re_search, re_match_2, re_search_2++   The former two functions operate on STRING with length LENGTH,+   while the later two operate on concatenation of STRING1 and STRING2+   with lengths LENGTH1 and LENGTH2, respectively.++   re_match() matches the compiled pattern in BUFP against the string,+   starting at index START.++   re_search() first tries matching at index START, then it tries to match+   starting from index START + 1, and so on.  The last start position tried+   is START + RANGE.  (Thus RANGE = 0 forces re_search to operate the same+   way as re_match().)++   The parameter STOP of re_{match,search}_2 specifies that no match exceeding+   the first STOP characters of the concatenation of the strings should be+   concerned.++   If REGS is not NULL, and BUFP->no_sub is not set, the offsets of the match+   and all groups is stroed in REGS.  (For the "_2" variants, the offsets are+   computed relative to the concatenation, not relative to the individual+   strings.)++   On success, re_match* functions return the length of the match, re_search*+   return the position of the start of the match.  Return value -1 means no+   match was found and -2 indicates an internal error.  */++int+re_match (bufp, string, length, start, regs)+    struct re_pattern_buffer *bufp;+    const char *string;+    int length, start;+    struct re_registers *regs;+{+  return re_search_stub (bufp, string, length, start, 0, length, regs, 1);+}+#ifdef _LIBC+weak_alias (__re_match, re_match)+#endif++int+re_search (bufp, string, length, start, range, regs)+    struct re_pattern_buffer *bufp;+    const char *string;+    int length, start, range;+    struct re_registers *regs;+{+  return re_search_stub (bufp, string, length, start, range, length, regs, 0);+}+#ifdef _LIBC+weak_alias (__re_search, re_search)+#endif++int+re_match_2 (bufp, string1, length1, string2, length2, start, regs, stop)+    struct re_pattern_buffer *bufp;+    const char *string1, *string2;+    int length1, length2, start, stop;+    struct re_registers *regs;+{+  return re_search_2_stub (bufp, string1, length1, string2, length2,+			   start, 0, regs, stop, 1);+}+#ifdef _LIBC+weak_alias (__re_match_2, re_match_2)+#endif++int+re_search_2 (bufp, string1, length1, string2, length2, start, range, regs, stop)+    struct re_pattern_buffer *bufp;+    const char *string1, *string2;+    int length1, length2, start, range, stop;+    struct re_registers *regs;+{+  return re_search_2_stub (bufp, string1, length1, string2, length2,+			   start, range, regs, stop, 0);+}+#ifdef _LIBC+weak_alias (__re_search_2, re_search_2)+#endif++static int+re_search_2_stub (bufp, string1, length1, string2, length2, start, range, regs,+		  stop, ret_len)+    struct re_pattern_buffer *bufp;+    const char *string1, *string2;+    int length1, length2, start, range, stop, ret_len;+    struct re_registers *regs;+{+  const char *str;+  int rval;+  int len = length1 + length2;+  int free_str = 0;++  if (BE (length1 < 0 || length2 < 0 || stop < 0, 0))+    return -2;++  /* Concatenate the strings.  */+  if (length2 > 0)+    if (length1 > 0)+      {+	char *s = re_malloc (char, len);++	if (BE (s == NULL, 0))+	  return -2;+#ifdef _LIBC+	memcpy (__mempcpy (s, string1, length1), string2, length2);+#else+	memcpy (s, string1, length1);+	memcpy (s + length1, string2, length2);+#endif+	str = s;+	free_str = 1;+      }+    else+      str = string2;+  else+    str = string1;++  rval = re_search_stub (bufp, str, len, start, range, stop, regs,+			 ret_len);+  if (free_str)+    re_free ((char *) str);+  return rval;+}++/* The parameters have the same meaning as those of re_search.+   Additional parameters:+   If RET_LEN is nonzero the length of the match is returned (re_match style);+   otherwise the position of the match is returned.  */++static int+re_search_stub (bufp, string, length, start, range, stop, regs, ret_len)+    struct re_pattern_buffer *bufp;+    const char *string;+    int length, start, range, stop, ret_len;+    struct re_registers *regs;+{+  reg_errcode_t result;+  regmatch_t *pmatch;+  int nregs, rval;+  int eflags = 0;+  re_dfa_t *dfa = (re_dfa_t *) bufp->buffer;++  /* Check for out-of-range.  */+  if (BE (start < 0 || start > length, 0))+    return -1;+  if (BE (start + range > length, 0))+    range = length - start;+  else if (BE (start + range < 0, 0))+    range = -start;++  __libc_lock_lock (dfa->lock);++  eflags |= (bufp->not_bol) ? REG_NOTBOL : 0;+  eflags |= (bufp->not_eol) ? REG_NOTEOL : 0;++  /* Compile fastmap if we haven't yet.  */+  if (range > 0 && bufp->fastmap != NULL && !bufp->fastmap_accurate)+    re_compile_fastmap (bufp);++  if (BE (bufp->no_sub, 0))+    regs = NULL;++  /* We need at least 1 register.  */+  if (regs == NULL)+    nregs = 1;+  else if (BE (bufp->regs_allocated == REGS_FIXED &&+	       regs->num_regs < bufp->re_nsub + 1, 0))+    {+      nregs = regs->num_regs;+      if (BE (nregs < 1, 0))+	{+	  /* Nothing can be copied to regs.  */+	  regs = NULL;+	  nregs = 1;+	}+    }+  else+    nregs = bufp->re_nsub + 1;+  pmatch = re_malloc (regmatch_t, nregs);+  if (BE (pmatch == NULL, 0))+    {+      rval = -2;+      goto out;+    }++  result = re_search_internal (bufp, string, length, start, range, stop,+			       nregs, pmatch, eflags);++  rval = 0;++  /* I hope we needn't fill ther regs with -1's when no match was found.  */+  if (result != REG_NOERROR)+    rval = -1;+  else if (regs != NULL)+    {+      /* If caller wants register contents data back, copy them.  */+      bufp->regs_allocated = re_copy_regs (regs, pmatch, nregs,+					   bufp->regs_allocated);+      if (BE (bufp->regs_allocated == REGS_UNALLOCATED, 0))+	rval = -2;+    }++  if (BE (rval == 0, 1))+    {+      if (ret_len)+	{+	  assert (pmatch[0].rm_so == start);+	  rval = pmatch[0].rm_eo - start;+	}+      else+	rval = pmatch[0].rm_so;+    }+  re_free (pmatch);+ out:+  __libc_lock_unlock (dfa->lock);+  return rval;+}++static unsigned+re_copy_regs (regs, pmatch, nregs, regs_allocated)+    struct re_registers *regs;+    regmatch_t *pmatch;+    int nregs, regs_allocated;+{+  int rval = REGS_REALLOCATE;+  int i;+  int need_regs = nregs + 1;+  /* We need one extra element beyond `num_regs' for the `-1' marker GNU code+     uses.  */++  /* Have the register data arrays been allocated?  */+  if (regs_allocated == REGS_UNALLOCATED)+    { /* No.  So allocate them with malloc.  */+      regs->start = re_malloc (regoff_t, need_regs);+      regs->end = re_malloc (regoff_t, need_regs);+      if (BE (regs->start == NULL, 0) || BE (regs->end == NULL, 0))+	return REGS_UNALLOCATED;+      regs->num_regs = need_regs;+    }+  else if (regs_allocated == REGS_REALLOCATE)+    { /* Yes.  If we need more elements than were already+	 allocated, reallocate them.  If we need fewer, just+	 leave it alone.  */+      if (BE (need_regs > regs->num_regs, 0))+	{+	  regoff_t *new_start = re_realloc (regs->start, regoff_t, need_regs);+	  regoff_t *new_end = re_realloc (regs->end, regoff_t, need_regs);+	  if (BE (new_start == NULL, 0) || BE (new_end == NULL, 0))+	    return REGS_UNALLOCATED;+	  regs->start = new_start;+	  regs->end = new_end;+	  regs->num_regs = need_regs;+	}+    }+  else+    {+      assert (regs_allocated == REGS_FIXED);+      /* This function may not be called with REGS_FIXED and nregs too big.  */+      assert (regs->num_regs >= nregs);+      rval = REGS_FIXED;+    }++  /* Copy the regs.  */+  for (i = 0; i < nregs; ++i)+    {+      regs->start[i] = pmatch[i].rm_so;+      regs->end[i] = pmatch[i].rm_eo;+    }+  for ( ; i < regs->num_regs; ++i)+    regs->start[i] = regs->end[i] = -1;++  return rval;+}++/* Set REGS to hold NUM_REGS registers, storing them in STARTS and+   ENDS.  Subsequent matches using PATTERN_BUFFER and REGS will use+   this memory for recording register information.  STARTS and ENDS+   must be allocated using the malloc library routine, and must each+   be at least NUM_REGS * sizeof (regoff_t) bytes long.++   If NUM_REGS == 0, then subsequent matches should allocate their own+   register data.++   Unless this function is called, the first search or match using+   PATTERN_BUFFER will allocate its own register data, without+   freeing the old data.  */++void+re_set_registers (bufp, regs, num_regs, starts, ends)+    struct re_pattern_buffer *bufp;+    struct re_registers *regs;+    unsigned num_regs;+    regoff_t *starts, *ends;+{+  if (num_regs)+    {+      bufp->regs_allocated = REGS_REALLOCATE;+      regs->num_regs = num_regs;+      regs->start = starts;+      regs->end = ends;+    }+  else+    {+      bufp->regs_allocated = REGS_UNALLOCATED;+      regs->num_regs = 0;+      regs->start = regs->end = (regoff_t *) 0;+    }+}+#ifdef _LIBC+weak_alias (__re_set_registers, re_set_registers)+#endif++/* Entry points compatible with 4.2 BSD regex library.  We don't define+   them unless specifically requested.  */++#if defined _REGEX_RE_COMP || defined _LIBC+int+# ifdef _LIBC+weak_function+# endif+re_exec (s)+     const char *s;+{+  return 0 == regexec (&re_comp_buf, s, 0, NULL, 0);+}+#endif /* _REGEX_RE_COMP */++/* Internal entry point.  */++/* Searches for a compiled pattern PREG in the string STRING, whose+   length is LENGTH.  NMATCH, PMATCH, and EFLAGS have the same+   mingings with regexec.  START, and RANGE have the same meanings+   with re_search.+   Return REG_NOERROR if we find a match, and REG_NOMATCH if not,+   otherwise return the error code.+   Note: We assume front end functions already check ranges.+   (START + RANGE >= 0 && START + RANGE <= LENGTH)  */++static reg_errcode_t+re_search_internal (preg, string, length, start, range, stop, nmatch, pmatch,+		    eflags)+    const regex_t *preg;+    const char *string;+    int length, start, range, stop, eflags;+    size_t nmatch;+    regmatch_t pmatch[];+{+  reg_errcode_t err;+  const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer;+  int left_lim, right_lim, incr;+  int fl_longest_match, match_first, match_kind, match_last = -1;+  int extra_nmatch;+  int sb, ch;+#if defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)+  re_match_context_t mctx = { .dfa = dfa };+#else+  re_match_context_t mctx;+#endif+  char *fastmap = (preg->fastmap != NULL && preg->fastmap_accurate+		   && range && !preg->can_be_null) ? preg->fastmap : NULL;+  RE_TRANSLATE_TYPE t = preg->translate;++#if !(defined _LIBC || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L))+  memset (&mctx, '\0', sizeof (re_match_context_t));+  mctx.dfa = dfa;+#endif++  extra_nmatch = (nmatch > preg->re_nsub) ? nmatch - (preg->re_nsub + 1) : 0;+  nmatch -= extra_nmatch;++  /* Check if the DFA haven't been compiled.  */+  if (BE (preg->used == 0 || dfa->init_state == NULL+	  || dfa->init_state_word == NULL || dfa->init_state_nl == NULL+	  || dfa->init_state_begbuf == NULL, 0))+    return REG_NOMATCH;++#ifdef DEBUG+  /* We assume front-end functions already check them.  */+  assert (start + range >= 0 && start + range <= length);+#endif++  /* If initial states with non-begbuf contexts have no elements,+     the regex must be anchored.  If preg->newline_anchor is set,+     we'll never use init_state_nl, so do not check it.  */+  if (dfa->init_state->nodes.nelem == 0+      && dfa->init_state_word->nodes.nelem == 0+      && (dfa->init_state_nl->nodes.nelem == 0+	  || !preg->newline_anchor))+    {+      if (start != 0 && start + range != 0)+        return REG_NOMATCH;+      start = range = 0;+    }++  /* We must check the longest matching, if nmatch > 0.  */+  fl_longest_match = (nmatch != 0 || dfa->nbackref);++  err = re_string_allocate (&mctx.input, string, length, dfa->nodes_len + 1,+			    preg->translate, preg->syntax & RE_ICASE, dfa);+  if (BE (err != REG_NOERROR, 0))+    goto free_return;+  mctx.input.stop = stop;+  mctx.input.raw_stop = stop;+  mctx.input.newline_anchor = preg->newline_anchor;++  err = match_ctx_init (&mctx, eflags, dfa->nbackref * 2);+  if (BE (err != REG_NOERROR, 0))+    goto free_return;++  /* We will log all the DFA states through which the dfa pass,+     if nmatch > 1, or this dfa has "multibyte node", which is a+     back-reference or a node which can accept multibyte character or+     multi character collating element.  */+  if (nmatch > 1 || dfa->has_mb_node)+    {+      mctx.state_log = re_malloc (re_dfastate_t *, mctx.input.bufs_len + 1);+      if (BE (mctx.state_log == NULL, 0))+	{+	  err = REG_ESPACE;+	  goto free_return;+	}+    }+  else+    mctx.state_log = NULL;++  match_first = start;+  mctx.input.tip_context = (eflags & REG_NOTBOL) ? CONTEXT_BEGBUF+			   : CONTEXT_NEWLINE | CONTEXT_BEGBUF;++  /* Check incrementally whether of not the input string match.  */+  incr = (range < 0) ? -1 : 1;+  left_lim = (range < 0) ? start + range : start;+  right_lim = (range < 0) ? start : start + range;+  sb = dfa->mb_cur_max == 1;+  match_kind =+    (fastmap+     ? ((sb || !(preg->syntax & RE_ICASE || t) ? 4 : 0)+	| (range >= 0 ? 2 : 0)+	| (t != NULL ? 1 : 0))+     : 8);++  for (;; match_first += incr)+    {+      err = REG_NOMATCH;+      if (match_first < left_lim || right_lim < match_first)+	goto free_return;++      /* Advance as rapidly as possible through the string, until we+	 find a plausible place to start matching.  This may be done+	 with varying efficiency, so there are various possibilities:+	 only the most common of them are specialized, in order to+	 save on code size.  We use a switch statement for speed.  */+      switch (match_kind)+	{+	case 8:+	  /* No fastmap.  */+	  break;++	case 7:+	  /* Fastmap with single-byte translation, match forward.  */+	  while (BE (match_first < right_lim, 1)+		 && !fastmap[t[(unsigned char) string[match_first]]])+	    ++match_first;+	  goto forward_match_found_start_or_reached_end;++	case 6:+	  /* Fastmap without translation, match forward.  */+	  while (BE (match_first < right_lim, 1)+		 && !fastmap[(unsigned char) string[match_first]])+	    ++match_first;++	forward_match_found_start_or_reached_end:+	  if (BE (match_first == right_lim, 0))+	    {+	      ch = match_first >= length+		       ? 0 : (unsigned char) string[match_first];+	      if (!fastmap[t ? t[ch] : ch])+		goto free_return;+	    }+	  break;++	case 4:+	case 5:+	  /* Fastmap without multi-byte translation, match backwards.  */+	  while (match_first >= left_lim)+	    {+	      ch = match_first >= length+		       ? 0 : (unsigned char) string[match_first];+	      if (fastmap[t ? t[ch] : ch])+		break;+	      --match_first;+	    }+	  if (match_first < left_lim)+	    goto free_return;+	  break;++	default:+	  /* In this case, we can't determine easily the current byte,+	     since it might be a component byte of a multibyte+	     character.  Then we use the constructed buffer instead.  */+	  for (;;)+	    {+	      /* If MATCH_FIRST is out of the valid range, reconstruct the+		 buffers.  */+	      unsigned int offset = match_first - mctx.input.raw_mbs_idx;+	      if (BE (offset >= (unsigned int) mctx.input.valid_raw_len, 0))+		{+		  err = re_string_reconstruct (&mctx.input, match_first,+					       eflags);+		  if (BE (err != REG_NOERROR, 0))+		    goto free_return;++		  offset = match_first - mctx.input.raw_mbs_idx;+		}+	      /* If MATCH_FIRST is out of the buffer, leave it as '\0'.+		 Note that MATCH_FIRST must not be smaller than 0.  */+	      ch = (match_first >= length+		    ? 0 : re_string_byte_at (&mctx.input, offset));+	      if (fastmap[ch])+		break;+	      match_first += incr;+	      if (match_first < left_lim || match_first > right_lim)+	        {+	          err = REG_NOMATCH;+	          goto free_return;+	        }+	    }+	  break;+	}++      /* Reconstruct the buffers so that the matcher can assume that+	 the matching starts from the beginning of the buffer.  */+      err = re_string_reconstruct (&mctx.input, match_first, eflags);+      if (BE (err != REG_NOERROR, 0))+	goto free_return;++#ifdef RE_ENABLE_I18N+     /* Don't consider this char as a possible match start if it part,+	yet isn't the head, of a multibyte character.  */+      if (!sb && !re_string_first_byte (&mctx.input, 0))+	continue;+#endif++      /* It seems to be appropriate one, then use the matcher.  */+      /* We assume that the matching starts from 0.  */+      mctx.state_log_top = mctx.nbkref_ents = mctx.max_mb_elem_len = 0;+      match_last = check_matching (&mctx, fl_longest_match,+				   range >= 0 ? &match_first : NULL);+      if (match_last != -1)+	{+	  if (BE (match_last == -2, 0))+	    {+	      err = REG_ESPACE;+	      goto free_return;+	    }+	  else+	    {+	      mctx.match_last = match_last;+	      if ((!preg->no_sub && nmatch > 1) || dfa->nbackref)+		{+		  re_dfastate_t *pstate = mctx.state_log[match_last];+		  mctx.last_node = check_halt_state_context (&mctx, pstate,+							     match_last);+		}+	      if ((!preg->no_sub && nmatch > 1 && dfa->has_plural_match)+		  || dfa->nbackref)+		{+		  err = prune_impossible_nodes (&mctx);+		  if (err == REG_NOERROR)+		    break;+		  if (BE (err != REG_NOMATCH, 0))+		    goto free_return;+		  match_last = -1;+		}+	      else+		break; /* We found a match.  */+	    }+	}++      match_ctx_clean (&mctx);+    }++#ifdef DEBUG+  assert (match_last != -1);+  assert (err == REG_NOERROR);+#endif++  /* Set pmatch[] if we need.  */+  if (nmatch > 0)+    {+      int reg_idx;++      /* Initialize registers.  */+      for (reg_idx = 1; reg_idx < nmatch; ++reg_idx)+	pmatch[reg_idx].rm_so = pmatch[reg_idx].rm_eo = -1;++      /* Set the points where matching start/end.  */+      pmatch[0].rm_so = 0;+      pmatch[0].rm_eo = mctx.match_last;++      if (!preg->no_sub && nmatch > 1)+	{+	  err = set_regs (preg, &mctx, nmatch, pmatch,+			  dfa->has_plural_match && dfa->nbackref > 0);+	  if (BE (err != REG_NOERROR, 0))+	    goto free_return;+	}++      /* At last, add the offset to the each registers, since we slided+	 the buffers so that we could assume that the matching starts+	 from 0.  */+      for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)+	if (pmatch[reg_idx].rm_so != -1)+	  {+#ifdef RE_ENABLE_I18N+	    if (BE (mctx.input.offsets_needed != 0, 0))+	      {+		pmatch[reg_idx].rm_so =+		  (pmatch[reg_idx].rm_so == mctx.input.valid_len+		   ? mctx.input.valid_raw_len+		   : mctx.input.offsets[pmatch[reg_idx].rm_so]);+		pmatch[reg_idx].rm_eo =+		  (pmatch[reg_idx].rm_eo == mctx.input.valid_len+		   ? mctx.input.valid_raw_len+		   : mctx.input.offsets[pmatch[reg_idx].rm_eo]);+	      }+#else+	    assert (mctx.input.offsets_needed == 0);+#endif+	    pmatch[reg_idx].rm_so += match_first;+	    pmatch[reg_idx].rm_eo += match_first;+	  }+      for (reg_idx = 0; reg_idx < extra_nmatch; ++reg_idx)+	{+	  pmatch[nmatch + reg_idx].rm_so = -1;+	  pmatch[nmatch + reg_idx].rm_eo = -1;+	}++      if (dfa->subexp_map)+        for (reg_idx = 0; reg_idx + 1 < nmatch; reg_idx++)+          if (dfa->subexp_map[reg_idx] != reg_idx)+            {+              pmatch[reg_idx + 1].rm_so+                = pmatch[dfa->subexp_map[reg_idx] + 1].rm_so;+              pmatch[reg_idx + 1].rm_eo+                = pmatch[dfa->subexp_map[reg_idx] + 1].rm_eo;+            }+    }++ free_return:+  re_free (mctx.state_log);+  if (dfa->nbackref)+    match_ctx_free (&mctx);+  re_string_destruct (&mctx.input);+  return err;+}++static reg_errcode_t+prune_impossible_nodes (mctx)+     re_match_context_t *mctx;+{+  const re_dfa_t *const dfa = mctx->dfa;+  int halt_node, match_last;+  reg_errcode_t ret;+  re_dfastate_t **sifted_states;+  re_dfastate_t **lim_states = NULL;+  re_sift_context_t sctx;+#ifdef DEBUG+  assert (mctx->state_log != NULL);+#endif+  match_last = mctx->match_last;+  halt_node = mctx->last_node;+  sifted_states = re_malloc (re_dfastate_t *, match_last + 1);+  if (BE (sifted_states == NULL, 0))+    {+      ret = REG_ESPACE;+      goto free_return;+    }+  if (dfa->nbackref)+    {+      lim_states = re_malloc (re_dfastate_t *, match_last + 1);+      if (BE (lim_states == NULL, 0))+	{+	  ret = REG_ESPACE;+	  goto free_return;+	}+      while (1)+	{+	  memset (lim_states, '\0',+		  sizeof (re_dfastate_t *) * (match_last + 1));+	  sift_ctx_init (&sctx, sifted_states, lim_states, halt_node,+			 match_last);+	  ret = sift_states_backward (mctx, &sctx);+	  re_node_set_free (&sctx.limits);+	  if (BE (ret != REG_NOERROR, 0))+	      goto free_return;+	  if (sifted_states[0] != NULL || lim_states[0] != NULL)+	    break;+	  do+	    {+	      --match_last;+	      if (match_last < 0)+		{+		  ret = REG_NOMATCH;+		  goto free_return;+		}+	    } while (mctx->state_log[match_last] == NULL+		     || !mctx->state_log[match_last]->halt);+	  halt_node = check_halt_state_context (mctx,+						mctx->state_log[match_last],+						match_last);+	}+      ret = merge_state_array (dfa, sifted_states, lim_states,+			       match_last + 1);+      re_free (lim_states);+      lim_states = NULL;+      if (BE (ret != REG_NOERROR, 0))+	goto free_return;+    }+  else+    {+      sift_ctx_init (&sctx, sifted_states, lim_states, halt_node, match_last);+      ret = sift_states_backward (mctx, &sctx);+      re_node_set_free (&sctx.limits);+      if (BE (ret != REG_NOERROR, 0))+	goto free_return;+    }+  re_free (mctx->state_log);+  mctx->state_log = sifted_states;+  sifted_states = NULL;+  mctx->last_node = halt_node;+  mctx->match_last = match_last;+  ret = REG_NOERROR;+ free_return:+  re_free (sifted_states);+  re_free (lim_states);+  return ret;+}++/* Acquire an initial state and return it.+   We must select appropriate initial state depending on the context,+   since initial states may have constraints like "\<", "^", etc..  */++static inline re_dfastate_t *+__attribute ((always_inline)) internal_function+acquire_init_state_context (reg_errcode_t *err, const re_match_context_t *mctx,+			    int idx)+{+  const re_dfa_t *const dfa = mctx->dfa;+  if (dfa->init_state->has_constraint)+    {+      unsigned int context;+      context = re_string_context_at (&mctx->input, idx - 1, mctx->eflags);+      if (IS_WORD_CONTEXT (context))+	return dfa->init_state_word;+      else if (IS_ORDINARY_CONTEXT (context))+	return dfa->init_state;+      else if (IS_BEGBUF_CONTEXT (context) && IS_NEWLINE_CONTEXT (context))+	return dfa->init_state_begbuf;+      else if (IS_NEWLINE_CONTEXT (context))+	return dfa->init_state_nl;+      else if (IS_BEGBUF_CONTEXT (context))+	{+	  /* It is relatively rare case, then calculate on demand.  */+	  return re_acquire_state_context (err, dfa,+					   dfa->init_state->entrance_nodes,+					   context);+	}+      else+	/* Must not happen?  */+	return dfa->init_state;+    }+  else+    return dfa->init_state;+}++/* Check whether the regular expression match input string INPUT or not,+   and return the index where the matching end, return -1 if not match,+   or return -2 in case of an error.+   FL_LONGEST_MATCH means we want the POSIX longest matching.+   If P_MATCH_FIRST is not NULL, and the match fails, it is set to the+   next place where we may want to try matching.+   Note that the matcher assume that the maching starts from the current+   index of the buffer.  */++static int+internal_function+check_matching (re_match_context_t *mctx, int fl_longest_match,+		int *p_match_first)+{+  const re_dfa_t *const dfa = mctx->dfa;+  reg_errcode_t err;+  int match = 0;+  int match_last = -1;+  int cur_str_idx = re_string_cur_idx (&mctx->input);+  re_dfastate_t *cur_state;+  int at_init_state = p_match_first != NULL;+  int next_start_idx = cur_str_idx;++  err = REG_NOERROR;+  cur_state = acquire_init_state_context (&err, mctx, cur_str_idx);+  /* An initial state must not be NULL (invalid).  */+  if (BE (cur_state == NULL, 0))+    {+      assert (err == REG_ESPACE);+      return -2;+    }++  if (mctx->state_log != NULL)+    {+      mctx->state_log[cur_str_idx] = cur_state;++      /* Check OP_OPEN_SUBEXP in the initial state in case that we use them+	 later.  E.g. Processing back references.  */+      if (BE (dfa->nbackref, 0))+	{+	  at_init_state = 0;+	  err = check_subexp_matching_top (mctx, &cur_state->nodes, 0);+	  if (BE (err != REG_NOERROR, 0))+	    return err;++	  if (cur_state->has_backref)+	    {+	      err = transit_state_bkref (mctx, &cur_state->nodes);+	      if (BE (err != REG_NOERROR, 0))+	        return err;+	    }+	}+    }++  /* If the RE accepts NULL string.  */+  if (BE (cur_state->halt, 0))+    {+      if (!cur_state->has_constraint+	  || check_halt_state_context (mctx, cur_state, cur_str_idx))+	{+	  if (!fl_longest_match)+	    return cur_str_idx;+	  else+	    {+	      match_last = cur_str_idx;+	      match = 1;+	    }+	}+    }++  while (!re_string_eoi (&mctx->input))+    {+      re_dfastate_t *old_state = cur_state;+      int next_char_idx = re_string_cur_idx (&mctx->input) + 1;++      if (BE (next_char_idx >= mctx->input.bufs_len, 0)+          || (BE (next_char_idx >= mctx->input.valid_len, 0)+              && mctx->input.valid_len < mctx->input.len))+        {+          err = extend_buffers (mctx);+          if (BE (err != REG_NOERROR, 0))+	    {+	      assert (err == REG_ESPACE);+	      return -2;+	    }+        }++      cur_state = transit_state (&err, mctx, cur_state);+      if (mctx->state_log != NULL)+	cur_state = merge_state_with_log (&err, mctx, cur_state);++      if (cur_state == NULL)+	{+	  /* Reached the invalid state or an error.  Try to recover a valid+	     state using the state log, if available and if we have not+	     already found a valid (even if not the longest) match.  */+	  if (BE (err != REG_NOERROR, 0))+	    return -2;++	  if (mctx->state_log == NULL+	      || (match && !fl_longest_match)+	      || (cur_state = find_recover_state (&err, mctx)) == NULL)+	    break;+	}++      if (BE (at_init_state, 0))+	{+	  if (old_state == cur_state)+	    next_start_idx = next_char_idx;+	  else+	    at_init_state = 0;+	}++      if (cur_state->halt)+	{+	  /* Reached a halt state.+	     Check the halt state can satisfy the current context.  */+	  if (!cur_state->has_constraint+	      || check_halt_state_context (mctx, cur_state,+					   re_string_cur_idx (&mctx->input)))+	    {+	      /* We found an appropriate halt state.  */+	      match_last = re_string_cur_idx (&mctx->input);+	      match = 1;++	      /* We found a match, do not modify match_first below.  */+	      p_match_first = NULL;+	      if (!fl_longest_match)+		break;+	    }+	}+    }++  if (p_match_first)+    *p_match_first += next_start_idx;++  return match_last;+}++/* Check NODE match the current context.  */++static int+internal_function+check_halt_node_context (const re_dfa_t *dfa, int node, unsigned int context)+{+  re_token_type_t type = dfa->nodes[node].type;+  unsigned int constraint = dfa->nodes[node].constraint;+  if (type != END_OF_RE)+    return 0;+  if (!constraint)+    return 1;+  if (NOT_SATISFY_NEXT_CONSTRAINT (constraint, context))+    return 0;+  return 1;+}++/* Check the halt state STATE match the current context.+   Return 0 if not match, if the node, STATE has, is a halt node and+   match the context, return the node.  */++static int+internal_function+check_halt_state_context (const re_match_context_t *mctx,+			  const re_dfastate_t *state, int idx)+{+  int i;+  unsigned int context;+#ifdef DEBUG+  assert (state->halt);+#endif+  context = re_string_context_at (&mctx->input, idx, mctx->eflags);+  for (i = 0; i < state->nodes.nelem; ++i)+    if (check_halt_node_context (mctx->dfa, state->nodes.elems[i], context))+      return state->nodes.elems[i];+  return 0;+}++/* Compute the next node to which "NFA" transit from NODE("NFA" is a NFA+   corresponding to the DFA).+   Return the destination node, and update EPS_VIA_NODES, return -1 in case+   of errors.  */++static int+internal_function+proceed_next_node (const re_match_context_t *mctx, int nregs, regmatch_t *regs,+		   int *pidx, int node, re_node_set *eps_via_nodes,+		   struct re_fail_stack_t *fs)+{+  const re_dfa_t *const dfa = mctx->dfa;+  int i, err;+  if (IS_EPSILON_NODE (dfa->nodes[node].type))+    {+      re_node_set *cur_nodes = &mctx->state_log[*pidx]->nodes;+      re_node_set *edests = &dfa->edests[node];+      int dest_node;+      err = re_node_set_insert (eps_via_nodes, node);+      if (BE (err < 0, 0))+	return -2;+      /* Pick up a valid destination, or return -1 if none is found.  */+      for (dest_node = -1, i = 0; i < edests->nelem; ++i)+	{+	  int candidate = edests->elems[i];+	  if (!re_node_set_contains (cur_nodes, candidate))+	    continue;+          if (dest_node == -1)+	    dest_node = candidate;++          else+	    {+	      /* In order to avoid infinite loop like "(a*)*", return the second+	         epsilon-transition if the first was already considered.  */+	      if (re_node_set_contains (eps_via_nodes, dest_node))+	        return candidate;++	      /* Otherwise, push the second epsilon-transition on the fail stack.  */+	      else if (fs != NULL+		       && push_fail_stack (fs, *pidx, candidate, nregs, regs,+				           eps_via_nodes))+		return -2;++	      /* We know we are going to exit.  */+	      break;+	    }+	}+      return dest_node;+    }+  else+    {+      int naccepted = 0;+      re_token_type_t type = dfa->nodes[node].type;++#ifdef RE_ENABLE_I18N+      if (dfa->nodes[node].accept_mb)+	naccepted = check_node_accept_bytes (dfa, node, &mctx->input, *pidx);+      else+#endif /* RE_ENABLE_I18N */+      if (type == OP_BACK_REF)+	{+	  int subexp_idx = dfa->nodes[node].opr.idx + 1;+	  naccepted = regs[subexp_idx].rm_eo - regs[subexp_idx].rm_so;+	  if (fs != NULL)+	    {+	      if (regs[subexp_idx].rm_so == -1 || regs[subexp_idx].rm_eo == -1)+		return -1;+	      else if (naccepted)+		{+		  char *buf = (char *) re_string_get_buffer (&mctx->input);+		  if (memcmp (buf + regs[subexp_idx].rm_so, buf + *pidx,+			      naccepted) != 0)+		    return -1;+		}+	    }++	  if (naccepted == 0)+	    {+	      int dest_node;+	      err = re_node_set_insert (eps_via_nodes, node);+	      if (BE (err < 0, 0))+		return -2;+	      dest_node = dfa->edests[node].elems[0];+	      if (re_node_set_contains (&mctx->state_log[*pidx]->nodes,+					dest_node))+		return dest_node;+	    }+	}++      if (naccepted != 0+	  || check_node_accept (mctx, dfa->nodes + node, *pidx))+	{+	  int dest_node = dfa->nexts[node];+	  *pidx = (naccepted == 0) ? *pidx + 1 : *pidx + naccepted;+	  if (fs && (*pidx > mctx->match_last || mctx->state_log[*pidx] == NULL+		     || !re_node_set_contains (&mctx->state_log[*pidx]->nodes,+					       dest_node)))+	    return -1;+	  re_node_set_empty (eps_via_nodes);+	  return dest_node;+	}+    }+  return -1;+}++static reg_errcode_t+internal_function+push_fail_stack (struct re_fail_stack_t *fs, int str_idx, int dest_node,+		 int nregs, regmatch_t *regs, re_node_set *eps_via_nodes)+{+  reg_errcode_t err;+  int num = fs->num++;+  if (fs->num == fs->alloc)+    {+      struct re_fail_stack_ent_t *new_array;+      new_array = realloc (fs->stack, (sizeof (struct re_fail_stack_ent_t)+				       * fs->alloc * 2));+      if (new_array == NULL)+	return REG_ESPACE;+      fs->alloc *= 2;+      fs->stack = new_array;+    }+  fs->stack[num].idx = str_idx;+  fs->stack[num].node = dest_node;+  fs->stack[num].regs = re_malloc (regmatch_t, nregs);+  if (fs->stack[num].regs == NULL)+    return REG_ESPACE;+  memcpy (fs->stack[num].regs, regs, sizeof (regmatch_t) * nregs);+  err = re_node_set_init_copy (&fs->stack[num].eps_via_nodes, eps_via_nodes);+  return err;+}++static int+internal_function+pop_fail_stack (struct re_fail_stack_t *fs, int *pidx, int nregs,+		regmatch_t *regs, re_node_set *eps_via_nodes)+{+  int num = --fs->num;+  assert (num >= 0);+  *pidx = fs->stack[num].idx;+  memcpy (regs, fs->stack[num].regs, sizeof (regmatch_t) * nregs);+  re_node_set_free (eps_via_nodes);+  re_free (fs->stack[num].regs);+  *eps_via_nodes = fs->stack[num].eps_via_nodes;+  return fs->stack[num].node;+}++/* Set the positions where the subexpressions are starts/ends to registers+   PMATCH.+   Note: We assume that pmatch[0] is already set, and+   pmatch[i].rm_so == pmatch[i].rm_eo == -1 for 0 < i < nmatch.  */++static reg_errcode_t+internal_function+set_regs (const regex_t *preg, const re_match_context_t *mctx, size_t nmatch,+	  regmatch_t *pmatch, int fl_backtrack)+{+  const re_dfa_t *dfa = (const re_dfa_t *) preg->buffer;+  int idx, cur_node;+  re_node_set eps_via_nodes;+  struct re_fail_stack_t *fs;+  struct re_fail_stack_t fs_body = { 0, 2, NULL };+  regmatch_t *prev_idx_match;+  int prev_idx_match_malloced = 0;++#ifdef DEBUG+  assert (nmatch > 1);+  assert (mctx->state_log != NULL);+#endif+  if (fl_backtrack)+    {+      fs = &fs_body;+      fs->stack = re_malloc (struct re_fail_stack_ent_t, fs->alloc);+      if (fs->stack == NULL)+	return REG_ESPACE;+    }+  else+    fs = NULL;++  cur_node = dfa->init_node;+  re_node_set_init_empty (&eps_via_nodes);++  if (__libc_use_alloca (nmatch * sizeof (regmatch_t)))+    prev_idx_match = (regmatch_t *) alloca (nmatch * sizeof (regmatch_t));+  else+    {+      prev_idx_match = re_malloc (regmatch_t, nmatch);+      if (prev_idx_match == NULL)+	{+	  free_fail_stack_return (fs);+	  return REG_ESPACE;+	}+      prev_idx_match_malloced = 1;+    }+  memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);++  for (idx = pmatch[0].rm_so; idx <= pmatch[0].rm_eo ;)+    {+      update_regs (dfa, pmatch, prev_idx_match, cur_node, idx, nmatch);++      if (idx == pmatch[0].rm_eo && cur_node == mctx->last_node)+	{+	  int reg_idx;+	  if (fs)+	    {+	      for (reg_idx = 0; reg_idx < nmatch; ++reg_idx)+		if (pmatch[reg_idx].rm_so > -1 && pmatch[reg_idx].rm_eo == -1)+		  break;+	      if (reg_idx == nmatch)+		{+		  re_node_set_free (&eps_via_nodes);+		  if (prev_idx_match_malloced)+		    re_free (prev_idx_match);+		  return free_fail_stack_return (fs);+		}+	      cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,+					 &eps_via_nodes);+	    }+	  else+	    {+	      re_node_set_free (&eps_via_nodes);+	      if (prev_idx_match_malloced)+		re_free (prev_idx_match);+	      return REG_NOERROR;+	    }+	}++      /* Proceed to next node.  */+      cur_node = proceed_next_node (mctx, nmatch, pmatch, &idx, cur_node,+				    &eps_via_nodes, fs);++      if (BE (cur_node < 0, 0))+	{+	  if (BE (cur_node == -2, 0))+	    {+	      re_node_set_free (&eps_via_nodes);+	      if (prev_idx_match_malloced)+		re_free (prev_idx_match);+	      free_fail_stack_return (fs);+	      return REG_ESPACE;+	    }+	  if (fs)+	    cur_node = pop_fail_stack (fs, &idx, nmatch, pmatch,+				       &eps_via_nodes);+	  else+	    {+	      re_node_set_free (&eps_via_nodes);+	      if (prev_idx_match_malloced)+		re_free (prev_idx_match);+	      return REG_NOMATCH;+	    }+	}+    }+  re_node_set_free (&eps_via_nodes);+  if (prev_idx_match_malloced)+    re_free (prev_idx_match);+  return free_fail_stack_return (fs);+}++static reg_errcode_t+internal_function+free_fail_stack_return (struct re_fail_stack_t *fs)+{+  if (fs)+    {+      int fs_idx;+      for (fs_idx = 0; fs_idx < fs->num; ++fs_idx)+	{+	  re_node_set_free (&fs->stack[fs_idx].eps_via_nodes);+	  re_free (fs->stack[fs_idx].regs);+	}+      re_free (fs->stack);+    }+  return REG_NOERROR;+}++static void+internal_function+update_regs (const re_dfa_t *dfa, regmatch_t *pmatch,+	     regmatch_t *prev_idx_match, int cur_node, int cur_idx, int nmatch)+{+  int type = dfa->nodes[cur_node].type;+  if (type == OP_OPEN_SUBEXP)+    {+      int reg_num = dfa->nodes[cur_node].opr.idx + 1;++      /* We are at the first node of this sub expression.  */+      if (reg_num < nmatch)+	{+	  pmatch[reg_num].rm_so = cur_idx;+	  pmatch[reg_num].rm_eo = -1;+	}+    }+  else if (type == OP_CLOSE_SUBEXP)+    {+      int reg_num = dfa->nodes[cur_node].opr.idx + 1;+      if (reg_num < nmatch)+	{+	  /* We are at the last node of this sub expression.  */+	  if (pmatch[reg_num].rm_so < cur_idx)+	    {+	      pmatch[reg_num].rm_eo = cur_idx;+	      /* This is a non-empty match or we are not inside an optional+		 subexpression.  Accept this right away.  */+	      memcpy (prev_idx_match, pmatch, sizeof (regmatch_t) * nmatch);+	    }+	  else+	    {+	      if (dfa->nodes[cur_node].opt_subexp+		  && prev_idx_match[reg_num].rm_so != -1)+		/* We transited through an empty match for an optional+		   subexpression, like (a?)*, and this is not the subexp's+		   first match.  Copy back the old content of the registers+		   so that matches of an inner subexpression are undone as+		   well, like in ((a?))*.  */+		memcpy (pmatch, prev_idx_match, sizeof (regmatch_t) * nmatch);+	      else+		/* We completed a subexpression, but it may be part of+		   an optional one, so do not update PREV_IDX_MATCH.  */+		pmatch[reg_num].rm_eo = cur_idx;+	    }+	}+    }+}++/* This function checks the STATE_LOG from the SCTX->last_str_idx to 0+   and sift the nodes in each states according to the following rules.+   Updated state_log will be wrote to STATE_LOG.++   Rules: We throw away the Node `a' in the STATE_LOG[STR_IDX] if...+     1. When STR_IDX == MATCH_LAST(the last index in the state_log):+	If `a' isn't the LAST_NODE and `a' can't epsilon transit to+	the LAST_NODE, we throw away the node `a'.+     2. When 0 <= STR_IDX < MATCH_LAST and `a' accepts+	string `s' and transit to `b':+	i. If 'b' isn't in the STATE_LOG[STR_IDX+strlen('s')], we throw+	   away the node `a'.+	ii. If 'b' is in the STATE_LOG[STR_IDX+strlen('s')] but 'b' is+	    thrown away, we throw away the node `a'.+     3. When 0 <= STR_IDX < MATCH_LAST and 'a' epsilon transit to 'b':+	i. If 'b' isn't in the STATE_LOG[STR_IDX], we throw away the+	   node `a'.+	ii. If 'b' is in the STATE_LOG[STR_IDX] but 'b' is thrown away,+	    we throw away the node `a'.  */++#define STATE_NODE_CONTAINS(state,node) \+  ((state) != NULL && re_node_set_contains (&(state)->nodes, node))++static reg_errcode_t+internal_function+sift_states_backward (const re_match_context_t *mctx, re_sift_context_t *sctx)+{+  reg_errcode_t err;+  int null_cnt = 0;+  int str_idx = sctx->last_str_idx;+  re_node_set cur_dest;++#ifdef DEBUG+  assert (mctx->state_log != NULL && mctx->state_log[str_idx] != NULL);+#endif++  /* Build sifted state_log[str_idx].  It has the nodes which can epsilon+     transit to the last_node and the last_node itself.  */+  err = re_node_set_init_1 (&cur_dest, sctx->last_node);+  if (BE (err != REG_NOERROR, 0))+    return err;+  err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest);+  if (BE (err != REG_NOERROR, 0))+    goto free_return;++  /* Then check each states in the state_log.  */+  while (str_idx > 0)+    {+      /* Update counters.  */+      null_cnt = (sctx->sifted_states[str_idx] == NULL) ? null_cnt + 1 : 0;+      if (null_cnt > mctx->max_mb_elem_len)+	{+	  memset (sctx->sifted_states, '\0',+		  sizeof (re_dfastate_t *) * str_idx);+	  re_node_set_free (&cur_dest);+	  return REG_NOERROR;+	}+      re_node_set_empty (&cur_dest);+      --str_idx;++      if (mctx->state_log[str_idx])+	{+	  err = build_sifted_states (mctx, sctx, str_idx, &cur_dest);+          if (BE (err != REG_NOERROR, 0))+	    goto free_return;+	}++      /* Add all the nodes which satisfy the following conditions:+	 - It can epsilon transit to a node in CUR_DEST.+	 - It is in CUR_SRC.+	 And update state_log.  */+      err = update_cur_sifted_state (mctx, sctx, str_idx, &cur_dest);+      if (BE (err != REG_NOERROR, 0))+	goto free_return;+    }+  err = REG_NOERROR;+ free_return:+  re_node_set_free (&cur_dest);+  return err;+}++static reg_errcode_t+internal_function+build_sifted_states (const re_match_context_t *mctx, re_sift_context_t *sctx,+		     int str_idx, re_node_set *cur_dest)+{+  const re_dfa_t *const dfa = mctx->dfa;+  const re_node_set *cur_src = &mctx->state_log[str_idx]->non_eps_nodes;+  int i;++  /* Then build the next sifted state.+     We build the next sifted state on `cur_dest', and update+     `sifted_states[str_idx]' with `cur_dest'.+     Note:+     `cur_dest' is the sifted state from `state_log[str_idx + 1]'.+     `cur_src' points the node_set of the old `state_log[str_idx]'+     (with the epsilon nodes pre-filtered out).  */+  for (i = 0; i < cur_src->nelem; i++)+    {+      int prev_node = cur_src->elems[i];+      int naccepted = 0;+      int ret;++#ifdef DEBUG+      re_token_type_t type = dfa->nodes[prev_node].type;+      assert (!IS_EPSILON_NODE (type));+#endif+#ifdef RE_ENABLE_I18N+      /* If the node may accept `multi byte'.  */+      if (dfa->nodes[prev_node].accept_mb)+	naccepted = sift_states_iter_mb (mctx, sctx, prev_node,+					 str_idx, sctx->last_str_idx);+#endif /* RE_ENABLE_I18N */++      /* We don't check backreferences here.+	 See update_cur_sifted_state().  */+      if (!naccepted+	  && check_node_accept (mctx, dfa->nodes + prev_node, str_idx)+	  && STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + 1],+				  dfa->nexts[prev_node]))+	naccepted = 1;++      if (naccepted == 0)+	continue;++      if (sctx->limits.nelem)+	{+	  int to_idx = str_idx + naccepted;+	  if (check_dst_limits (mctx, &sctx->limits,+				dfa->nexts[prev_node], to_idx,+				prev_node, str_idx))+	    continue;+	}+      ret = re_node_set_insert (cur_dest, prev_node);+      if (BE (ret == -1, 0))+	return REG_ESPACE;+    }++  return REG_NOERROR;+}++/* Helper functions.  */++static reg_errcode_t+internal_function+clean_state_log_if_needed (re_match_context_t *mctx, int next_state_log_idx)+{+  int top = mctx->state_log_top;++  if (next_state_log_idx >= mctx->input.bufs_len+      || (next_state_log_idx >= mctx->input.valid_len+	  && mctx->input.valid_len < mctx->input.len))+    {+      reg_errcode_t err;+      err = extend_buffers (mctx);+      if (BE (err != REG_NOERROR, 0))+	return err;+    }++  if (top < next_state_log_idx)+    {+      memset (mctx->state_log + top + 1, '\0',+	      sizeof (re_dfastate_t *) * (next_state_log_idx - top));+      mctx->state_log_top = next_state_log_idx;+    }+  return REG_NOERROR;+}++static reg_errcode_t+internal_function+merge_state_array (const re_dfa_t *dfa, re_dfastate_t **dst,+		   re_dfastate_t **src, int num)+{+  int st_idx;+  reg_errcode_t err;+  for (st_idx = 0; st_idx < num; ++st_idx)+    {+      if (dst[st_idx] == NULL)+	dst[st_idx] = src[st_idx];+      else if (src[st_idx] != NULL)+	{+	  re_node_set merged_set;+	  err = re_node_set_init_union (&merged_set, &dst[st_idx]->nodes,+					&src[st_idx]->nodes);+	  if (BE (err != REG_NOERROR, 0))+	    return err;+	  dst[st_idx] = re_acquire_state (&err, dfa, &merged_set);+	  re_node_set_free (&merged_set);+	  if (BE (err != REG_NOERROR, 0))+	    return err;+	}+    }+  return REG_NOERROR;+}++static reg_errcode_t+internal_function+update_cur_sifted_state (const re_match_context_t *mctx,+			 re_sift_context_t *sctx, int str_idx,+			 re_node_set *dest_nodes)+{+  const re_dfa_t *const dfa = mctx->dfa;+  reg_errcode_t err = REG_NOERROR;+  const re_node_set *candidates;+  candidates = ((mctx->state_log[str_idx] == NULL) ? NULL+		: &mctx->state_log[str_idx]->nodes);++  if (dest_nodes->nelem == 0)+    sctx->sifted_states[str_idx] = NULL;+  else+    {+      if (candidates)+	{+	  /* At first, add the nodes which can epsilon transit to a node in+	     DEST_NODE.  */+	  err = add_epsilon_src_nodes (dfa, dest_nodes, candidates);+	  if (BE (err != REG_NOERROR, 0))+	    return err;++	  /* Then, check the limitations in the current sift_context.  */+	  if (sctx->limits.nelem)+	    {+	      err = check_subexp_limits (dfa, dest_nodes, candidates, &sctx->limits,+					 mctx->bkref_ents, str_idx);+	      if (BE (err != REG_NOERROR, 0))+		return err;+	    }+	}++      sctx->sifted_states[str_idx] = re_acquire_state (&err, dfa, dest_nodes);+      if (BE (err != REG_NOERROR, 0))+	return err;+    }++  if (candidates && mctx->state_log[str_idx]->has_backref)+    {+      err = sift_states_bkref (mctx, sctx, str_idx, candidates);+      if (BE (err != REG_NOERROR, 0))+	return err;+    }+  return REG_NOERROR;+}++static reg_errcode_t+internal_function+add_epsilon_src_nodes (const re_dfa_t *dfa, re_node_set *dest_nodes,+		       const re_node_set *candidates)+{+  reg_errcode_t err = REG_NOERROR;+  int i;++  re_dfastate_t *state = re_acquire_state (&err, dfa, dest_nodes);+  if (BE (err != REG_NOERROR, 0))+    return err;++  if (!state->inveclosure.alloc)+    {+      err = re_node_set_alloc (&state->inveclosure, dest_nodes->nelem);+      if (BE (err != REG_NOERROR, 0))+        return REG_ESPACE;+      for (i = 0; i < dest_nodes->nelem; i++)+        re_node_set_merge (&state->inveclosure,+			   dfa->inveclosures + dest_nodes->elems[i]);+    }+  return re_node_set_add_intersect (dest_nodes, candidates,+				    &state->inveclosure);+}++static reg_errcode_t+internal_function+sub_epsilon_src_nodes (const re_dfa_t *dfa, int node, re_node_set *dest_nodes,+		       const re_node_set *candidates)+{+    int ecl_idx;+    reg_errcode_t err;+    re_node_set *inv_eclosure = dfa->inveclosures + node;+    re_node_set except_nodes;+    re_node_set_init_empty (&except_nodes);+    for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)+      {+	int cur_node = inv_eclosure->elems[ecl_idx];+	if (cur_node == node)+	  continue;+	if (IS_EPSILON_NODE (dfa->nodes[cur_node].type))+	  {+	    int edst1 = dfa->edests[cur_node].elems[0];+	    int edst2 = ((dfa->edests[cur_node].nelem > 1)+			 ? dfa->edests[cur_node].elems[1] : -1);+	    if ((!re_node_set_contains (inv_eclosure, edst1)+		 && re_node_set_contains (dest_nodes, edst1))+		|| (edst2 > 0+		    && !re_node_set_contains (inv_eclosure, edst2)+		    && re_node_set_contains (dest_nodes, edst2)))+	      {+		err = re_node_set_add_intersect (&except_nodes, candidates,+						 dfa->inveclosures + cur_node);+		if (BE (err != REG_NOERROR, 0))+		  {+		    re_node_set_free (&except_nodes);+		    return err;+		  }+	      }+	  }+      }+    for (ecl_idx = 0; ecl_idx < inv_eclosure->nelem; ++ecl_idx)+      {+	int cur_node = inv_eclosure->elems[ecl_idx];+	if (!re_node_set_contains (&except_nodes, cur_node))+	  {+	    int idx = re_node_set_contains (dest_nodes, cur_node) - 1;+	    re_node_set_remove_at (dest_nodes, idx);+	  }+      }+    re_node_set_free (&except_nodes);+    return REG_NOERROR;+}++static int+internal_function+check_dst_limits (const re_match_context_t *mctx, re_node_set *limits,+		  int dst_node, int dst_idx, int src_node, int src_idx)+{+  const re_dfa_t *const dfa = mctx->dfa;+  int lim_idx, src_pos, dst_pos;++  int dst_bkref_idx = search_cur_bkref_entry (mctx, dst_idx);+  int src_bkref_idx = search_cur_bkref_entry (mctx, src_idx);+  for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)+    {+      int subexp_idx;+      struct re_backref_cache_entry *ent;+      ent = mctx->bkref_ents + limits->elems[lim_idx];+      subexp_idx = dfa->nodes[ent->node].opr.idx;++      dst_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx],+					   subexp_idx, dst_node, dst_idx,+					   dst_bkref_idx);+      src_pos = check_dst_limits_calc_pos (mctx, limits->elems[lim_idx],+					   subexp_idx, src_node, src_idx,+					   src_bkref_idx);++      /* In case of:+	 <src> <dst> ( <subexp> )+	 ( <subexp> ) <src> <dst>+	 ( <subexp1> <src> <subexp2> <dst> <subexp3> )  */+      if (src_pos == dst_pos)+	continue; /* This is unrelated limitation.  */+      else+	return 1;+    }+  return 0;+}++static int+internal_function+check_dst_limits_calc_pos_1 (const re_match_context_t *mctx, int boundaries,+			     int subexp_idx, int from_node, int bkref_idx)+{+  const re_dfa_t *const dfa = mctx->dfa;+  const re_node_set *eclosures = dfa->eclosures + from_node;+  int node_idx;++  /* Else, we are on the boundary: examine the nodes on the epsilon+     closure.  */+  for (node_idx = 0; node_idx < eclosures->nelem; ++node_idx)+    {+      int node = eclosures->elems[node_idx];+      switch (dfa->nodes[node].type)+	{+	case OP_BACK_REF:+	  if (bkref_idx != -1)+	    {+	      struct re_backref_cache_entry *ent = mctx->bkref_ents + bkref_idx;+	      do+	        {+		  int dst, cpos;++		  if (ent->node != node)+		    continue;++		  if (subexp_idx < BITSET_WORD_BITS+		      && !(ent->eps_reachable_subexps_map+			   & ((bitset_word_t) 1 << subexp_idx)))+		    continue;++		  /* Recurse trying to reach the OP_OPEN_SUBEXP and+		     OP_CLOSE_SUBEXP cases below.  But, if the+		     destination node is the same node as the source+		     node, don't recurse because it would cause an+		     infinite loop: a regex that exhibits this behavior+		     is ()\1*\1*  */+		  dst = dfa->edests[node].elems[0];+		  if (dst == from_node)+		    {+		      if (boundaries & 1)+		        return -1;+		      else /* if (boundaries & 2) */+		        return 0;+		    }++		  cpos =+		    check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx,+						 dst, bkref_idx);+		  if (cpos == -1 /* && (boundaries & 1) */)+		    return -1;+		  if (cpos == 0 && (boundaries & 2))+		    return 0;++		  if (subexp_idx < BITSET_WORD_BITS)+		    ent->eps_reachable_subexps_map+		      &= ~((bitset_word_t) 1 << subexp_idx);+	        }+	      while (ent++->more);+	    }+	  break;++	case OP_OPEN_SUBEXP:+	  if ((boundaries & 1) && subexp_idx == dfa->nodes[node].opr.idx)+	    return -1;+	  break;++	case OP_CLOSE_SUBEXP:+	  if ((boundaries & 2) && subexp_idx == dfa->nodes[node].opr.idx)+	    return 0;+	  break;++	default:+	    break;+	}+    }++  return (boundaries & 2) ? 1 : 0;+}++static int+internal_function+check_dst_limits_calc_pos (const re_match_context_t *mctx, int limit,+			   int subexp_idx, int from_node, int str_idx,+			   int bkref_idx)+{+  struct re_backref_cache_entry *lim = mctx->bkref_ents + limit;+  int boundaries;++  /* If we are outside the range of the subexpression, return -1 or 1.  */+  if (str_idx < lim->subexp_from)+    return -1;++  if (lim->subexp_to < str_idx)+    return 1;++  /* If we are within the subexpression, return 0.  */+  boundaries = (str_idx == lim->subexp_from);+  boundaries |= (str_idx == lim->subexp_to) << 1;+  if (boundaries == 0)+    return 0;++  /* Else, examine epsilon closure.  */+  return check_dst_limits_calc_pos_1 (mctx, boundaries, subexp_idx,+				      from_node, bkref_idx);+}++/* Check the limitations of sub expressions LIMITS, and remove the nodes+   which are against limitations from DEST_NODES. */++static reg_errcode_t+internal_function+check_subexp_limits (const re_dfa_t *dfa, re_node_set *dest_nodes,+		     const re_node_set *candidates, re_node_set *limits,+		     struct re_backref_cache_entry *bkref_ents, int str_idx)+{+  reg_errcode_t err;+  int node_idx, lim_idx;++  for (lim_idx = 0; lim_idx < limits->nelem; ++lim_idx)+    {+      int subexp_idx;+      struct re_backref_cache_entry *ent;+      ent = bkref_ents + limits->elems[lim_idx];++      if (str_idx <= ent->subexp_from || ent->str_idx < str_idx)+	continue; /* This is unrelated limitation.  */++      subexp_idx = dfa->nodes[ent->node].opr.idx;+      if (ent->subexp_to == str_idx)+	{+	  int ops_node = -1;+	  int cls_node = -1;+	  for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)+	    {+	      int node = dest_nodes->elems[node_idx];+	      re_token_type_t type = dfa->nodes[node].type;+	      if (type == OP_OPEN_SUBEXP+		  && subexp_idx == dfa->nodes[node].opr.idx)+		ops_node = node;+	      else if (type == OP_CLOSE_SUBEXP+		       && subexp_idx == dfa->nodes[node].opr.idx)+		cls_node = node;+	    }++	  /* Check the limitation of the open subexpression.  */+	  /* Note that (ent->subexp_to = str_idx != ent->subexp_from).  */+	  if (ops_node >= 0)+	    {+	      err = sub_epsilon_src_nodes (dfa, ops_node, dest_nodes,+					   candidates);+	      if (BE (err != REG_NOERROR, 0))+		return err;+	    }++	  /* Check the limitation of the close subexpression.  */+	  if (cls_node >= 0)+	    for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)+	      {+		int node = dest_nodes->elems[node_idx];+		if (!re_node_set_contains (dfa->inveclosures + node,+					   cls_node)+		    && !re_node_set_contains (dfa->eclosures + node,+					      cls_node))+		  {+		    /* It is against this limitation.+		       Remove it form the current sifted state.  */+		    err = sub_epsilon_src_nodes (dfa, node, dest_nodes,+						 candidates);+		    if (BE (err != REG_NOERROR, 0))+		      return err;+		    --node_idx;+		  }+	      }+	}+      else /* (ent->subexp_to != str_idx)  */+	{+	  for (node_idx = 0; node_idx < dest_nodes->nelem; ++node_idx)+	    {+	      int node = dest_nodes->elems[node_idx];+	      re_token_type_t type = dfa->nodes[node].type;+	      if (type == OP_CLOSE_SUBEXP || type == OP_OPEN_SUBEXP)+		{+		  if (subexp_idx != dfa->nodes[node].opr.idx)+		    continue;+		  /* It is against this limitation.+		     Remove it form the current sifted state.  */+		  err = sub_epsilon_src_nodes (dfa, node, dest_nodes,+					       candidates);+		  if (BE (err != REG_NOERROR, 0))+		    return err;+		}+	    }+	}+    }+  return REG_NOERROR;+}++static reg_errcode_t+internal_function+sift_states_bkref (const re_match_context_t *mctx, re_sift_context_t *sctx,+		   int str_idx, const re_node_set *candidates)+{+  const re_dfa_t *const dfa = mctx->dfa;+  reg_errcode_t err;+  int node_idx, node;+  re_sift_context_t local_sctx;+  int first_idx = search_cur_bkref_entry (mctx, str_idx);++  if (first_idx == -1)+    return REG_NOERROR;++  local_sctx.sifted_states = NULL; /* Mark that it hasn't been initialized.  */++  for (node_idx = 0; node_idx < candidates->nelem; ++node_idx)+    {+      int enabled_idx;+      re_token_type_t type;+      struct re_backref_cache_entry *entry;+      node = candidates->elems[node_idx];+      type = dfa->nodes[node].type;+      /* Avoid infinite loop for the REs like "()\1+".  */+      if (node == sctx->last_node && str_idx == sctx->last_str_idx)+	continue;+      if (type != OP_BACK_REF)+	continue;++      entry = mctx->bkref_ents + first_idx;+      enabled_idx = first_idx;+      do+	{+	  int subexp_len;+	  int to_idx;+	  int dst_node;+	  int ret;+	  re_dfastate_t *cur_state;++	  if (entry->node != node)+	    continue;+	  subexp_len = entry->subexp_to - entry->subexp_from;+	  to_idx = str_idx + subexp_len;+	  dst_node = (subexp_len ? dfa->nexts[node]+		      : dfa->edests[node].elems[0]);++	  if (to_idx > sctx->last_str_idx+	      || sctx->sifted_states[to_idx] == NULL+	      || !STATE_NODE_CONTAINS (sctx->sifted_states[to_idx], dst_node)+	      || check_dst_limits (mctx, &sctx->limits, node,+				   str_idx, dst_node, to_idx))+	    continue;++	  if (local_sctx.sifted_states == NULL)+	    {+	      local_sctx = *sctx;+	      err = re_node_set_init_copy (&local_sctx.limits, &sctx->limits);+	      if (BE (err != REG_NOERROR, 0))+		goto free_return;+	    }+	  local_sctx.last_node = node;+	  local_sctx.last_str_idx = str_idx;+	  ret = re_node_set_insert (&local_sctx.limits, enabled_idx);+	  if (BE (ret < 0, 0))+	    {+	      err = REG_ESPACE;+	      goto free_return;+	    }+	  cur_state = local_sctx.sifted_states[str_idx];+	  err = sift_states_backward (mctx, &local_sctx);+	  if (BE (err != REG_NOERROR, 0))+	    goto free_return;+	  if (sctx->limited_states != NULL)+	    {+	      err = merge_state_array (dfa, sctx->limited_states,+				       local_sctx.sifted_states,+				       str_idx + 1);+	      if (BE (err != REG_NOERROR, 0))+		goto free_return;+	    }+	  local_sctx.sifted_states[str_idx] = cur_state;+	  re_node_set_remove (&local_sctx.limits, enabled_idx);++	  /* mctx->bkref_ents may have changed, reload the pointer.  */+          entry = mctx->bkref_ents + enabled_idx;+	}+      while (enabled_idx++, entry++->more);+    }+  err = REG_NOERROR;+ free_return:+  if (local_sctx.sifted_states != NULL)+    {+      re_node_set_free (&local_sctx.limits);+    }++  return err;+}+++#ifdef RE_ENABLE_I18N+static int+internal_function+sift_states_iter_mb (const re_match_context_t *mctx, re_sift_context_t *sctx,+		     int node_idx, int str_idx, int max_str_idx)+{+  const re_dfa_t *const dfa = mctx->dfa;+  int naccepted;+  /* Check the node can accept `multi byte'.  */+  naccepted = check_node_accept_bytes (dfa, node_idx, &mctx->input, str_idx);+  if (naccepted > 0 && str_idx + naccepted <= max_str_idx &&+      !STATE_NODE_CONTAINS (sctx->sifted_states[str_idx + naccepted],+			    dfa->nexts[node_idx]))+    /* The node can't accept the `multi byte', or the+       destination was already thrown away, then the node+       could't accept the current input `multi byte'.   */+    naccepted = 0;+  /* Otherwise, it is sure that the node could accept+     `naccepted' bytes input.  */+  return naccepted;+}+#endif /* RE_ENABLE_I18N */+++/* Functions for state transition.  */++/* Return the next state to which the current state STATE will transit by+   accepting the current input byte, and update STATE_LOG if necessary.+   If STATE can accept a multibyte char/collating element/back reference+   update the destination of STATE_LOG.  */++static re_dfastate_t *+internal_function+transit_state (reg_errcode_t *err, re_match_context_t *mctx,+	       re_dfastate_t *state)+{+  re_dfastate_t **trtable;+  unsigned char ch;++#ifdef RE_ENABLE_I18N+  /* If the current state can accept multibyte.  */+  if (BE (state->accept_mb, 0))+    {+      *err = transit_state_mb (mctx, state);+      if (BE (*err != REG_NOERROR, 0))+	return NULL;+    }+#endif /* RE_ENABLE_I18N */++  /* Then decide the next state with the single byte.  */+#if 0+  if (0)+    /* don't use transition table  */+    return transit_state_sb (err, mctx, state);+#endif++  /* Use transition table  */+  ch = re_string_fetch_byte (&mctx->input);+  for (;;)+    {+      trtable = state->trtable;+      if (BE (trtable != NULL, 1))+	return trtable[ch];++      trtable = state->word_trtable;+      if (BE (trtable != NULL, 1))+        {+	  unsigned int context;+	  context+	    = re_string_context_at (&mctx->input,+				    re_string_cur_idx (&mctx->input) - 1,+				    mctx->eflags);+	  if (IS_WORD_CONTEXT (context))+	    return trtable[ch + SBC_MAX];+	  else+	    return trtable[ch];+	}++      if (!build_trtable (mctx->dfa, state))+	{+	  *err = REG_ESPACE;+	  return NULL;+	}++      /* Retry, we now have a transition table.  */+    }+}++/* Update the state_log if we need */+re_dfastate_t *+internal_function+merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx,+		      re_dfastate_t *next_state)+{+  const re_dfa_t *const dfa = mctx->dfa;+  int cur_idx = re_string_cur_idx (&mctx->input);++  if (cur_idx > mctx->state_log_top)+    {+      mctx->state_log[cur_idx] = next_state;+      mctx->state_log_top = cur_idx;+    }+  else if (mctx->state_log[cur_idx] == 0)+    {+      mctx->state_log[cur_idx] = next_state;+    }+  else+    {+      re_dfastate_t *pstate;+      unsigned int context;+      re_node_set next_nodes, *log_nodes, *table_nodes = NULL;+      /* If (state_log[cur_idx] != 0), it implies that cur_idx is+         the destination of a multibyte char/collating element/+         back reference.  Then the next state is the union set of+         these destinations and the results of the transition table.  */+      pstate = mctx->state_log[cur_idx];+      log_nodes = pstate->entrance_nodes;+      if (next_state != NULL)+        {+          table_nodes = next_state->entrance_nodes;+          *err = re_node_set_init_union (&next_nodes, table_nodes,+					     log_nodes);+          if (BE (*err != REG_NOERROR, 0))+	    return NULL;+        }+      else+        next_nodes = *log_nodes;+      /* Note: We already add the nodes of the initial state,+	 then we don't need to add them here.  */++      context = re_string_context_at (&mctx->input,+				      re_string_cur_idx (&mctx->input) - 1,+				      mctx->eflags);+      next_state = mctx->state_log[cur_idx]+        = re_acquire_state_context (err, dfa, &next_nodes, context);+      /* We don't need to check errors here, since the return value of+         this function is next_state and ERR is already set.  */++      if (table_nodes != NULL)+        re_node_set_free (&next_nodes);+    }++  if (BE (dfa->nbackref, 0) && next_state != NULL)+    {+      /* Check OP_OPEN_SUBEXP in the current state in case that we use them+	 later.  We must check them here, since the back references in the+	 next state might use them.  */+      *err = check_subexp_matching_top (mctx, &next_state->nodes,+					cur_idx);+      if (BE (*err != REG_NOERROR, 0))+	return NULL;++      /* If the next state has back references.  */+      if (next_state->has_backref)+	{+	  *err = transit_state_bkref (mctx, &next_state->nodes);+	  if (BE (*err != REG_NOERROR, 0))+	    return NULL;+	  next_state = mctx->state_log[cur_idx];+	}+    }++  return next_state;+}++/* Skip bytes in the input that correspond to part of a+   multi-byte match, then look in the log for a state+   from which to restart matching.  */+re_dfastate_t *+internal_function+find_recover_state (reg_errcode_t *err, re_match_context_t *mctx)+{+  re_dfastate_t *cur_state;+  do+    {+      int max = mctx->state_log_top;+      int cur_str_idx = re_string_cur_idx (&mctx->input);++      do+	{+          if (++cur_str_idx > max)+            return NULL;+          re_string_skip_bytes (&mctx->input, 1);+	}+      while (mctx->state_log[cur_str_idx] == NULL);++      cur_state = merge_state_with_log (err, mctx, NULL);+    }+  while (*err == REG_NOERROR && cur_state == NULL);+  return cur_state;+}++/* Helper functions for transit_state.  */++/* From the node set CUR_NODES, pick up the nodes whose types are+   OP_OPEN_SUBEXP and which have corresponding back references in the regular+   expression. And register them to use them later for evaluating the+   correspoding back references.  */++static reg_errcode_t+internal_function+check_subexp_matching_top (re_match_context_t *mctx, re_node_set *cur_nodes,+			   int str_idx)+{+  const re_dfa_t *const dfa = mctx->dfa;+  int node_idx;+  reg_errcode_t err;++  /* TODO: This isn't efficient.+	   Because there might be more than one nodes whose types are+	   OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all+	   nodes.+	   E.g. RE: (a){2}  */+  for (node_idx = 0; node_idx < cur_nodes->nelem; ++node_idx)+    {+      int node = cur_nodes->elems[node_idx];+      if (dfa->nodes[node].type == OP_OPEN_SUBEXP+	  && dfa->nodes[node].opr.idx < BITSET_WORD_BITS+	  && (dfa->used_bkref_map+	      & ((bitset_word_t) 1 << dfa->nodes[node].opr.idx)))+	{+	  err = match_ctx_add_subtop (mctx, node, str_idx);+	  if (BE (err != REG_NOERROR, 0))+	    return err;+	}+    }+  return REG_NOERROR;+}++#if 0+/* Return the next state to which the current state STATE will transit by+   accepting the current input byte.  */++static re_dfastate_t *+transit_state_sb (reg_errcode_t *err, re_match_context_t *mctx,+		  re_dfastate_t *state)+{+  const re_dfa_t *const dfa = mctx->dfa;+  re_node_set next_nodes;+  re_dfastate_t *next_state;+  int node_cnt, cur_str_idx = re_string_cur_idx (&mctx->input);+  unsigned int context;++  *err = re_node_set_alloc (&next_nodes, state->nodes.nelem + 1);+  if (BE (*err != REG_NOERROR, 0))+    return NULL;+  for (node_cnt = 0; node_cnt < state->nodes.nelem; ++node_cnt)+    {+      int cur_node = state->nodes.elems[node_cnt];+      if (check_node_accept (mctx, dfa->nodes + cur_node, cur_str_idx))+	{+	  *err = re_node_set_merge (&next_nodes,+				    dfa->eclosures + dfa->nexts[cur_node]);+	  if (BE (*err != REG_NOERROR, 0))+	    {+	      re_node_set_free (&next_nodes);+	      return NULL;+	    }+	}+    }+  context = re_string_context_at (&mctx->input, cur_str_idx, mctx->eflags);+  next_state = re_acquire_state_context (err, dfa, &next_nodes, context);+  /* We don't need to check errors here, since the return value of+     this function is next_state and ERR is already set.  */++  re_node_set_free (&next_nodes);+  re_string_skip_bytes (&mctx->input, 1);+  return next_state;+}+#endif++#ifdef RE_ENABLE_I18N+static reg_errcode_t+internal_function+transit_state_mb (re_match_context_t *mctx, re_dfastate_t *pstate)+{+  const re_dfa_t *const dfa = mctx->dfa;+  reg_errcode_t err;+  int i;++  for (i = 0; i < pstate->nodes.nelem; ++i)+    {+      re_node_set dest_nodes, *new_nodes;+      int cur_node_idx = pstate->nodes.elems[i];+      int naccepted, dest_idx;+      unsigned int context;+      re_dfastate_t *dest_state;++      if (!dfa->nodes[cur_node_idx].accept_mb)+        continue;++      if (dfa->nodes[cur_node_idx].constraint)+	{+	  context = re_string_context_at (&mctx->input,+					  re_string_cur_idx (&mctx->input),+					  mctx->eflags);+	  if (NOT_SATISFY_NEXT_CONSTRAINT (dfa->nodes[cur_node_idx].constraint,+					   context))+	    continue;+	}++      /* How many bytes the node can accept?  */+      naccepted = check_node_accept_bytes (dfa, cur_node_idx, &mctx->input,+					   re_string_cur_idx (&mctx->input));+      if (naccepted == 0)+	continue;++      /* The node can accepts `naccepted' bytes.  */+      dest_idx = re_string_cur_idx (&mctx->input) + naccepted;+      mctx->max_mb_elem_len = ((mctx->max_mb_elem_len < naccepted) ? naccepted+			       : mctx->max_mb_elem_len);+      err = clean_state_log_if_needed (mctx, dest_idx);+      if (BE (err != REG_NOERROR, 0))+	return err;+#ifdef DEBUG+      assert (dfa->nexts[cur_node_idx] != -1);+#endif+      new_nodes = dfa->eclosures + dfa->nexts[cur_node_idx];++      dest_state = mctx->state_log[dest_idx];+      if (dest_state == NULL)+	dest_nodes = *new_nodes;+      else+	{+	  err = re_node_set_init_union (&dest_nodes,+					dest_state->entrance_nodes, new_nodes);+	  if (BE (err != REG_NOERROR, 0))+	    return err;+	}+      context = re_string_context_at (&mctx->input, dest_idx - 1,+				      mctx->eflags);+      mctx->state_log[dest_idx]+	= re_acquire_state_context (&err, dfa, &dest_nodes, context);+      if (dest_state != NULL)+	re_node_set_free (&dest_nodes);+      if (BE (mctx->state_log[dest_idx] == NULL && err != REG_NOERROR, 0))+	return err;+    }+  return REG_NOERROR;+}+#endif /* RE_ENABLE_I18N */++static reg_errcode_t+internal_function+transit_state_bkref (re_match_context_t *mctx, const re_node_set *nodes)+{+  const re_dfa_t *const dfa = mctx->dfa;+  reg_errcode_t err;+  int i;+  int cur_str_idx = re_string_cur_idx (&mctx->input);++  for (i = 0; i < nodes->nelem; ++i)+    {+      int dest_str_idx, prev_nelem, bkc_idx;+      int node_idx = nodes->elems[i];+      unsigned int context;+      const re_token_t *node = dfa->nodes + node_idx;+      re_node_set *new_dest_nodes;++      /* Check whether `node' is a backreference or not.  */+      if (node->type != OP_BACK_REF)+	continue;++      if (node->constraint)+	{+	  context = re_string_context_at (&mctx->input, cur_str_idx,+					  mctx->eflags);+	  if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context))+	    continue;+	}++      /* `node' is a backreference.+	 Check the substring which the substring matched.  */+      bkc_idx = mctx->nbkref_ents;+      err = get_subexp (mctx, node_idx, cur_str_idx);+      if (BE (err != REG_NOERROR, 0))+	goto free_return;++      /* And add the epsilon closures (which is `new_dest_nodes') of+	 the backreference to appropriate state_log.  */+#ifdef DEBUG+      assert (dfa->nexts[node_idx] != -1);+#endif+      for (; bkc_idx < mctx->nbkref_ents; ++bkc_idx)+	{+	  int subexp_len;+	  re_dfastate_t *dest_state;+	  struct re_backref_cache_entry *bkref_ent;+	  bkref_ent = mctx->bkref_ents + bkc_idx;+	  if (bkref_ent->node != node_idx || bkref_ent->str_idx != cur_str_idx)+	    continue;+	  subexp_len = bkref_ent->subexp_to - bkref_ent->subexp_from;+	  new_dest_nodes = (subexp_len == 0+			    ? dfa->eclosures + dfa->edests[node_idx].elems[0]+			    : dfa->eclosures + dfa->nexts[node_idx]);+	  dest_str_idx = (cur_str_idx + bkref_ent->subexp_to+			  - bkref_ent->subexp_from);+	  context = re_string_context_at (&mctx->input, dest_str_idx - 1,+					  mctx->eflags);+	  dest_state = mctx->state_log[dest_str_idx];+	  prev_nelem = ((mctx->state_log[cur_str_idx] == NULL) ? 0+			: mctx->state_log[cur_str_idx]->nodes.nelem);+	  /* Add `new_dest_node' to state_log.  */+	  if (dest_state == NULL)+	    {+	      mctx->state_log[dest_str_idx]+		= re_acquire_state_context (&err, dfa, new_dest_nodes,+					    context);+	      if (BE (mctx->state_log[dest_str_idx] == NULL+		      && err != REG_NOERROR, 0))+		goto free_return;+	    }+	  else+	    {+	      re_node_set dest_nodes;+	      err = re_node_set_init_union (&dest_nodes,+					    dest_state->entrance_nodes,+					    new_dest_nodes);+	      if (BE (err != REG_NOERROR, 0))+		{+		  re_node_set_free (&dest_nodes);+		  goto free_return;+		}+	      mctx->state_log[dest_str_idx]+		= re_acquire_state_context (&err, dfa, &dest_nodes, context);+	      re_node_set_free (&dest_nodes);+	      if (BE (mctx->state_log[dest_str_idx] == NULL+		      && err != REG_NOERROR, 0))+		goto free_return;+	    }+	  /* We need to check recursively if the backreference can epsilon+	     transit.  */+	  if (subexp_len == 0+	      && mctx->state_log[cur_str_idx]->nodes.nelem > prev_nelem)+	    {+	      err = check_subexp_matching_top (mctx, new_dest_nodes,+					       cur_str_idx);+	      if (BE (err != REG_NOERROR, 0))+		goto free_return;+	      err = transit_state_bkref (mctx, new_dest_nodes);+	      if (BE (err != REG_NOERROR, 0))+		goto free_return;+	    }+	}+    }+  err = REG_NOERROR;+ free_return:+  return err;+}++/* Enumerate all the candidates which the backreference BKREF_NODE can match+   at BKREF_STR_IDX, and register them by match_ctx_add_entry().+   Note that we might collect inappropriate candidates here.+   However, the cost of checking them strictly here is too high, then we+   delay these checking for prune_impossible_nodes().  */++static reg_errcode_t+internal_function+get_subexp (re_match_context_t *mctx, int bkref_node, int bkref_str_idx)+{+  const re_dfa_t *const dfa = mctx->dfa;+  int subexp_num, sub_top_idx;+  const char *buf = (const char *) re_string_get_buffer (&mctx->input);+  /* Return if we have already checked BKREF_NODE at BKREF_STR_IDX.  */+  int cache_idx = search_cur_bkref_entry (mctx, bkref_str_idx);+  if (cache_idx != -1)+    {+      const struct re_backref_cache_entry *entry+	= mctx->bkref_ents + cache_idx;+      do+        if (entry->node == bkref_node)+	  return REG_NOERROR; /* We already checked it.  */+      while (entry++->more);+    }++  subexp_num = dfa->nodes[bkref_node].opr.idx;++  /* For each sub expression  */+  for (sub_top_idx = 0; sub_top_idx < mctx->nsub_tops; ++sub_top_idx)+    {+      reg_errcode_t err;+      re_sub_match_top_t *sub_top = mctx->sub_tops[sub_top_idx];+      re_sub_match_last_t *sub_last;+      int sub_last_idx, sl_str, bkref_str_off;++      if (dfa->nodes[sub_top->node].opr.idx != subexp_num)+	continue; /* It isn't related.  */++      sl_str = sub_top->str_idx;+      bkref_str_off = bkref_str_idx;+      /* At first, check the last node of sub expressions we already+	 evaluated.  */+      for (sub_last_idx = 0; sub_last_idx < sub_top->nlasts; ++sub_last_idx)+	{+	  int sl_str_diff;+	  sub_last = sub_top->lasts[sub_last_idx];+	  sl_str_diff = sub_last->str_idx - sl_str;+	  /* The matched string by the sub expression match with the substring+	     at the back reference?  */+	  if (sl_str_diff > 0)+	    {+	      if (BE (bkref_str_off + sl_str_diff > mctx->input.valid_len, 0))+		{+		  /* Not enough chars for a successful match.  */+		  if (bkref_str_off + sl_str_diff > mctx->input.len)+		    break;++		  err = clean_state_log_if_needed (mctx,+						   bkref_str_off+						   + sl_str_diff);+		  if (BE (err != REG_NOERROR, 0))+		    return err;+		  buf = (const char *) re_string_get_buffer (&mctx->input);+		}+	      if (memcmp (buf + bkref_str_off, buf + sl_str, sl_str_diff) != 0)+		/* We don't need to search this sub expression any more.  */+		break;+	    }+	  bkref_str_off += sl_str_diff;+	  sl_str += sl_str_diff;+	  err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node,+				bkref_str_idx);++	  /* Reload buf, since the preceding call might have reallocated+	     the buffer.  */+	  buf = (const char *) re_string_get_buffer (&mctx->input);++	  if (err == REG_NOMATCH)+	    continue;+	  if (BE (err != REG_NOERROR, 0))+	    return err;+	}++      if (sub_last_idx < sub_top->nlasts)+	continue;+      if (sub_last_idx > 0)+	++sl_str;+      /* Then, search for the other last nodes of the sub expression.  */+      for (; sl_str <= bkref_str_idx; ++sl_str)+	{+	  int cls_node, sl_str_off;+	  const re_node_set *nodes;+	  sl_str_off = sl_str - sub_top->str_idx;+	  /* The matched string by the sub expression match with the substring+	     at the back reference?  */+	  if (sl_str_off > 0)+	    {+	      if (BE (bkref_str_off >= mctx->input.valid_len, 0))+		{+		  /* If we are at the end of the input, we cannot match.  */+		  if (bkref_str_off >= mctx->input.len)+		    break;++		  err = extend_buffers (mctx);+		  if (BE (err != REG_NOERROR, 0))+		    return err;++		  buf = (const char *) re_string_get_buffer (&mctx->input);+		}+	      if (buf [bkref_str_off++] != buf[sl_str - 1])+		break; /* We don't need to search this sub expression+			  any more.  */+	    }+	  if (mctx->state_log[sl_str] == NULL)+	    continue;+	  /* Does this state have a ')' of the sub expression?  */+	  nodes = &mctx->state_log[sl_str]->nodes;+	  cls_node = find_subexp_node (dfa, nodes, subexp_num,+				       OP_CLOSE_SUBEXP);+	  if (cls_node == -1)+	    continue; /* No.  */+	  if (sub_top->path == NULL)+	    {+	      sub_top->path = calloc (sizeof (state_array_t),+				      sl_str - sub_top->str_idx + 1);+	      if (sub_top->path == NULL)+		return REG_ESPACE;+	    }+	  /* Can the OP_OPEN_SUBEXP node arrive the OP_CLOSE_SUBEXP node+	     in the current context?  */+	  err = check_arrival (mctx, sub_top->path, sub_top->node,+			       sub_top->str_idx, cls_node, sl_str,+			       OP_CLOSE_SUBEXP);+	  if (err == REG_NOMATCH)+	      continue;+	  if (BE (err != REG_NOERROR, 0))+	      return err;+	  sub_last = match_ctx_add_sublast (sub_top, cls_node, sl_str);+	  if (BE (sub_last == NULL, 0))+	    return REG_ESPACE;+	  err = get_subexp_sub (mctx, sub_top, sub_last, bkref_node,+				bkref_str_idx);+	  if (err == REG_NOMATCH)+	    continue;+	}+    }+  return REG_NOERROR;+}++/* Helper functions for get_subexp().  */++/* Check SUB_LAST can arrive to the back reference BKREF_NODE at BKREF_STR.+   If it can arrive, register the sub expression expressed with SUB_TOP+   and SUB_LAST.  */++static reg_errcode_t+internal_function+get_subexp_sub (re_match_context_t *mctx, const re_sub_match_top_t *sub_top,+		re_sub_match_last_t *sub_last, int bkref_node, int bkref_str)+{+  reg_errcode_t err;+  int to_idx;+  /* Can the subexpression arrive the back reference?  */+  err = check_arrival (mctx, &sub_last->path, sub_last->node,+		       sub_last->str_idx, bkref_node, bkref_str,+		       OP_OPEN_SUBEXP);+  if (err != REG_NOERROR)+    return err;+  err = match_ctx_add_entry (mctx, bkref_node, bkref_str, sub_top->str_idx,+			     sub_last->str_idx);+  if (BE (err != REG_NOERROR, 0))+    return err;+  to_idx = bkref_str + sub_last->str_idx - sub_top->str_idx;+  return clean_state_log_if_needed (mctx, to_idx);+}++/* Find the first node which is '(' or ')' and whose index is SUBEXP_IDX.+   Search '(' if FL_OPEN, or search ')' otherwise.+   TODO: This function isn't efficient...+	 Because there might be more than one nodes whose types are+	 OP_OPEN_SUBEXP and whose index is SUBEXP_IDX, we must check all+	 nodes.+	 E.g. RE: (a){2}  */++static int+internal_function+find_subexp_node (const re_dfa_t *dfa, const re_node_set *nodes,+		  int subexp_idx, int type)+{+  int cls_idx;+  for (cls_idx = 0; cls_idx < nodes->nelem; ++cls_idx)+    {+      int cls_node = nodes->elems[cls_idx];+      const re_token_t *node = dfa->nodes + cls_node;+      if (node->type == type+	  && node->opr.idx == subexp_idx)+	return cls_node;+    }+  return -1;+}++/* Check whether the node TOP_NODE at TOP_STR can arrive to the node+   LAST_NODE at LAST_STR.  We record the path onto PATH since it will be+   heavily reused.+   Return REG_NOERROR if it can arrive, or REG_NOMATCH otherwise.  */++static reg_errcode_t+internal_function+check_arrival (re_match_context_t *mctx, state_array_t *path, int top_node,+	       int top_str, int last_node, int last_str, int type)+{+  const re_dfa_t *const dfa = mctx->dfa;+  reg_errcode_t err = REG_NOERROR;+  int subexp_num, backup_cur_idx, str_idx, null_cnt;+  re_dfastate_t *cur_state = NULL;+  re_node_set *cur_nodes, next_nodes;+  re_dfastate_t **backup_state_log;+  unsigned int context;++  subexp_num = dfa->nodes[top_node].opr.idx;+  /* Extend the buffer if we need.  */+  if (BE (path->alloc < last_str + mctx->max_mb_elem_len + 1, 0))+    {+      re_dfastate_t **new_array;+      int old_alloc = path->alloc;+      path->alloc += last_str + mctx->max_mb_elem_len + 1;+      new_array = re_realloc (path->array, re_dfastate_t *, path->alloc);+      if (BE (new_array == NULL, 0))+	{+	  path->alloc = old_alloc;+	  return REG_ESPACE;+	}+      path->array = new_array;+      memset (new_array + old_alloc, '\0',+	      sizeof (re_dfastate_t *) * (path->alloc - old_alloc));+    }++  str_idx = path->next_idx ?: top_str;++  /* Temporary modify MCTX.  */+  backup_state_log = mctx->state_log;+  backup_cur_idx = mctx->input.cur_idx;+  mctx->state_log = path->array;+  mctx->input.cur_idx = str_idx;++  /* Setup initial node set.  */+  context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags);+  if (str_idx == top_str)+    {+      err = re_node_set_init_1 (&next_nodes, top_node);+      if (BE (err != REG_NOERROR, 0))+	return err;+      err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type);+      if (BE (err != REG_NOERROR, 0))+	{+	  re_node_set_free (&next_nodes);+	  return err;+	}+    }+  else+    {+      cur_state = mctx->state_log[str_idx];+      if (cur_state && cur_state->has_backref)+	{+	  err = re_node_set_init_copy (&next_nodes, &cur_state->nodes);+	  if (BE (err != REG_NOERROR, 0))+	    return err;+	}+      else+	re_node_set_init_empty (&next_nodes);+    }+  if (str_idx == top_str || (cur_state && cur_state->has_backref))+    {+      if (next_nodes.nelem)+	{+	  err = expand_bkref_cache (mctx, &next_nodes, str_idx,+				    subexp_num, type);+	  if (BE (err != REG_NOERROR, 0))+	    {+	      re_node_set_free (&next_nodes);+	      return err;+	    }+	}+      cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context);+      if (BE (cur_state == NULL && err != REG_NOERROR, 0))+	{+	  re_node_set_free (&next_nodes);+	  return err;+	}+      mctx->state_log[str_idx] = cur_state;+    }++  for (null_cnt = 0; str_idx < last_str && null_cnt <= mctx->max_mb_elem_len;)+    {+      re_node_set_empty (&next_nodes);+      if (mctx->state_log[str_idx + 1])+	{+	  err = re_node_set_merge (&next_nodes,+				   &mctx->state_log[str_idx + 1]->nodes);+	  if (BE (err != REG_NOERROR, 0))+	    {+	      re_node_set_free (&next_nodes);+	      return err;+	    }+	}+      if (cur_state)+	{+	  err = check_arrival_add_next_nodes (mctx, str_idx,+					      &cur_state->non_eps_nodes,+					      &next_nodes);+	  if (BE (err != REG_NOERROR, 0))+	    {+	      re_node_set_free (&next_nodes);+	      return err;+	    }+	}+      ++str_idx;+      if (next_nodes.nelem)+	{+	  err = check_arrival_expand_ecl (dfa, &next_nodes, subexp_num, type);+	  if (BE (err != REG_NOERROR, 0))+	    {+	      re_node_set_free (&next_nodes);+	      return err;+	    }+	  err = expand_bkref_cache (mctx, &next_nodes, str_idx,+				    subexp_num, type);+	  if (BE (err != REG_NOERROR, 0))+	    {+	      re_node_set_free (&next_nodes);+	      return err;+	    }+	}+      context = re_string_context_at (&mctx->input, str_idx - 1, mctx->eflags);+      cur_state = re_acquire_state_context (&err, dfa, &next_nodes, context);+      if (BE (cur_state == NULL && err != REG_NOERROR, 0))+	{+	  re_node_set_free (&next_nodes);+	  return err;+	}+      mctx->state_log[str_idx] = cur_state;+      null_cnt = cur_state == NULL ? null_cnt + 1 : 0;+    }+  re_node_set_free (&next_nodes);+  cur_nodes = (mctx->state_log[last_str] == NULL ? NULL+	       : &mctx->state_log[last_str]->nodes);+  path->next_idx = str_idx;++  /* Fix MCTX.  */+  mctx->state_log = backup_state_log;+  mctx->input.cur_idx = backup_cur_idx;++  /* Then check the current node set has the node LAST_NODE.  */+  if (cur_nodes != NULL && re_node_set_contains (cur_nodes, last_node))+    return REG_NOERROR;++  return REG_NOMATCH;+}++/* Helper functions for check_arrival.  */++/* Calculate the destination nodes of CUR_NODES at STR_IDX, and append them+   to NEXT_NODES.+   TODO: This function is similar to the functions transit_state*(),+	 however this function has many additional works.+	 Can't we unify them?  */++static reg_errcode_t+internal_function+check_arrival_add_next_nodes (re_match_context_t *mctx, int str_idx,+			      re_node_set *cur_nodes, re_node_set *next_nodes)+{+  const re_dfa_t *const dfa = mctx->dfa;+  int result;+  int cur_idx;+  reg_errcode_t err = REG_NOERROR;+  re_node_set union_set;+  re_node_set_init_empty (&union_set);+  for (cur_idx = 0; cur_idx < cur_nodes->nelem; ++cur_idx)+    {+      int naccepted = 0;+      int cur_node = cur_nodes->elems[cur_idx];+#ifdef DEBUG+      re_token_type_t type = dfa->nodes[cur_node].type;+      assert (!IS_EPSILON_NODE (type));+#endif+#ifdef RE_ENABLE_I18N+      /* If the node may accept `multi byte'.  */+      if (dfa->nodes[cur_node].accept_mb)+	{+	  naccepted = check_node_accept_bytes (dfa, cur_node, &mctx->input,+					       str_idx);+	  if (naccepted > 1)+	    {+	      re_dfastate_t *dest_state;+	      int next_node = dfa->nexts[cur_node];+	      int next_idx = str_idx + naccepted;+	      dest_state = mctx->state_log[next_idx];+	      re_node_set_empty (&union_set);+	      if (dest_state)+		{+		  err = re_node_set_merge (&union_set, &dest_state->nodes);+		  if (BE (err != REG_NOERROR, 0))+		    {+		      re_node_set_free (&union_set);+		      return err;+		    }+		}+	      result = re_node_set_insert (&union_set, next_node);+	      if (BE (result < 0, 0))+		{+		  re_node_set_free (&union_set);+		  return REG_ESPACE;+		}+	      mctx->state_log[next_idx] = re_acquire_state (&err, dfa,+							    &union_set);+	      if (BE (mctx->state_log[next_idx] == NULL+		      && err != REG_NOERROR, 0))+		{+		  re_node_set_free (&union_set);+		  return err;+		}+	    }+	}+#endif /* RE_ENABLE_I18N */+      if (naccepted+	  || check_node_accept (mctx, dfa->nodes + cur_node, str_idx))+	{+	  result = re_node_set_insert (next_nodes, dfa->nexts[cur_node]);+	  if (BE (result < 0, 0))+	    {+	      re_node_set_free (&union_set);+	      return REG_ESPACE;+	    }+	}+    }+  re_node_set_free (&union_set);+  return REG_NOERROR;+}++/* For all the nodes in CUR_NODES, add the epsilon closures of them to+   CUR_NODES, however exclude the nodes which are:+    - inside the sub expression whose number is EX_SUBEXP, if FL_OPEN.+    - out of the sub expression whose number is EX_SUBEXP, if !FL_OPEN.+*/++static reg_errcode_t+internal_function+check_arrival_expand_ecl (const re_dfa_t *dfa, re_node_set *cur_nodes,+			  int ex_subexp, int type)+{+  reg_errcode_t err;+  int idx, outside_node;+  re_node_set new_nodes;+#ifdef DEBUG+  assert (cur_nodes->nelem);+#endif+  err = re_node_set_alloc (&new_nodes, cur_nodes->nelem);+  if (BE (err != REG_NOERROR, 0))+    return err;+  /* Create a new node set NEW_NODES with the nodes which are epsilon+     closures of the node in CUR_NODES.  */++  for (idx = 0; idx < cur_nodes->nelem; ++idx)+    {+      int cur_node = cur_nodes->elems[idx];+      const re_node_set *eclosure = dfa->eclosures + cur_node;+      outside_node = find_subexp_node (dfa, eclosure, ex_subexp, type);+      if (outside_node == -1)+	{+	  /* There are no problematic nodes, just merge them.  */+	  err = re_node_set_merge (&new_nodes, eclosure);+	  if (BE (err != REG_NOERROR, 0))+	    {+	      re_node_set_free (&new_nodes);+	      return err;+	    }+	}+      else+	{+	  /* There are problematic nodes, re-calculate incrementally.  */+	  err = check_arrival_expand_ecl_sub (dfa, &new_nodes, cur_node,+					      ex_subexp, type);+	  if (BE (err != REG_NOERROR, 0))+	    {+	      re_node_set_free (&new_nodes);+	      return err;+	    }+	}+    }+  re_node_set_free (cur_nodes);+  *cur_nodes = new_nodes;+  return REG_NOERROR;+}++/* Helper function for check_arrival_expand_ecl.+   Check incrementally the epsilon closure of TARGET, and if it isn't+   problematic append it to DST_NODES.  */++static reg_errcode_t+internal_function+check_arrival_expand_ecl_sub (const re_dfa_t *dfa, re_node_set *dst_nodes,+			      int target, int ex_subexp, int type)+{+  int cur_node;+  for (cur_node = target; !re_node_set_contains (dst_nodes, cur_node);)+    {+      int err;++      if (dfa->nodes[cur_node].type == type+	  && dfa->nodes[cur_node].opr.idx == ex_subexp)+	{+	  if (type == OP_CLOSE_SUBEXP)+	    {+	      err = re_node_set_insert (dst_nodes, cur_node);+	      if (BE (err == -1, 0))+		return REG_ESPACE;+	    }+	  break;+	}+      err = re_node_set_insert (dst_nodes, cur_node);+      if (BE (err == -1, 0))+	return REG_ESPACE;+      if (dfa->edests[cur_node].nelem == 0)+	break;+      if (dfa->edests[cur_node].nelem == 2)+	{+	  err = check_arrival_expand_ecl_sub (dfa, dst_nodes,+					      dfa->edests[cur_node].elems[1],+					      ex_subexp, type);+	  if (BE (err != REG_NOERROR, 0))+	    return err;+	}+      cur_node = dfa->edests[cur_node].elems[0];+    }+  return REG_NOERROR;+}+++/* For all the back references in the current state, calculate the+   destination of the back references by the appropriate entry+   in MCTX->BKREF_ENTS.  */++static reg_errcode_t+internal_function+expand_bkref_cache (re_match_context_t *mctx, re_node_set *cur_nodes,+		    int cur_str, int subexp_num, int type)+{+  const re_dfa_t *const dfa = mctx->dfa;+  reg_errcode_t err;+  int cache_idx_start = search_cur_bkref_entry (mctx, cur_str);+  struct re_backref_cache_entry *ent;++  if (cache_idx_start == -1)+    return REG_NOERROR;++ restart:+  ent = mctx->bkref_ents + cache_idx_start;+  do+    {+      int to_idx, next_node;++      /* Is this entry ENT is appropriate?  */+      if (!re_node_set_contains (cur_nodes, ent->node))+	continue; /* No.  */++      to_idx = cur_str + ent->subexp_to - ent->subexp_from;+      /* Calculate the destination of the back reference, and append it+	 to MCTX->STATE_LOG.  */+      if (to_idx == cur_str)+	{+	  /* The backreference did epsilon transit, we must re-check all the+	     node in the current state.  */+	  re_node_set new_dests;+	  reg_errcode_t err2, err3;+	  next_node = dfa->edests[ent->node].elems[0];+	  if (re_node_set_contains (cur_nodes, next_node))+	    continue;+	  err = re_node_set_init_1 (&new_dests, next_node);+	  err2 = check_arrival_expand_ecl (dfa, &new_dests, subexp_num, type);+	  err3 = re_node_set_merge (cur_nodes, &new_dests);+	  re_node_set_free (&new_dests);+	  if (BE (err != REG_NOERROR || err2 != REG_NOERROR+		  || err3 != REG_NOERROR, 0))+	    {+	      err = (err != REG_NOERROR ? err+		     : (err2 != REG_NOERROR ? err2 : err3));+	      return err;+	    }+	  /* TODO: It is still inefficient...  */+	  goto restart;+	}+      else+	{+	  re_node_set union_set;+	  next_node = dfa->nexts[ent->node];+	  if (mctx->state_log[to_idx])+	    {+	      int ret;+	      if (re_node_set_contains (&mctx->state_log[to_idx]->nodes,+					next_node))+		continue;+	      err = re_node_set_init_copy (&union_set,+					   &mctx->state_log[to_idx]->nodes);+	      ret = re_node_set_insert (&union_set, next_node);+	      if (BE (err != REG_NOERROR || ret < 0, 0))+		{+		  re_node_set_free (&union_set);+		  err = err != REG_NOERROR ? err : REG_ESPACE;+		  return err;+		}+	    }+	  else+	    {+	      err = re_node_set_init_1 (&union_set, next_node);+	      if (BE (err != REG_NOERROR, 0))+		return err;+	    }+	  mctx->state_log[to_idx] = re_acquire_state (&err, dfa, &union_set);+	  re_node_set_free (&union_set);+	  if (BE (mctx->state_log[to_idx] == NULL+		  && err != REG_NOERROR, 0))+	    return err;+	}+    }+  while (ent++->more);+  return REG_NOERROR;+}++/* Build transition table for the state.+   Return 1 if succeeded, otherwise return NULL.  */++static int+internal_function+build_trtable (const re_dfa_t *dfa, re_dfastate_t *state)+{+  reg_errcode_t err;+  int i, j, ch, need_word_trtable = 0;+  bitset_word_t elem, mask;+  bool dests_node_malloced = false;+  bool dest_states_malloced = false;+  int ndests; /* Number of the destination states from `state'.  */+  re_dfastate_t **trtable;+  re_dfastate_t **dest_states = NULL, **dest_states_word, **dest_states_nl;+  re_node_set follows, *dests_node;+  bitset_t *dests_ch;+  bitset_t acceptable;++  struct dests_alloc+  {+    re_node_set dests_node[SBC_MAX];+    bitset_t dests_ch[SBC_MAX];+  } *dests_alloc;++  /* We build DFA states which corresponds to the destination nodes+     from `state'.  `dests_node[i]' represents the nodes which i-th+     destination state contains, and `dests_ch[i]' represents the+     characters which i-th destination state accepts.  */+  if (__libc_use_alloca (sizeof (struct dests_alloc)))+    dests_alloc = (struct dests_alloc *) alloca (sizeof (struct dests_alloc));+  else+    {+      dests_alloc = re_malloc (struct dests_alloc, 1);+      if (BE (dests_alloc == NULL, 0))+	return 0;+      dests_node_malloced = true;+    }+  dests_node = dests_alloc->dests_node;+  dests_ch = dests_alloc->dests_ch;++  /* Initialize transiton table.  */+  state->word_trtable = state->trtable = NULL;++  /* At first, group all nodes belonging to `state' into several+     destinations.  */+  ndests = group_nodes_into_DFAstates (dfa, state, dests_node, dests_ch);+  if (BE (ndests <= 0, 0))+    {+      if (dests_node_malloced)+	free (dests_alloc);+      /* Return 0 in case of an error, 1 otherwise.  */+      if (ndests == 0)+	{+	  state->trtable = (re_dfastate_t **)+	    calloc (sizeof (re_dfastate_t *), SBC_MAX);+	  return 1;+	}+      return 0;+    }++  err = re_node_set_alloc (&follows, ndests + 1);+  if (BE (err != REG_NOERROR, 0))+    goto out_free;++  if (__libc_use_alloca ((sizeof (re_node_set) + sizeof (bitset_t)) * SBC_MAX+			 + ndests * 3 * sizeof (re_dfastate_t *)))+    dest_states = (re_dfastate_t **)+      alloca (ndests * 3 * sizeof (re_dfastate_t *));+  else+    {+      dest_states = (re_dfastate_t **)+	malloc (ndests * 3 * sizeof (re_dfastate_t *));+      if (BE (dest_states == NULL, 0))+	{+out_free:+	  if (dest_states_malloced)+	    free (dest_states);+	  re_node_set_free (&follows);+	  for (i = 0; i < ndests; ++i)+	    re_node_set_free (dests_node + i);+	  if (dests_node_malloced)+	    free (dests_alloc);+	  return 0;+	}+      dest_states_malloced = true;+    }+  dest_states_word = dest_states + ndests;+  dest_states_nl = dest_states_word + ndests;+  bitset_empty (acceptable);++  /* Then build the states for all destinations.  */+  for (i = 0; i < ndests; ++i)+    {+      int next_node;+      re_node_set_empty (&follows);+      /* Merge the follows of this destination states.  */+      for (j = 0; j < dests_node[i].nelem; ++j)+	{+	  next_node = dfa->nexts[dests_node[i].elems[j]];+	  if (next_node != -1)+	    {+	      err = re_node_set_merge (&follows, dfa->eclosures + next_node);+	      if (BE (err != REG_NOERROR, 0))+		goto out_free;+	    }+	}+      dest_states[i] = re_acquire_state_context (&err, dfa, &follows, 0);+      if (BE (dest_states[i] == NULL && err != REG_NOERROR, 0))+	goto out_free;+      /* If the new state has context constraint,+	 build appropriate states for these contexts.  */+      if (dest_states[i]->has_constraint)+	{+	  dest_states_word[i] = re_acquire_state_context (&err, dfa, &follows,+							  CONTEXT_WORD);+	  if (BE (dest_states_word[i] == NULL && err != REG_NOERROR, 0))+	    goto out_free;++	  if (dest_states[i] != dest_states_word[i] && dfa->mb_cur_max > 1)+	    need_word_trtable = 1;++	  dest_states_nl[i] = re_acquire_state_context (&err, dfa, &follows,+							CONTEXT_NEWLINE);+	  if (BE (dest_states_nl[i] == NULL && err != REG_NOERROR, 0))+	    goto out_free;+ 	}+      else+	{+	  dest_states_word[i] = dest_states[i];+	  dest_states_nl[i] = dest_states[i];+	}+      bitset_merge (acceptable, dests_ch[i]);+    }++  if (!BE (need_word_trtable, 0))+    {+      /* We don't care about whether the following character is a word+	 character, or we are in a single-byte character set so we can+	 discern by looking at the character code: allocate a+	 256-entry transition table.  */+      trtable = state->trtable =+	(re_dfastate_t **) calloc (sizeof (re_dfastate_t *), SBC_MAX);+      if (BE (trtable == NULL, 0))+	goto out_free;++      /* For all characters ch...:  */+      for (i = 0; i < BITSET_WORDS; ++i)+	for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1;+	     elem;+	     mask <<= 1, elem >>= 1, ++ch)+	  if (BE (elem & 1, 0))+	    {+	      /* There must be exactly one destination which accepts+		 character ch.  See group_nodes_into_DFAstates.  */+	      for (j = 0; (dests_ch[j][i] & mask) == 0; ++j)+		;++	      /* j-th destination accepts the word character ch.  */+	      if (dfa->word_char[i] & mask)+		trtable[ch] = dest_states_word[j];+	      else+		trtable[ch] = dest_states[j];+	    }+    }+  else+    {+      /* We care about whether the following character is a word+	 character, and we are in a multi-byte character set: discern+	 by looking at the character code: build two 256-entry+	 transition tables, one starting at trtable[0] and one+	 starting at trtable[SBC_MAX].  */+      trtable = state->word_trtable =+	(re_dfastate_t **) calloc (sizeof (re_dfastate_t *), 2 * SBC_MAX);+      if (BE (trtable == NULL, 0))+	goto out_free;++      /* For all characters ch...:  */+      for (i = 0; i < BITSET_WORDS; ++i)+	for (ch = i * BITSET_WORD_BITS, elem = acceptable[i], mask = 1;+	     elem;+	     mask <<= 1, elem >>= 1, ++ch)+	  if (BE (elem & 1, 0))+	    {+	      /* There must be exactly one destination which accepts+		 character ch.  See group_nodes_into_DFAstates.  */+	      for (j = 0; (dests_ch[j][i] & mask) == 0; ++j)+		;++	      /* j-th destination accepts the word character ch.  */+	      trtable[ch] = dest_states[j];+	      trtable[ch + SBC_MAX] = dest_states_word[j];+	    }+    }++  /* new line */+  if (bitset_contain (acceptable, NEWLINE_CHAR))+    {+      /* The current state accepts newline character.  */+      for (j = 0; j < ndests; ++j)+	if (bitset_contain (dests_ch[j], NEWLINE_CHAR))+	  {+	    /* k-th destination accepts newline character.  */+	    trtable[NEWLINE_CHAR] = dest_states_nl[j];+	    if (need_word_trtable)+	      trtable[NEWLINE_CHAR + SBC_MAX] = dest_states_nl[j];+	    /* There must be only one destination which accepts+	       newline.  See group_nodes_into_DFAstates.  */+	    break;+	  }+    }++  if (dest_states_malloced)+    free (dest_states);++  re_node_set_free (&follows);+  for (i = 0; i < ndests; ++i)+    re_node_set_free (dests_node + i);++  if (dests_node_malloced)+    free (dests_alloc);++  return 1;+}++/* Group all nodes belonging to STATE into several destinations.+   Then for all destinations, set the nodes belonging to the destination+   to DESTS_NODE[i] and set the characters accepted by the destination+   to DEST_CH[i].  This function return the number of destinations.  */++static int+internal_function+group_nodes_into_DFAstates (const re_dfa_t *dfa, const re_dfastate_t *state,+			    re_node_set *dests_node, bitset_t *dests_ch)+{+  reg_errcode_t err;+  int result;+  int i, j, k;+  int ndests; /* Number of the destinations from `state'.  */+  bitset_t accepts; /* Characters a node can accept.  */+  const re_node_set *cur_nodes = &state->nodes;+  bitset_empty (accepts);+  ndests = 0;++  /* For all the nodes belonging to `state',  */+  for (i = 0; i < cur_nodes->nelem; ++i)+    {+      re_token_t *node = &dfa->nodes[cur_nodes->elems[i]];+      re_token_type_t type = node->type;+      unsigned int constraint = node->constraint;++      /* Enumerate all single byte character this node can accept.  */+      if (type == CHARACTER)+	bitset_set (accepts, node->opr.c);+      else if (type == SIMPLE_BRACKET)+	{+	  bitset_merge (accepts, node->opr.sbcset);+	}+      else if (type == OP_PERIOD)+	{+#ifdef RE_ENABLE_I18N+	  if (dfa->mb_cur_max > 1)+	    bitset_merge (accepts, dfa->sb_char);+	  else+#endif+	    bitset_set_all (accepts);+	  if (!(dfa->syntax & RE_DOT_NEWLINE))+	    bitset_clear (accepts, '\n');+	  if (dfa->syntax & RE_DOT_NOT_NULL)+	    bitset_clear (accepts, '\0');+	}+#ifdef RE_ENABLE_I18N+      else if (type == OP_UTF8_PERIOD)+        {+	  memset (accepts, '\xff', sizeof (bitset_t) / 2);+	  if (!(dfa->syntax & RE_DOT_NEWLINE))+	    bitset_clear (accepts, '\n');+	  if (dfa->syntax & RE_DOT_NOT_NULL)+	    bitset_clear (accepts, '\0');+        }+#endif+      else+	continue;++      /* Check the `accepts' and sift the characters which are not+	 match it the context.  */+      if (constraint)+	{+	  if (constraint & NEXT_NEWLINE_CONSTRAINT)+	    {+	      bool accepts_newline = bitset_contain (accepts, NEWLINE_CHAR);+	      bitset_empty (accepts);+	      if (accepts_newline)+		bitset_set (accepts, NEWLINE_CHAR);+	      else+		continue;+	    }+	  if (constraint & NEXT_ENDBUF_CONSTRAINT)+	    {+	      bitset_empty (accepts);+	      continue;+	    }++	  if (constraint & NEXT_WORD_CONSTRAINT)+	    {+	      bitset_word_t any_set = 0;+	      if (type == CHARACTER && !node->word_char)+		{+		  bitset_empty (accepts);+		  continue;+		}+#ifdef RE_ENABLE_I18N+	      if (dfa->mb_cur_max > 1)+		for (j = 0; j < BITSET_WORDS; ++j)+		  any_set |= (accepts[j] &= (dfa->word_char[j] | ~dfa->sb_char[j]));+	      else+#endif+		for (j = 0; j < BITSET_WORDS; ++j)+		  any_set |= (accepts[j] &= dfa->word_char[j]);+	      if (!any_set)+		continue;+	    }+	  if (constraint & NEXT_NOTWORD_CONSTRAINT)+	    {+	      bitset_word_t any_set = 0;+	      if (type == CHARACTER && node->word_char)+		{+		  bitset_empty (accepts);+		  continue;+		}+#ifdef RE_ENABLE_I18N+	      if (dfa->mb_cur_max > 1)+		for (j = 0; j < BITSET_WORDS; ++j)+		  any_set |= (accepts[j] &= ~(dfa->word_char[j] & dfa->sb_char[j]));+	      else+#endif+		for (j = 0; j < BITSET_WORDS; ++j)+		  any_set |= (accepts[j] &= ~dfa->word_char[j]);+	      if (!any_set)+		continue;+	    }+	}++      /* Then divide `accepts' into DFA states, or create a new+	 state.  Above, we make sure that accepts is not empty.  */+      for (j = 0; j < ndests; ++j)+	{+	  bitset_t intersec; /* Intersection sets, see below.  */+	  bitset_t remains;+	  /* Flags, see below.  */+	  bitset_word_t has_intersec, not_subset, not_consumed;++	  /* Optimization, skip if this state doesn't accept the character.  */+	  if (type == CHARACTER && !bitset_contain (dests_ch[j], node->opr.c))+	    continue;++	  /* Enumerate the intersection set of this state and `accepts'.  */+	  has_intersec = 0;+	  for (k = 0; k < BITSET_WORDS; ++k)+	    has_intersec |= intersec[k] = accepts[k] & dests_ch[j][k];+	  /* And skip if the intersection set is empty.  */+	  if (!has_intersec)+	    continue;++	  /* Then check if this state is a subset of `accepts'.  */+	  not_subset = not_consumed = 0;+	  for (k = 0; k < BITSET_WORDS; ++k)+	    {+	      not_subset |= remains[k] = ~accepts[k] & dests_ch[j][k];+	      not_consumed |= accepts[k] = accepts[k] & ~dests_ch[j][k];+	    }++	  /* If this state isn't a subset of `accepts', create a+	     new group state, which has the `remains'. */+	  if (not_subset)+	    {+	      bitset_copy (dests_ch[ndests], remains);+	      bitset_copy (dests_ch[j], intersec);+	      err = re_node_set_init_copy (dests_node + ndests, &dests_node[j]);+	      if (BE (err != REG_NOERROR, 0))+		goto error_return;+	      ++ndests;+	    }++	  /* Put the position in the current group. */+	  result = re_node_set_insert (&dests_node[j], cur_nodes->elems[i]);+	  if (BE (result < 0, 0))+	    goto error_return;++	  /* If all characters are consumed, go to next node. */+	  if (!not_consumed)+	    break;+	}+      /* Some characters remain, create a new group. */+      if (j == ndests)+	{+	  bitset_copy (dests_ch[ndests], accepts);+	  err = re_node_set_init_1 (dests_node + ndests, cur_nodes->elems[i]);+	  if (BE (err != REG_NOERROR, 0))+	    goto error_return;+	  ++ndests;+	  bitset_empty (accepts);+	}+    }+  return ndests;+ error_return:+  for (j = 0; j < ndests; ++j)+    re_node_set_free (dests_node + j);+  return -1;+}++#ifdef RE_ENABLE_I18N+/* Check how many bytes the node `dfa->nodes[node_idx]' accepts.+   Return the number of the bytes the node accepts.+   STR_IDX is the current index of the input string.++   This function handles the nodes which can accept one character, or+   one collating element like '.', '[a-z]', opposite to the other nodes+   can only accept one byte.  */++static int+internal_function+check_node_accept_bytes (const re_dfa_t *dfa, int node_idx,+			 const re_string_t *input, int str_idx)+{+  const re_token_t *node = dfa->nodes + node_idx;+  int char_len, elem_len;+  int i;++  if (BE (node->type == OP_UTF8_PERIOD, 0))+    {+      unsigned char c = re_string_byte_at (input, str_idx), d;+      if (BE (c < 0xc2, 1))+	return 0;++      if (str_idx + 2 > input->len)+	return 0;++      d = re_string_byte_at (input, str_idx + 1);+      if (c < 0xe0)+	return (d < 0x80 || d > 0xbf) ? 0 : 2;+      else if (c < 0xf0)+	{+	  char_len = 3;+	  if (c == 0xe0 && d < 0xa0)+	    return 0;+	}+      else if (c < 0xf8)+	{+	  char_len = 4;+	  if (c == 0xf0 && d < 0x90)+	    return 0;+	}+      else if (c < 0xfc)+	{+	  char_len = 5;+	  if (c == 0xf8 && d < 0x88)+	    return 0;+	}+      else if (c < 0xfe)+	{+	  char_len = 6;+	  if (c == 0xfc && d < 0x84)+	    return 0;+	}+      else+	return 0;++      if (str_idx + char_len > input->len)+	return 0;++      for (i = 1; i < char_len; ++i)+	{+	  d = re_string_byte_at (input, str_idx + i);+	  if (d < 0x80 || d > 0xbf)+	    return 0;+	}+      return char_len;+    }++  char_len = re_string_char_size_at (input, str_idx);+  if (node->type == OP_PERIOD)+    {+      if (char_len <= 1)+        return 0;+      /* FIXME: I don't think this if is needed, as both '\n'+	 and '\0' are char_len == 1.  */+      /* '.' accepts any one character except the following two cases.  */+      if ((!(dfa->syntax & RE_DOT_NEWLINE) &&+	   re_string_byte_at (input, str_idx) == '\n') ||+	  ((dfa->syntax & RE_DOT_NOT_NULL) &&+	   re_string_byte_at (input, str_idx) == '\0'))+	return 0;+      return char_len;+    }++  elem_len = re_string_elem_size_at (input, str_idx);+  if ((elem_len <= 1 && char_len <= 1) || char_len == 0)+    return 0;++  if (node->type == COMPLEX_BRACKET)+    {+      const re_charset_t *cset = node->opr.mbcset;+# ifdef _LIBC+      const unsigned char *pin+	= ((const unsigned char *) re_string_get_buffer (input) + str_idx);+      int j;+      uint32_t nrules;+# endif /* _LIBC */+      int match_len = 0;+      wchar_t wc = ((cset->nranges || cset->nchar_classes || cset->nmbchars)+		    ? re_string_wchar_at (input, str_idx) : 0);++      /* match with multibyte character?  */+      for (i = 0; i < cset->nmbchars; ++i)+	if (wc == cset->mbchars[i])+	  {+	    match_len = char_len;+	    goto check_node_accept_bytes_match;+	  }+      /* match with character_class?  */+      for (i = 0; i < cset->nchar_classes; ++i)+	{+	  wctype_t wt = cset->char_classes[i];+	  if (__iswctype (wc, wt))+	    {+	      match_len = char_len;+	      goto check_node_accept_bytes_match;+	    }+	}++# ifdef _LIBC+      nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);+      if (nrules != 0)+	{+	  unsigned int in_collseq = 0;+	  const int32_t *table, *indirect;+	  const unsigned char *weights, *extra;+	  const char *collseqwc;+	  /* This #include defines a local function!  */+#  include <locale/weight.h>++	  /* match with collating_symbol?  */+	  if (cset->ncoll_syms)+	    extra = (const unsigned char *)+	      _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);+	  for (i = 0; i < cset->ncoll_syms; ++i)+	    {+	      const unsigned char *coll_sym = extra + cset->coll_syms[i];+	      /* Compare the length of input collating element and+		 the length of current collating element.  */+	      if (*coll_sym != elem_len)+		continue;+	      /* Compare each bytes.  */+	      for (j = 0; j < *coll_sym; j++)+		if (pin[j] != coll_sym[1 + j])+		  break;+	      if (j == *coll_sym)+		{+		  /* Match if every bytes is equal.  */+		  match_len = j;+		  goto check_node_accept_bytes_match;+		}+	    }++	  if (cset->nranges)+	    {+	      if (elem_len <= char_len)+		{+		  collseqwc = _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQWC);+		  in_collseq = __collseq_table_lookup (collseqwc, wc);+		}+	      else+		in_collseq = find_collation_sequence_value (pin, elem_len);+	    }+	  /* match with range expression?  */+	  for (i = 0; i < cset->nranges; ++i)+	    if (cset->range_starts[i] <= in_collseq+		&& in_collseq <= cset->range_ends[i])+	      {+		match_len = elem_len;+		goto check_node_accept_bytes_match;+	      }++	  /* match with equivalence_class?  */+	  if (cset->nequiv_classes)+	    {+	      const unsigned char *cp = pin;+	      table = (const int32_t *)+		_NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB);+	      weights = (const unsigned char *)+		_NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB);+	      extra = (const unsigned char *)+		_NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB);+	      indirect = (const int32_t *)+		_NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB);+	      int32_t idx = findidx (&cp);+	      if (idx > 0)+		for (i = 0; i < cset->nequiv_classes; ++i)+		  {+		    int32_t equiv_class_idx = cset->equiv_classes[i];+		    size_t weight_len = weights[idx & 0xffffff];+		    if (weight_len == weights[equiv_class_idx & 0xffffff]+			&& (idx >> 24) == (equiv_class_idx >> 24))+		      {+			int cnt = 0;++			idx &= 0xffffff;+			equiv_class_idx &= 0xffffff;++			while (cnt <= weight_len+			       && (weights[equiv_class_idx + 1 + cnt]+				   == weights[idx + 1 + cnt]))+			  ++cnt;+			if (cnt > weight_len)+			  {+			    match_len = elem_len;+			    goto check_node_accept_bytes_match;+			  }+		      }+		  }+	    }+	}+      else+# endif /* _LIBC */+	{+	  /* match with range expression?  */+#if __GNUC__ >= 2+	  wchar_t cmp_buf[] = {L'\0', L'\0', wc, L'\0', L'\0', L'\0'};+#else+	  wchar_t cmp_buf[] = {L'\0', L'\0', L'\0', L'\0', L'\0', L'\0'};+	  cmp_buf[2] = wc;+#endif+	  for (i = 0; i < cset->nranges; ++i)+	    {+	      cmp_buf[0] = cset->range_starts[i];+	      cmp_buf[4] = cset->range_ends[i];+	      if (wcscoll (cmp_buf, cmp_buf + 2) <= 0+		  && wcscoll (cmp_buf + 2, cmp_buf + 4) <= 0)+		{+		  match_len = char_len;+		  goto check_node_accept_bytes_match;+		}+	    }+	}+    check_node_accept_bytes_match:+      if (!cset->non_match)+	return match_len;+      else+	{+	  if (match_len > 0)+	    return 0;+	  else+	    return (elem_len > char_len) ? elem_len : char_len;+	}+    }+  return 0;+}++# ifdef _LIBC+static unsigned int+internal_function+find_collation_sequence_value (const unsigned char *mbs, size_t mbs_len)+{+  uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES);+  if (nrules == 0)+    {+      if (mbs_len == 1)+	{+	  /* No valid character.  Match it as a single byte character.  */+	  const unsigned char *collseq = (const unsigned char *)+	    _NL_CURRENT (LC_COLLATE, _NL_COLLATE_COLLSEQMB);+	  return collseq[mbs[0]];+	}+      return UINT_MAX;+    }+  else+    {+      int32_t idx;+      const unsigned char *extra = (const unsigned char *)+	_NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB);+      int32_t extrasize = (const unsigned char *)+	_NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB + 1) - extra;++      for (idx = 0; idx < extrasize;)+	{+	  int mbs_cnt, found = 0;+	  int32_t elem_mbs_len;+	  /* Skip the name of collating element name.  */+	  idx = idx + extra[idx] + 1;+	  elem_mbs_len = extra[idx++];+	  if (mbs_len == elem_mbs_len)+	    {+	      for (mbs_cnt = 0; mbs_cnt < elem_mbs_len; ++mbs_cnt)+		if (extra[idx + mbs_cnt] != mbs[mbs_cnt])+		  break;+	      if (mbs_cnt == elem_mbs_len)+		/* Found the entry.  */+		found = 1;+	    }+	  /* Skip the byte sequence of the collating element.  */+	  idx += elem_mbs_len;+	  /* Adjust for the alignment.  */+	  idx = (idx + 3) & ~3;+	  /* Skip the collation sequence value.  */+	  idx += sizeof (uint32_t);+	  /* Skip the wide char sequence of the collating element.  */+	  idx = idx + sizeof (uint32_t) * (extra[idx] + 1);+	  /* If we found the entry, return the sequence value.  */+	  if (found)+	    return *(uint32_t *) (extra + idx);+	  /* Skip the collation sequence value.  */+	  idx += sizeof (uint32_t);+	}+      return UINT_MAX;+    }+}+# endif /* _LIBC */+#endif /* RE_ENABLE_I18N */++/* Check whether the node accepts the byte which is IDX-th+   byte of the INPUT.  */++static int+internal_function+check_node_accept (const re_match_context_t *mctx, const re_token_t *node,+		   int idx)+{+  unsigned char ch;+  ch = re_string_byte_at (&mctx->input, idx);+  switch (node->type)+    {+    case CHARACTER:+      if (node->opr.c != ch)+        return 0;+      break;++    case SIMPLE_BRACKET:+      if (!bitset_contain (node->opr.sbcset, ch))+        return 0;+      break;++#ifdef RE_ENABLE_I18N+    case OP_UTF8_PERIOD:+      if (ch >= 0x80)+        return 0;+      /* FALLTHROUGH */+#endif+    case OP_PERIOD:+      if ((ch == '\n' && !(mctx->dfa->syntax & RE_DOT_NEWLINE))+	  || (ch == '\0' && (mctx->dfa->syntax & RE_DOT_NOT_NULL)))+	return 0;+      break;++    default:+      return 0;+    }++  if (node->constraint)+    {+      /* The node has constraints.  Check whether the current context+	 satisfies the constraints.  */+      unsigned int context = re_string_context_at (&mctx->input, idx,+						   mctx->eflags);+      if (NOT_SATISFY_NEXT_CONSTRAINT (node->constraint, context))+	return 0;+    }++  return 1;+}++/* Extend the buffers, if the buffers have run out.  */++static reg_errcode_t+internal_function+extend_buffers (re_match_context_t *mctx)+{+  reg_errcode_t ret;+  re_string_t *pstr = &mctx->input;++  /* Double the lengthes of the buffers.  */+  ret = re_string_realloc_buffers (pstr, pstr->bufs_len * 2);+  if (BE (ret != REG_NOERROR, 0))+    return ret;++  if (mctx->state_log != NULL)+    {+      /* And double the length of state_log.  */+      /* XXX We have no indication of the size of this buffer.  If this+	 allocation fail we have no indication that the state_log array+	 does not have the right size.  */+      re_dfastate_t **new_array = re_realloc (mctx->state_log, re_dfastate_t *,+					      pstr->bufs_len + 1);+      if (BE (new_array == NULL, 0))+	return REG_ESPACE;+      mctx->state_log = new_array;+    }++  /* Then reconstruct the buffers.  */+  if (pstr->icase)+    {+#ifdef RE_ENABLE_I18N+      if (pstr->mb_cur_max > 1)+	{+	  ret = build_wcs_upper_buffer (pstr);+	  if (BE (ret != REG_NOERROR, 0))+	    return ret;+	}+      else+#endif /* RE_ENABLE_I18N  */+	build_upper_buffer (pstr);+    }+  else+    {+#ifdef RE_ENABLE_I18N+      if (pstr->mb_cur_max > 1)+	build_wcs_buffer (pstr);+      else+#endif /* RE_ENABLE_I18N  */+	{+	  if (pstr->trans != NULL)+	    re_string_translate_buffer (pstr);+	}+    }+  return REG_NOERROR;+}+++/* Functions for matching context.  */++/* Initialize MCTX.  */++static reg_errcode_t+internal_function+match_ctx_init (re_match_context_t *mctx, int eflags, int n)+{+  mctx->eflags = eflags;+  mctx->match_last = -1;+  if (n > 0)+    {+      mctx->bkref_ents = re_malloc (struct re_backref_cache_entry, n);+      mctx->sub_tops = re_malloc (re_sub_match_top_t *, n);+      if (BE (mctx->bkref_ents == NULL || mctx->sub_tops == NULL, 0))+	return REG_ESPACE;+    }+  /* Already zero-ed by the caller.+     else+       mctx->bkref_ents = NULL;+     mctx->nbkref_ents = 0;+     mctx->nsub_tops = 0;  */+  mctx->abkref_ents = n;+  mctx->max_mb_elem_len = 1;+  mctx->asub_tops = n;+  return REG_NOERROR;+}++/* Clean the entries which depend on the current input in MCTX.+   This function must be invoked when the matcher changes the start index+   of the input, or changes the input string.  */++static void+internal_function+match_ctx_clean (re_match_context_t *mctx)+{+  int st_idx;+  for (st_idx = 0; st_idx < mctx->nsub_tops; ++st_idx)+    {+      int sl_idx;+      re_sub_match_top_t *top = mctx->sub_tops[st_idx];+      for (sl_idx = 0; sl_idx < top->nlasts; ++sl_idx)+	{+	  re_sub_match_last_t *last = top->lasts[sl_idx];+	  re_free (last->path.array);+	  re_free (last);+	}+      re_free (top->lasts);+      if (top->path)+	{+	  re_free (top->path->array);+	  re_free (top->path);+	}+      free (top);+    }++  mctx->nsub_tops = 0;+  mctx->nbkref_ents = 0;+}++/* Free all the memory associated with MCTX.  */++static void+internal_function+match_ctx_free (re_match_context_t *mctx)+{+  /* First, free all the memory associated with MCTX->SUB_TOPS.  */+  match_ctx_clean (mctx);+  re_free (mctx->sub_tops);+  re_free (mctx->bkref_ents);+}++/* Add a new backreference entry to MCTX.+   Note that we assume that caller never call this function with duplicate+   entry, and call with STR_IDX which isn't smaller than any existing entry.+*/++static reg_errcode_t+internal_function+match_ctx_add_entry (re_match_context_t *mctx, int node, int str_idx, int from,+		     int to)+{+  if (mctx->nbkref_ents >= mctx->abkref_ents)+    {+      struct re_backref_cache_entry* new_entry;+      new_entry = re_realloc (mctx->bkref_ents, struct re_backref_cache_entry,+			      mctx->abkref_ents * 2);+      if (BE (new_entry == NULL, 0))+	{+	  re_free (mctx->bkref_ents);+	  return REG_ESPACE;+	}+      mctx->bkref_ents = new_entry;+      memset (mctx->bkref_ents + mctx->nbkref_ents, '\0',+	      sizeof (struct re_backref_cache_entry) * mctx->abkref_ents);+      mctx->abkref_ents *= 2;+    }+  if (mctx->nbkref_ents > 0+      && mctx->bkref_ents[mctx->nbkref_ents - 1].str_idx == str_idx)+    mctx->bkref_ents[mctx->nbkref_ents - 1].more = 1;++  mctx->bkref_ents[mctx->nbkref_ents].node = node;+  mctx->bkref_ents[mctx->nbkref_ents].str_idx = str_idx;+  mctx->bkref_ents[mctx->nbkref_ents].subexp_from = from;+  mctx->bkref_ents[mctx->nbkref_ents].subexp_to = to;++  /* This is a cache that saves negative results of check_dst_limits_calc_pos.+     If bit N is clear, means that this entry won't epsilon-transition to+     an OP_OPEN_SUBEXP or OP_CLOSE_SUBEXP for the N+1-th subexpression.  If+     it is set, check_dst_limits_calc_pos_1 will recurse and try to find one+     such node.++     A backreference does not epsilon-transition unless it is empty, so set+     to all zeros if FROM != TO.  */+  mctx->bkref_ents[mctx->nbkref_ents].eps_reachable_subexps_map+    = (from == to ? ~0 : 0);++  mctx->bkref_ents[mctx->nbkref_ents++].more = 0;+  if (mctx->max_mb_elem_len < to - from)+    mctx->max_mb_elem_len = to - from;+  return REG_NOERROR;+}++/* Search for the first entry which has the same str_idx, or -1 if none is+   found.  Note that MCTX->BKREF_ENTS is already sorted by MCTX->STR_IDX.  */++static int+internal_function+search_cur_bkref_entry (const re_match_context_t *mctx, int str_idx)+{+  int left, right, mid, last;+  last = right = mctx->nbkref_ents;+  for (left = 0; left < right;)+    {+      mid = (left + right) / 2;+      if (mctx->bkref_ents[mid].str_idx < str_idx)+	left = mid + 1;+      else+	right = mid;+    }+  if (left < last && mctx->bkref_ents[left].str_idx == str_idx)+    return left;+  else+    return -1;+}++/* Register the node NODE, whose type is OP_OPEN_SUBEXP, and which matches+   at STR_IDX.  */++static reg_errcode_t+internal_function+match_ctx_add_subtop (re_match_context_t *mctx, int node, int str_idx)+{+#ifdef DEBUG+  assert (mctx->sub_tops != NULL);+  assert (mctx->asub_tops > 0);+#endif+  if (BE (mctx->nsub_tops == mctx->asub_tops, 0))+    {+      int new_asub_tops = mctx->asub_tops * 2;+      re_sub_match_top_t **new_array = re_realloc (mctx->sub_tops,+						   re_sub_match_top_t *,+						   new_asub_tops);+      if (BE (new_array == NULL, 0))+	return REG_ESPACE;+      mctx->sub_tops = new_array;+      mctx->asub_tops = new_asub_tops;+    }+  mctx->sub_tops[mctx->nsub_tops] = calloc (1, sizeof (re_sub_match_top_t));+  if (BE (mctx->sub_tops[mctx->nsub_tops] == NULL, 0))+    return REG_ESPACE;+  mctx->sub_tops[mctx->nsub_tops]->node = node;+  mctx->sub_tops[mctx->nsub_tops++]->str_idx = str_idx;+  return REG_NOERROR;+}++/* Register the node NODE, whose type is OP_CLOSE_SUBEXP, and which matches+   at STR_IDX, whose corresponding OP_OPEN_SUBEXP is SUB_TOP.  */++static re_sub_match_last_t *+internal_function+match_ctx_add_sublast (re_sub_match_top_t *subtop, int node, int str_idx)+{+  re_sub_match_last_t *new_entry;+  if (BE (subtop->nlasts == subtop->alasts, 0))+    {+      int new_alasts = 2 * subtop->alasts + 1;+      re_sub_match_last_t **new_array = re_realloc (subtop->lasts,+						    re_sub_match_last_t *,+						    new_alasts);+      if (BE (new_array == NULL, 0))+	return NULL;+      subtop->lasts = new_array;+      subtop->alasts = new_alasts;+    }+  new_entry = calloc (1, sizeof (re_sub_match_last_t));+  if (BE (new_entry != NULL, 1))+    {+      subtop->lasts[subtop->nlasts] = new_entry;+      new_entry->node = node;+      new_entry->str_idx = str_idx;+      ++subtop->nlasts;+    }+  return new_entry;+}++static void+internal_function+sift_ctx_init (re_sift_context_t *sctx, re_dfastate_t **sifted_sts,+	       re_dfastate_t **limited_sts, int last_node, int last_str_idx)+{+  sctx->sifted_states = sifted_sts;+  sctx->limited_states = limited_sts;+  sctx->last_node = last_node;+  sctx->last_str_idx = last_str_idx;+  re_node_set_init_empty (&sctx->limits);+}
+ regex-posix-clib.cabal view
@@ -0,0 +1,39 @@+cabal-version:          1.12+name:                   regex-posix-clib+version:                2.7++build-type:             Simple+license:                LGPL-2.1+license-file:           LICENSE+maintainer:             hvr@gnu.org+bug-reports:            https://github.com/hvr/regex-posix+synopsis:               "Regex for Windows" C library+category:               Text+description:+  This CABAL package provides the <http://gnuwin32.sourceforge.net/packages/regex.htm Regex for Windows> C library for convenience on operating systems lacking a <https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/regex.h.html POSIX.2 regex> implementation.++extra-source-files:+  cbits/re_comp.h+  cbits/regcomp.c+  cbits/regex.c+  cbits/regex.h+  cbits/regex_internal.c+  cbits/regex_internal.h+  cbits/regexec.c++source-repository head+  type:     git+  location: https://github.com/hvr/regex-posix.git+  branch:   clib/master++library+  c-sources:        cbits/regex.c+  cc-options:       -O3+                    -U_LIBC -UDEBUG+                    -UHAVE_CONFIG_H+                    -DHAVE_STDBOOL_H+                    -DHAVE_STDINT_H+  include-dirs:     cbits+  install-includes: regex.h re_comp.h++  default-language: Haskell2010